mirror of
https://github.com/russok/FitoTrack.git
synced 2025-10-29 08:42:12 -07:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be3ce4f1c3 | ||
|
|
d372e5ffff | ||
|
|
428256294a | ||
|
|
e69f40553a | ||
|
|
0d84407165 | ||
|
|
72650fefb4 | ||
|
|
815cd764c1 | ||
|
|
e0c3a860b2 | ||
|
|
32724a58f2 | ||
|
|
6cf233a5ea | ||
|
|
5adc2a0536 | ||
|
|
4a89e95b41 | ||
|
|
16c42ec350 | ||
|
|
3f7d590ded | ||
|
|
289e25949f | ||
|
|
8665d5ca14 | ||
|
|
e6ab3ab871 | ||
|
|
4a27bdba26 | ||
|
|
62570fed27 | ||
|
|
a336015818 | ||
|
|
3d930cc49e | ||
|
|
fe181b5fe4 | ||
|
|
3a22c97018 | ||
|
|
bf6c5d0923 | ||
|
|
a26d6a748b | ||
|
|
1ed129778b | ||
|
|
e978e8f6c2 | ||
|
|
e5f3f9f0f7 | ||
|
|
91d97ae805 | ||
|
|
5f84e57bf3 |
13
.gitignore
vendored
13
.gitignore
vendored
@ -1,8 +1,3 @@
|
|||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
/node_modules
|
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
/coverage
|
/coverage
|
||||||
|
|
||||||
@ -13,7 +8,11 @@
|
|||||||
|
|
||||||
# misc
|
# misc
|
||||||
.*
|
.*
|
||||||
*.properties
|
|
||||||
*.iml
|
|
||||||
!.gitignore
|
!.gitignore
|
||||||
|
|
||||||
|
# idea
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
# gradle
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
|||||||
24
NOTICE.md
24
NOTICE.md
@ -49,6 +49,30 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
|
<https://github.com/vectorstofinal/geoid_heights>
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 vectorstofinal
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
<https://github.com/westnordost/osmapi>
|
<https://github.com/westnordost/osmapi>
|
||||||
|
|
||||||
© 2016-2019 Tobias Zwick. This library is released under the terms of the GNU Lesser General Public License (LGPL).
|
© 2016-2019 Tobias Zwick. This library is released under the terms of the GNU Lesser General Public License (LGPL).
|
||||||
|
|||||||
@ -20,7 +20,7 @@ FitoTrack is a mobile app for logging and viewing your workouts. Whether you're
|
|||||||
- **View your workouts.** View general information such as date, time, duration, distance, speed and pace. See your route on a map. Work out your level of performance from the speed diagram.
|
- **View your workouts.** View general information such as date, time, duration, distance, speed and pace. See your route on a map. Work out your level of performance from the speed diagram.
|
||||||
- **Open-Source.** There is neither advertivesment nor tracking, and the source code is open and licensed under the GPLv3.
|
- **Open-Source.** There is neither advertivesment nor tracking, and the source code is open and licensed under the GPLv3.
|
||||||
|
|
||||||
please see the [Userguide](https://codeberg.org/jannis/FitoTrack/wiki/How-to-use) if you have any problems and the [Roadmap](https://codeberg.org/jannis/FitoTrack/wiki/Roadmap) for planned features.
|
Please see the [Userguide](https://codeberg.org/jannis/FitoTrack/wiki/How-to-use) if you have any problems.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|||||||
@ -35,8 +35,8 @@ android {
|
|||||||
applicationId "de.tadris.fitness"
|
applicationId "de.tadris.fitness"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 420
|
versionCode 500
|
||||||
versionName "4.2"
|
versionName "5.0"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@ -73,7 +73,7 @@ dependencies {
|
|||||||
implementation 'org.mapsforge:mapsforge-map-android:0.11.0'
|
implementation 'org.mapsforge:mapsforge-map-android:0.11.0'
|
||||||
implementation 'com.caverock:androidsvg:1.3'
|
implementation 'com.caverock:androidsvg:1.3'
|
||||||
|
|
||||||
// Charts
|
// UI
|
||||||
implementation 'net.sf.kxml:kxml2:2.3.0'
|
implementation 'net.sf.kxml:kxml2:2.3.0'
|
||||||
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
|
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
|
||||||
implementation 'com.github.clans:fab:1.6.4'
|
implementation 'com.github.clans:fab:1.6.4'
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
package="de.tadris.fitness">
|
package="de.tadris.fitness">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
@ -39,19 +40,21 @@
|
|||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
tools:ignore="GoogleAppIndexingWarning">
|
tools:ignore="GoogleAppIndexingWarning">
|
||||||
<activity android:name=".activity.VoiceAnnouncementsSettingsActivity"></activity>
|
<activity android:name=".activity.VoiceAnnouncementsSettingsActivity" />
|
||||||
|
<activity android:name=".activity.SettingsActivity" />
|
||||||
|
<activity android:name=".activity.EnterWorkoutActivity"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.ShowWorkoutMapActivity"
|
android:name=".activity.ShowWorkoutMapActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.ShowWorkoutMapDiagramActivity"
|
android:name=".activity.ShowWorkoutMapDiagramActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
<activity android:name=".activity.SettingsActivity" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.ShowWorkoutActivity"
|
android:name=".activity.ShowWorkoutActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.RecordWorkoutActivity"
|
android:name=".activity.RecordWorkoutActivity"
|
||||||
|
android:showOnLockScreen="true"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.ListWorkoutsActivity"
|
android:name=".activity.ListWorkoutsActivity"
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import java.util.List;
|
|||||||
import de.tadris.fitness.data.AppDatabase;
|
import de.tadris.fitness.data.AppDatabase;
|
||||||
import de.tadris.fitness.data.UserPreferences;
|
import de.tadris.fitness.data.UserPreferences;
|
||||||
import de.tadris.fitness.recording.LocationListener;
|
import de.tadris.fitness.recording.LocationListener;
|
||||||
|
import de.tadris.fitness.util.FitoTrackThemes;
|
||||||
import de.tadris.fitness.util.unit.UnitUtils;
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
|
|
||||||
public class Instance {
|
public class Instance {
|
||||||
@ -50,17 +51,19 @@ public class Instance {
|
|||||||
public final AppDatabase db;
|
public final AppDatabase db;
|
||||||
public final List<LocationListener.LocationChangeListener> locationChangeListeners = new ArrayList<>();
|
public final List<LocationListener.LocationChangeListener> locationChangeListeners = new ArrayList<>();
|
||||||
public final UserPreferences userPreferences;
|
public final UserPreferences userPreferences;
|
||||||
|
public final FitoTrackThemes themes;
|
||||||
|
|
||||||
public boolean pressureAvailable= false;
|
public boolean pressureAvailable= false;
|
||||||
public float lastPressure= 0;
|
public float lastPressure= 0;
|
||||||
|
|
||||||
private Instance(Context context) {
|
private Instance(Context context) {
|
||||||
userPreferences= new UserPreferences(context);
|
userPreferences= new UserPreferences(context);
|
||||||
|
themes = new FitoTrackThemes(context);
|
||||||
db = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME)
|
db = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME)
|
||||||
.addMigrations(new Migration(1, 2) {
|
.addMigrations(new Migration(1, 2) {
|
||||||
@Override
|
@Override
|
||||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||||
try{
|
try {
|
||||||
database.beginTransaction();
|
database.beginTransaction();
|
||||||
|
|
||||||
database.execSQL("ALTER table workout add descent REAL NOT NULL DEFAULT 0;");
|
database.execSQL("ALTER table workout add descent REAL NOT NULL DEFAULT 0;");
|
||||||
@ -85,7 +88,20 @@ public class Instance {
|
|||||||
database.execSQL("DROP TABLE workout_sample2");
|
database.execSQL("DROP TABLE workout_sample2");
|
||||||
|
|
||||||
database.setTransactionSuccessful();
|
database.setTransactionSuccessful();
|
||||||
}finally {
|
} finally {
|
||||||
|
database.endTransaction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, new Migration(2, 3) {
|
||||||
|
@Override
|
||||||
|
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||||
|
try {
|
||||||
|
database.beginTransaction();
|
||||||
|
|
||||||
|
database.execSQL("ALTER table workout add COLUMN edited INTEGER not null default 0");
|
||||||
|
|
||||||
|
database.setTransactionSuccessful();
|
||||||
|
} finally {
|
||||||
database.endTransaction();
|
database.endTransaction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,221 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.activity;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.InputType;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
import de.tadris.fitness.data.WorkoutBuilder;
|
||||||
|
import de.tadris.fitness.data.WorkoutType;
|
||||||
|
import de.tadris.fitness.dialog.DatePickerFragment;
|
||||||
|
import de.tadris.fitness.dialog.DurationPickerDialogFragment;
|
||||||
|
import de.tadris.fitness.dialog.SelectWorkoutTypeDialog;
|
||||||
|
import de.tadris.fitness.dialog.TimePickerFragment;
|
||||||
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
|
|
||||||
|
public class EnterWorkoutActivity extends InformationActivity implements SelectWorkoutTypeDialog.WorkoutTypeSelectListener, DatePickerFragment.DatePickerCallback, TimePickerFragment.TimePickerCallback, DurationPickerDialogFragment.DurationPickListener {
|
||||||
|
|
||||||
|
WorkoutBuilder workoutBuilder = new WorkoutBuilder();
|
||||||
|
TextView typeTextView, dateTextView, timeTextView, durationTextView;
|
||||||
|
EditText distanceEditText, commentEditText;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_enter_workout);
|
||||||
|
|
||||||
|
initRoot();
|
||||||
|
|
||||||
|
addTitle(getString(R.string.info));
|
||||||
|
setupActionBar();
|
||||||
|
|
||||||
|
KeyValueLine typeLine = addKeyValueLine(getString(R.string.type));
|
||||||
|
typeTextView = typeLine.value;
|
||||||
|
typeLine.lineRoot.setOnClickListener(v -> showTypeSelection());
|
||||||
|
|
||||||
|
distanceEditText = new EditText(this);
|
||||||
|
distanceEditText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
||||||
|
distanceEditText.setSingleLine(true);
|
||||||
|
distanceEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
|
||||||
|
distanceEditText.setOnEditorActionListener((v, actionId, event) -> {
|
||||||
|
// If the User clicks on the finish button on the keyboard, continue by showing the date selection
|
||||||
|
if (actionId == EditorInfo.IME_ACTION_SEARCH ||
|
||||||
|
actionId == EditorInfo.IME_ACTION_DONE ||
|
||||||
|
event != null &&
|
||||||
|
event.getAction() == KeyEvent.ACTION_DOWN &&
|
||||||
|
event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
|
||||||
|
if (event == null || !event.isShiftPressed()) {
|
||||||
|
showDateSelection();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
addKeyValueLine(getString(R.string.workoutDistance), distanceEditText, UnitUtils.CHOSEN_SYSTEM.getLongDistanceUnit());
|
||||||
|
|
||||||
|
|
||||||
|
KeyValueLine dateLine = addKeyValueLine(getString(R.string.workoutDate));
|
||||||
|
dateLine.lineRoot.setOnClickListener(v -> showDateSelection());
|
||||||
|
dateTextView = dateLine.value;
|
||||||
|
|
||||||
|
KeyValueLine timeLine = addKeyValueLine(getString(R.string.workoutStartTime));
|
||||||
|
timeLine.lineRoot.setOnClickListener(v -> showTimeSelection());
|
||||||
|
timeTextView = timeLine.value;
|
||||||
|
|
||||||
|
KeyValueLine durationLine = addKeyValueLine(getString(R.string.workoutDuration));
|
||||||
|
durationLine.lineRoot.setOnClickListener(v -> showDurationSelection());
|
||||||
|
durationTextView = durationLine.value;
|
||||||
|
|
||||||
|
addTitle(getString(R.string.comment));
|
||||||
|
|
||||||
|
commentEditText = new EditText(this);
|
||||||
|
commentEditText.setSingleLine(true);
|
||||||
|
root.addView(commentEditText);
|
||||||
|
|
||||||
|
updateTextViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveWorkout() {
|
||||||
|
workoutBuilder.setComment(commentEditText.getText().toString());
|
||||||
|
try {
|
||||||
|
workoutBuilder.setLength((int) (Double.parseDouble(distanceEditText.getText().toString()) * 1000));
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
distanceEditText.requestFocus();
|
||||||
|
distanceEditText.setError(getString(R.string.errorEnterValidNumber));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (workoutBuilder.getStart().getTimeInMillis() > System.currentTimeMillis()) {
|
||||||
|
Toast.makeText(this, R.string.errorWorkoutAddFuture, Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (workoutBuilder.getDuration() < 1000) {
|
||||||
|
Toast.makeText(this, R.string.errorEnterValidDuration, Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ShowWorkoutActivity.selectedWorkout = workoutBuilder.insertWorkout(this);
|
||||||
|
startActivity(new Intent(this, ShowWorkoutActivity.class));
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTextViews() {
|
||||||
|
typeTextView.setText(getString(workoutBuilder.getWorkoutType().title));
|
||||||
|
dateTextView.setText(SimpleDateFormat.getDateInstance().format(workoutBuilder.getStart().getTime()));
|
||||||
|
timeTextView.setText(SimpleDateFormat.getTimeInstance().format(workoutBuilder.getStart().getTime()));
|
||||||
|
durationTextView.setText(UnitUtils.getHourMinuteSecondTime(workoutBuilder.getDuration()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showTypeSelection() {
|
||||||
|
new SelectWorkoutTypeDialog(this, this).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSelectWorkoutType(WorkoutType workoutType) {
|
||||||
|
workoutBuilder.setWorkoutType(workoutType);
|
||||||
|
updateTextViews();
|
||||||
|
distanceEditText.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showDateSelection() {
|
||||||
|
DatePickerFragment fragment = new DatePickerFragment();
|
||||||
|
fragment.callback = this;
|
||||||
|
fragment.show(getFragmentManager(), "datePicker");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDatePick(int year, int month, int day) {
|
||||||
|
workoutBuilder.getStart().set(year, month, day);
|
||||||
|
updateTextViews();
|
||||||
|
showTimeSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showTimeSelection() {
|
||||||
|
TimePickerFragment fragment = new TimePickerFragment();
|
||||||
|
fragment.callback = this;
|
||||||
|
fragment.show(getFragmentManager(), "timePicker");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTimePick(int hour, int minute) {
|
||||||
|
workoutBuilder.getStart().set(Calendar.HOUR_OF_DAY, hour);
|
||||||
|
workoutBuilder.getStart().set(Calendar.MINUTE, minute);
|
||||||
|
workoutBuilder.getStart().set(Calendar.SECOND, 0);
|
||||||
|
updateTextViews();
|
||||||
|
showDurationSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showDurationSelection() {
|
||||||
|
DurationPickerDialogFragment fragment = new DurationPickerDialogFragment(this, this, workoutBuilder.getDuration());
|
||||||
|
fragment.listener = this;
|
||||||
|
fragment.initialDuration = workoutBuilder.getDuration();
|
||||||
|
fragment.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDurationPick(long duration) {
|
||||||
|
workoutBuilder.setDuration(duration);
|
||||||
|
updateTextViews();
|
||||||
|
commentEditText.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
|
getMenuInflater().inflate(R.menu.enter_workout_menu, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
int id = item.getItemId();
|
||||||
|
switch (id) {
|
||||||
|
case R.id.actionEnterWorkoutAdd:
|
||||||
|
saveWorkout();
|
||||||
|
return true;
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupActionBar() {
|
||||||
|
if (getActionBar() != null) {
|
||||||
|
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void initRoot() {
|
||||||
|
root = findViewById(R.id.enterWorkoutRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,15 +23,23 @@ import android.Manifest;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
|
|
||||||
|
import de.tadris.fitness.Instance;
|
||||||
import de.tadris.fitness.R;
|
import de.tadris.fitness.R;
|
||||||
|
|
||||||
abstract public class FitoTrackActivity extends Activity {
|
abstract public class FitoTrackActivity extends Activity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setTheme(Instance.getInstance(this).themes.getDefaultTheme());
|
||||||
|
}
|
||||||
|
|
||||||
int getThemePrimaryColor() {
|
int getThemePrimaryColor() {
|
||||||
final TypedValue value = new TypedValue ();
|
final TypedValue value = new TypedValue ();
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import android.app.AlertDialog;
|
|||||||
import android.media.Ringtone;
|
import android.media.Ringtone;
|
||||||
import android.media.RingtoneManager;
|
import android.media.RingtoneManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
@ -31,13 +32,21 @@ import android.preference.RingtonePreference;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
|
import de.tadris.fitness.Instance;
|
||||||
import de.tadris.fitness.R;
|
import de.tadris.fitness.R;
|
||||||
import de.tadris.fitness.util.unit.UnitUtils;
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
|
|
||||||
public abstract class FitoTrackSettingsActivity extends PreferenceActivity {
|
public abstract class FitoTrackSettingsActivity extends PreferenceActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
setTheme(Instance.getInstance(this).themes.getDefaultTheme());
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
protected void showErrorDialog(Exception e, @StringRes int title, @StringRes int message) {
|
protected void showErrorDialog(Exception e, @StringRes int title, @StringRes int message) {
|
||||||
new AlertDialog.Builder(this)
|
new AlertDialog.Builder(this)
|
||||||
.setTitle(title)
|
.setTitle(title)
|
||||||
|
|||||||
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.activity;
|
||||||
|
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
|
||||||
|
public abstract class InformationActivity extends FitoTrackActivity {
|
||||||
|
|
||||||
|
ViewGroup root;
|
||||||
|
|
||||||
|
protected void addTitle(String title) {
|
||||||
|
TextView textView = new TextView(this);
|
||||||
|
textView.setText(title);
|
||||||
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
||||||
|
textView.setTextColor(getThemePrimaryColor());
|
||||||
|
textView.setTypeface(Typeface.DEFAULT_BOLD);
|
||||||
|
textView.setAllCaps(true);
|
||||||
|
textView.setPadding(0, 20, 0, 0);
|
||||||
|
|
||||||
|
root.addView(textView);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TextView addText(String text, boolean themeColor) {
|
||||||
|
TextView textView = createTextView(text, themeColor);
|
||||||
|
root.addView(textView);
|
||||||
|
|
||||||
|
return textView;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TextView createTextView(String text) {
|
||||||
|
return createTextView(text, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TextView createTextView(String text, boolean themeColor) {
|
||||||
|
TextView textView = new TextView(this);
|
||||||
|
textView.setText(text);
|
||||||
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
||||||
|
if (themeColor) {
|
||||||
|
textView.setTextColor(getThemePrimaryColor());
|
||||||
|
} else {
|
||||||
|
textView.setTextColor(getResources().getColor(R.color.textLighterBlack));
|
||||||
|
}
|
||||||
|
textView.setPadding(0, 20, 0, 0);
|
||||||
|
|
||||||
|
return textView;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addKeyValue(String key1, String value1) {
|
||||||
|
addKeyValue(key1, value1, "", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addKeyValue(String key1, String value1, String key2, String value2) {
|
||||||
|
View v = getLayoutInflater().inflate(R.layout.show_entry, root, false);
|
||||||
|
|
||||||
|
TextView title1 = v.findViewById(R.id.v1title);
|
||||||
|
TextView title2 = v.findViewById(R.id.v2title);
|
||||||
|
TextView v1 = v.findViewById(R.id.v1value);
|
||||||
|
TextView v2 = v.findViewById(R.id.v2value);
|
||||||
|
|
||||||
|
title1.setText(key1);
|
||||||
|
title2.setText(key2);
|
||||||
|
v1.setText(value1);
|
||||||
|
v2.setText(value2);
|
||||||
|
|
||||||
|
root.addView(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected KeyValueLine addKeyValueLine(String key) {
|
||||||
|
return addKeyValueLine(key, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected KeyValueLine addKeyValueLine(String key, String value) {
|
||||||
|
return addKeyValueLine(key, null, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected KeyValueLine addKeyValueLine(String key, @Nullable View view) {
|
||||||
|
return addKeyValueLine(key, view, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected KeyValueLine addKeyValueLine(String key, @Nullable View view, String value) {
|
||||||
|
View v = getLayoutInflater().inflate(R.layout.enter_workout_line, root, false);
|
||||||
|
|
||||||
|
TextView keyView = v.findViewById(R.id.lineKey);
|
||||||
|
TextView valueView = v.findViewById(R.id.lineValue);
|
||||||
|
LinearLayout customViewRoot = v.findViewById(R.id.lineViewRoot);
|
||||||
|
|
||||||
|
keyView.setText(key);
|
||||||
|
valueView.setText(value);
|
||||||
|
|
||||||
|
if (view != null) {
|
||||||
|
customViewRoot.addView(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
root.addView(v);
|
||||||
|
return new KeyValueLine(v, keyView, valueView, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class KeyValueLine {
|
||||||
|
public View lineRoot;
|
||||||
|
public TextView key;
|
||||||
|
public TextView value;
|
||||||
|
public View customView;
|
||||||
|
|
||||||
|
public KeyValueLine(View lineRoot, TextView key, TextView value, View customView) {
|
||||||
|
this.lineRoot = lineRoot;
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
this.customView = customView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract void initRoot();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package de.tadris.fitness.activity;
|
package de.tadris.fitness.activity;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
@ -37,10 +36,11 @@ import com.github.clans.fab.FloatingActionMenu;
|
|||||||
import de.tadris.fitness.Instance;
|
import de.tadris.fitness.Instance;
|
||||||
import de.tadris.fitness.R;
|
import de.tadris.fitness.R;
|
||||||
import de.tadris.fitness.data.Workout;
|
import de.tadris.fitness.data.Workout;
|
||||||
|
import de.tadris.fitness.data.WorkoutType;
|
||||||
import de.tadris.fitness.util.DialogUtils;
|
import de.tadris.fitness.util.DialogUtils;
|
||||||
import de.tadris.fitness.view.WorkoutAdapter;
|
import de.tadris.fitness.view.WorkoutAdapter;
|
||||||
|
|
||||||
public class ListWorkoutsActivity extends Activity implements WorkoutAdapter.WorkoutAdapterListener {
|
public class ListWorkoutsActivity extends FitoTrackActivity implements WorkoutAdapter.WorkoutAdapterListener {
|
||||||
|
|
||||||
private RecyclerView listView;
|
private RecyclerView listView;
|
||||||
private RecyclerView.Adapter adapter;
|
private RecyclerView.Adapter adapter;
|
||||||
@ -63,16 +63,17 @@ public class ListWorkoutsActivity extends Activity implements WorkoutAdapter.Wor
|
|||||||
menu= findViewById(R.id.workoutListMenu);
|
menu= findViewById(R.id.workoutListMenu);
|
||||||
menu.setOnMenuButtonLongClickListener(v -> {
|
menu.setOnMenuButtonLongClickListener(v -> {
|
||||||
if(workouts.length > 0){
|
if(workouts.length > 0){
|
||||||
startRecording(workouts[0].workoutType);
|
startRecording(workouts[0].getWorkoutType());
|
||||||
return true;
|
return true;
|
||||||
}else{
|
}else{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
findViewById(R.id.workoutListRecordRunning).setOnClickListener(v -> startRecording(Workout.WORKOUT_TYPE_RUNNING));
|
findViewById(R.id.workoutListRecordRunning).setOnClickListener(v -> startRecording(WorkoutType.RUNNING));
|
||||||
findViewById(R.id.workoutListRecordHiking) .setOnClickListener(v -> startRecording(Workout.WORKOUT_TYPE_HIKING));
|
findViewById(R.id.workoutListRecordHiking).setOnClickListener(v -> startRecording(WorkoutType.HIKING));
|
||||||
findViewById(R.id.workoutListRecordCycling).setOnClickListener(v -> startRecording(Workout.WORKOUT_TYPE_CYCLING));
|
findViewById(R.id.workoutListRecordCycling).setOnClickListener(v -> startRecording(WorkoutType.CYCLING));
|
||||||
|
findViewById(R.id.workoutListEnter).setOnClickListener(v -> startEnterWorkoutActivity());
|
||||||
|
|
||||||
checkFirstStart();
|
checkFirstStart();
|
||||||
|
|
||||||
@ -92,7 +93,13 @@ public class ListWorkoutsActivity extends Activity implements WorkoutAdapter.Wor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startRecording(String activity) {
|
private void startEnterWorkoutActivity() {
|
||||||
|
menu.close(true);
|
||||||
|
final Intent intent = new Intent(this, EnterWorkoutActivity.class);
|
||||||
|
new Handler().postDelayed(() -> startActivity(intent), 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startRecording(WorkoutType activity) {
|
||||||
menu.close(true);
|
menu.close(true);
|
||||||
RecordWorkoutActivity.ACTIVITY= activity;
|
RecordWorkoutActivity.ACTIVITY= activity;
|
||||||
final Intent intent= new Intent(this, RecordWorkoutActivity.class);
|
final Intent intent= new Intent(this, RecordWorkoutActivity.class);
|
||||||
|
|||||||
@ -35,6 +35,7 @@ import android.view.Menu;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@ -53,20 +54,18 @@ import java.util.List;
|
|||||||
|
|
||||||
import de.tadris.fitness.Instance;
|
import de.tadris.fitness.Instance;
|
||||||
import de.tadris.fitness.R;
|
import de.tadris.fitness.R;
|
||||||
import de.tadris.fitness.announcement.AnnouncementGPSStatus;
|
import de.tadris.fitness.data.WorkoutType;
|
||||||
import de.tadris.fitness.announcement.VoiceAnnouncements;
|
|
||||||
import de.tadris.fitness.data.Workout;
|
|
||||||
import de.tadris.fitness.map.MapManager;
|
import de.tadris.fitness.map.MapManager;
|
||||||
import de.tadris.fitness.map.tilesource.TileSources;
|
|
||||||
import de.tadris.fitness.recording.LocationListener;
|
import de.tadris.fitness.recording.LocationListener;
|
||||||
import de.tadris.fitness.recording.PressureService;
|
import de.tadris.fitness.recording.PressureService;
|
||||||
import de.tadris.fitness.recording.WorkoutRecorder;
|
import de.tadris.fitness.recording.WorkoutRecorder;
|
||||||
import de.tadris.fitness.util.ThemeManager;
|
import de.tadris.fitness.recording.announcement.AnnouncementGPSStatus;
|
||||||
|
import de.tadris.fitness.recording.announcement.VoiceAnnouncements;
|
||||||
import de.tadris.fitness.util.unit.UnitUtils;
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
|
|
||||||
public class RecordWorkoutActivity extends FitoTrackActivity implements LocationListener.LocationChangeListener, WorkoutRecorder.WorkoutRecorderListener, VoiceAnnouncements.VoiceAnnouncementCallback {
|
public class RecordWorkoutActivity extends FitoTrackActivity implements LocationListener.LocationChangeListener, WorkoutRecorder.WorkoutRecorderListener, VoiceAnnouncements.VoiceAnnouncementCallback {
|
||||||
|
|
||||||
public static String ACTIVITY= Workout.WORKOUT_TYPE_RUNNING;
|
public static WorkoutType ACTIVITY = WorkoutType.OTHER;
|
||||||
|
|
||||||
private MapView mapView;
|
private MapView mapView;
|
||||||
private TileDownloadLayer downloadLayer;
|
private TileDownloadLayer downloadLayer;
|
||||||
@ -76,6 +75,7 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
|
|||||||
private final InfoViewHolder[] infoViews = new InfoViewHolder[4];
|
private final InfoViewHolder[] infoViews = new InfoViewHolder[4];
|
||||||
private TextView timeView;
|
private TextView timeView;
|
||||||
private TextView gpsStatusView;
|
private TextView gpsStatusView;
|
||||||
|
private TextView attribution;
|
||||||
private View waitingForGPSOverlay;
|
private View waitingForGPSOverlay;
|
||||||
private boolean gpsFound = false;
|
private boolean gpsFound = false;
|
||||||
private boolean isResumed = false;
|
private boolean isResumed = false;
|
||||||
@ -90,7 +90,7 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setTheme(ThemeManager.getThemeByWorkoutType(ACTIVITY));
|
setTheme(Instance.getInstance(this).themes.getWorkoutTypeTheme(ACTIVITY));
|
||||||
setContentView(R.layout.activity_record_workout);
|
setContentView(R.layout.activity_record_workout);
|
||||||
|
|
||||||
setTitle(R.string.recordWorkout);
|
setTitle(R.string.recordWorkout);
|
||||||
@ -101,6 +101,8 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
|
|||||||
waitingForGPSOverlay= findViewById(R.id.recorderWaitingOverlay);
|
waitingForGPSOverlay= findViewById(R.id.recorderWaitingOverlay);
|
||||||
waitingForGPSOverlay.setVisibility(View.VISIBLE);
|
waitingForGPSOverlay.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
attribution = findViewById(R.id.recordMapAttribution);
|
||||||
|
|
||||||
checkPermissions();
|
checkPermissions();
|
||||||
|
|
||||||
recorder= new WorkoutRecorder(this, ACTIVITY, this);
|
recorder= new WorkoutRecorder(this, ACTIVITY, this);
|
||||||
@ -136,7 +138,9 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
|
|||||||
waitingForGPSOverlay.clearAnimation();
|
waitingForGPSOverlay.clearAnimation();
|
||||||
waitingForGPSOverlay.animate().alpha(0f).setDuration(1000).setListener(new Animator.AnimatorListener() {
|
waitingForGPSOverlay.animate().alpha(0f).setDuration(1000).setListener(new Animator.AnimatorListener() {
|
||||||
@Override public void onAnimationStart(Animator animator) { }
|
@Override public void onAnimationStart(Animator animator) { }
|
||||||
|
|
||||||
@Override public void onAnimationCancel(Animator animator) { }
|
@Override public void onAnimationCancel(Animator animator) { }
|
||||||
|
|
||||||
@Override public void onAnimationRepeat(Animator animator) { }
|
@Override public void onAnimationRepeat(Animator animator) { }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -144,17 +148,16 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
|
|||||||
waitingForGPSOverlay.setVisibility(View.GONE);
|
waitingForGPSOverlay.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
|
hideOSMAttribution();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hideOSMAttribution() {
|
||||||
|
attribution.animate().alpha(0f).setDuration(1000).setStartDelay(5000).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupMap(){
|
private void setupMap(){
|
||||||
this.mapView= new MapView(this);
|
this.mapView= new MapView(this);
|
||||||
TileSources.Purpose purpose;
|
downloadLayer = MapManager.setupMap(mapView);
|
||||||
if(ACTIVITY.equals(Workout.WORKOUT_TYPE_CYCLING)){
|
|
||||||
purpose= TileSources.Purpose.CYCLING;
|
|
||||||
}else{
|
|
||||||
purpose= TileSources.Purpose.OUTDOOR;
|
|
||||||
}
|
|
||||||
downloadLayer= MapManager.setupMap(mapView, purpose);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLine(){
|
private void updateLine(){
|
||||||
@ -343,10 +346,18 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
|
|||||||
|
|
||||||
public void onResume(){
|
public void onResume(){
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
enableLockScreenVisibility();
|
||||||
downloadLayer.onResume();
|
downloadLayer.onResume();
|
||||||
isResumed= true;
|
isResumed= true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void enableLockScreenVisibility() {
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
|
||||||
|
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
|
||||||
|
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
|
||||||
|
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
// Inflate the menu; this adds items to the action bar if it is present.
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
|
|||||||
@ -40,9 +40,9 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import de.tadris.fitness.R;
|
import de.tadris.fitness.R;
|
||||||
import de.tadris.fitness.announcement.VoiceAnnouncements;
|
|
||||||
import de.tadris.fitness.export.BackupController;
|
import de.tadris.fitness.export.BackupController;
|
||||||
import de.tadris.fitness.export.RestoreController;
|
import de.tadris.fitness.export.RestoreController;
|
||||||
|
import de.tadris.fitness.recording.announcement.VoiceAnnouncements;
|
||||||
import de.tadris.fitness.util.FileUtils;
|
import de.tadris.fitness.util.FileUtils;
|
||||||
import de.tadris.fitness.util.unit.UnitUtils;
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
import de.tadris.fitness.view.ProgressDialogController;
|
import de.tadris.fitness.view.ProgressDialogController;
|
||||||
@ -62,6 +62,12 @@ public class SettingsActivity extends FitoTrackSettingsActivity {
|
|||||||
|
|
||||||
bindPreferenceSummaryToValue(findPreference("unitSystem"));
|
bindPreferenceSummaryToValue(findPreference("unitSystem"));
|
||||||
bindPreferenceSummaryToValue(findPreference("mapStyle"));
|
bindPreferenceSummaryToValue(findPreference("mapStyle"));
|
||||||
|
bindPreferenceSummaryToValue(findPreference("themeSetting"));
|
||||||
|
findPreference("themeSetting").setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
|
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, newValue);
|
||||||
|
Toast.makeText(SettingsActivity.this, R.string.hintRestart, Toast.LENGTH_LONG).show();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
findPreference("weight").setOnPreferenceClickListener(preference -> {
|
findPreference("weight").setOnPreferenceClickListener(preference -> {
|
||||||
showWeightPicker();
|
showWeightPicker();
|
||||||
|
|||||||
@ -21,13 +21,10 @@ package de.tadris.fitness.activity;
|
|||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
@ -66,12 +63,13 @@ public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils.
|
|||||||
initBeforeContent();
|
initBeforeContent();
|
||||||
|
|
||||||
setContentView(R.layout.activity_show_workout);
|
setContentView(R.layout.activity_show_workout);
|
||||||
root= findViewById(R.id.showWorkoutRoot);
|
initRoot();
|
||||||
|
|
||||||
initAfterContent();
|
initAfterContent();
|
||||||
|
|
||||||
commentView = addText(getString(R.string.comment) + ": " + workout.comment);
|
commentView = addText("", true);
|
||||||
commentView.setOnClickListener(v -> openEditCommentDialog());
|
commentView.setOnClickListener(v -> openEditCommentDialog());
|
||||||
|
updateCommentText();
|
||||||
|
|
||||||
addTitle(getString(R.string.workoutTime));
|
addTitle(getString(R.string.workoutTime));
|
||||||
addKeyValue(getString(R.string.workoutDate), getDate());
|
addKeyValue(getString(R.string.workoutDate), getDate());
|
||||||
@ -82,34 +80,43 @@ public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils.
|
|||||||
|
|
||||||
addKeyValue(getString(R.string.workoutDistance), UnitUtils.getDistance(workout.length), getString(R.string.workoutPace), UnitUtils.getPace(workout.avgPace));
|
addKeyValue(getString(R.string.workoutDistance), UnitUtils.getDistance(workout.length), getString(R.string.workoutPace), UnitUtils.getPace(workout.avgPace));
|
||||||
|
|
||||||
addTitle(getString(R.string.workoutRoute));
|
if (hasSamples()) {
|
||||||
|
addTitle(getString(R.string.workoutRoute));
|
||||||
|
|
||||||
addMap();
|
addMap();
|
||||||
|
|
||||||
|
map.setClickable(false);
|
||||||
|
mapRoot.setOnClickListener(v -> startActivity(new Intent(ShowWorkoutActivity.this, ShowWorkoutMapActivity.class)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
map.setClickable(false);
|
|
||||||
mapRoot.setOnClickListener(v -> startActivity(new Intent(ShowWorkoutActivity.this, ShowWorkoutMapActivity.class)));
|
|
||||||
|
|
||||||
addTitle(getString(R.string.workoutSpeed));
|
addTitle(getString(R.string.workoutSpeed));
|
||||||
|
|
||||||
addKeyValue(getString(R.string.workoutAvgSpeedShort), UnitUtils.getSpeed(workout.avgSpeed),
|
addKeyValue(getString(R.string.workoutAvgSpeedShort), UnitUtils.getSpeed(workout.avgSpeed),
|
||||||
getString(R.string.workoutTopSpeed), UnitUtils.getSpeed(workout.topSpeed));
|
getString(R.string.workoutTopSpeed), UnitUtils.getSpeed(workout.topSpeed));
|
||||||
|
|
||||||
addSpeedDiagram();
|
if (hasSamples()) {
|
||||||
|
|
||||||
speedDiagram.setOnClickListener(v -> startDiagramActivity(ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE_SPEED));
|
addSpeedDiagram();
|
||||||
|
|
||||||
|
speedDiagram.setOnClickListener(v -> startDiagramActivity(ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE_SPEED));
|
||||||
|
}
|
||||||
|
|
||||||
addTitle(getString(R.string.workoutBurnedEnergy));
|
addTitle(getString(R.string.workoutBurnedEnergy));
|
||||||
addKeyValue(getString(R.string.workoutTotalEnergy), workout.calorie + " kcal",
|
addKeyValue(getString(R.string.workoutTotalEnergy), workout.calorie + " kcal",
|
||||||
getString(R.string.workoutEnergyConsumption), UnitUtils.getRelativeEnergyConsumption((double)workout.calorie / ((double)workout.length / 1000)));
|
getString(R.string.workoutEnergyConsumption), UnitUtils.getRelativeEnergyConsumption((double)workout.calorie / ((double)workout.length / 1000)));
|
||||||
|
|
||||||
addTitle(getString(R.string.height));
|
if (hasSamples()) {
|
||||||
|
addTitle(getString(R.string.height));
|
||||||
|
|
||||||
addKeyValue(getString(R.string.workoutAscent), UnitUtils.getDistance((int)workout.ascent),
|
addKeyValue(getString(R.string.workoutAscent), UnitUtils.getDistance((int) workout.ascent),
|
||||||
getString(R.string.workoutDescent), UnitUtils.getDistance((int)workout.descent));
|
getString(R.string.workoutDescent), UnitUtils.getDistance((int) workout.descent));
|
||||||
|
|
||||||
addHeightDiagram();
|
addHeightDiagram();
|
||||||
|
|
||||||
heightDiagram.setOnClickListener(v -> startDiagramActivity(ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE_HEIGHT));
|
heightDiagram.setOnClickListener(v -> startDiagramActivity(ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE_HEIGHT));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -126,14 +133,31 @@ public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils.
|
|||||||
editText.setSingleLine(true);
|
editText.setSingleLine(true);
|
||||||
new AlertDialog.Builder(this)
|
new AlertDialog.Builder(this)
|
||||||
.setTitle(R.string.enterComment)
|
.setTitle(R.string.enterComment)
|
||||||
.setPositiveButton(R.string.okay, (dialog, which) -> changeComment(editText.getText().toString(), commentView))
|
.setPositiveButton(R.string.okay, (dialog, which) -> changeComment(editText.getText().toString()))
|
||||||
.setView(editText).create().show();
|
.setView(editText).create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeComment(String comment, TextView onChange) {
|
private void changeComment(String comment) {
|
||||||
workout.comment= comment;
|
workout.comment= comment;
|
||||||
Instance.getInstance(this).db.workoutDao().updateWorkout(workout);
|
Instance.getInstance(this).db.workoutDao().updateWorkout(workout);
|
||||||
onChange.setText(getString(R.string.comment) + ": " + workout.comment);
|
updateCommentText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCommentText() {
|
||||||
|
String str = "";
|
||||||
|
if (workout.edited) {
|
||||||
|
str += getString(R.string.workoutEdited);
|
||||||
|
}
|
||||||
|
if (workout.comment != null && workout.comment.length() > 0) {
|
||||||
|
if (str.length() > 0) {
|
||||||
|
str += "\n";
|
||||||
|
}
|
||||||
|
str += getString(R.string.comment) + ": " + workout.comment;
|
||||||
|
}
|
||||||
|
if (str.length() == 0) {
|
||||||
|
str = getString(R.string.noComment);
|
||||||
|
}
|
||||||
|
commentView.setText(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getDate() {
|
private String getDate() {
|
||||||
@ -141,51 +165,6 @@ public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils.
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void addTitle(String title) {
|
|
||||||
TextView textView= new TextView(this);
|
|
||||||
textView.setText(title);
|
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
|
||||||
textView.setTextColor(getThemePrimaryColor());
|
|
||||||
textView.setTypeface(Typeface.DEFAULT_BOLD);
|
|
||||||
textView.setAllCaps(true);
|
|
||||||
textView.setPadding(0, 20, 0, 0);
|
|
||||||
|
|
||||||
root.addView(textView);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TextView addText(String text) {
|
|
||||||
TextView textView= new TextView(this);
|
|
||||||
textView.setText(text);
|
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
|
||||||
textView.setTextColor(getThemePrimaryColor());
|
|
||||||
textView.setPadding(0, 20, 0, 0);
|
|
||||||
|
|
||||||
root.addView(textView);
|
|
||||||
|
|
||||||
return textView;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addKeyValue(String key1, String value1) {
|
|
||||||
addKeyValue(key1, value1, "", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addKeyValue(String key1, String value1, String key2, String value2) {
|
|
||||||
View v= getLayoutInflater().inflate(R.layout.show_entry, root, false);
|
|
||||||
|
|
||||||
TextView title1= v.findViewById(R.id.v1title);
|
|
||||||
TextView title2= v.findViewById(R.id.v2title);
|
|
||||||
TextView v1= v.findViewById(R.id.v1value);
|
|
||||||
TextView v2= v.findViewById(R.id.v2value);
|
|
||||||
|
|
||||||
title1.setText(key1);
|
|
||||||
title2.setText(key2);
|
|
||||||
v1.setText(value1);
|
|
||||||
v2.setText(value2);
|
|
||||||
|
|
||||||
root.addView(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
// Inflate the menu; this adds items to the action bar if it is present.
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
@ -299,4 +278,8 @@ public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils.
|
|||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void initRoot() {
|
||||||
|
root = findViewById(R.id.showWorkoutRoot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
*
|
*
|
||||||
* This file is part of FitoTrack
|
* This file is part of FitoTrack
|
||||||
*
|
*
|
||||||
@ -32,7 +32,7 @@ public class ShowWorkoutMapActivity extends WorkoutActivity {
|
|||||||
initBeforeContent();
|
initBeforeContent();
|
||||||
|
|
||||||
setContentView(R.layout.activity_show_workout_map);
|
setContentView(R.layout.activity_show_workout_map);
|
||||||
root= findViewById(R.id.showWorkoutMapParent);
|
initRoot();
|
||||||
|
|
||||||
initAfterContent();
|
initAfterContent();
|
||||||
|
|
||||||
@ -43,4 +43,8 @@ public class ShowWorkoutMapActivity extends WorkoutActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void initRoot() {
|
||||||
|
root = findViewById(R.id.showWorkoutMapParent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
*
|
*
|
||||||
* This file is part of FitoTrack
|
* This file is part of FitoTrack
|
||||||
*
|
*
|
||||||
@ -36,7 +36,7 @@ public class ShowWorkoutMapDiagramActivity extends WorkoutActivity {
|
|||||||
initBeforeContent();
|
initBeforeContent();
|
||||||
|
|
||||||
setContentView(R.layout.activity_show_workout_map_diagram);
|
setContentView(R.layout.activity_show_workout_map_diagram);
|
||||||
root= findViewById(R.id.showWorkoutMapParent);
|
initRoot();
|
||||||
|
|
||||||
initAfterContent();
|
initAfterContent();
|
||||||
|
|
||||||
@ -54,4 +54,8 @@ public class ShowWorkoutMapDiagramActivity extends WorkoutActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void initRoot() {
|
||||||
|
root = findViewById(R.id.showWorkoutMapParent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -55,18 +55,14 @@ import de.tadris.fitness.data.WorkoutManager;
|
|||||||
import de.tadris.fitness.data.WorkoutSample;
|
import de.tadris.fitness.data.WorkoutSample;
|
||||||
import de.tadris.fitness.map.MapManager;
|
import de.tadris.fitness.map.MapManager;
|
||||||
import de.tadris.fitness.map.WorkoutLayer;
|
import de.tadris.fitness.map.WorkoutLayer;
|
||||||
import de.tadris.fitness.map.tilesource.TileSources;
|
|
||||||
import de.tadris.fitness.util.ThemeManager;
|
|
||||||
import de.tadris.fitness.util.WorkoutTypeCalculator;
|
|
||||||
import de.tadris.fitness.util.unit.UnitUtils;
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
|
|
||||||
public abstract class WorkoutActivity extends FitoTrackActivity {
|
public abstract class WorkoutActivity extends InformationActivity {
|
||||||
|
|
||||||
public static Workout selectedWorkout;
|
public static Workout selectedWorkout;
|
||||||
|
|
||||||
List<WorkoutSample> samples;
|
List<WorkoutSample> samples;
|
||||||
Workout workout;
|
Workout workout;
|
||||||
ViewGroup root;
|
|
||||||
private Resources.Theme theme;
|
private Resources.Theme theme;
|
||||||
MapView map;
|
MapView map;
|
||||||
private TileDownloadLayer downloadLayer;
|
private TileDownloadLayer downloadLayer;
|
||||||
@ -79,14 +75,14 @@ public abstract class WorkoutActivity extends FitoTrackActivity {
|
|||||||
void initBeforeContent() {
|
void initBeforeContent() {
|
||||||
workout= selectedWorkout;
|
workout= selectedWorkout;
|
||||||
samples= Arrays.asList(Instance.getInstance(this).db.workoutDao().getAllSamplesOfWorkout(workout.id));
|
samples= Arrays.asList(Instance.getInstance(this).db.workoutDao().getAllSamplesOfWorkout(workout.id));
|
||||||
setTheme(ThemeManager.getThemeByWorkout(workout));
|
setTheme(Instance.getInstance(this).themes.getWorkoutTypeTheme(workout.getWorkoutType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void initAfterContent() {
|
void initAfterContent() {
|
||||||
if (getActionBar() != null) {
|
if (getActionBar() != null) {
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
}
|
}
|
||||||
setTitle(WorkoutTypeCalculator.getType(workout));
|
setTitle(workout.getWorkoutType().title);
|
||||||
|
|
||||||
theme= getTheme();
|
theme= getTheme();
|
||||||
}
|
}
|
||||||
@ -259,7 +255,7 @@ public abstract class WorkoutActivity extends FitoTrackActivity {
|
|||||||
|
|
||||||
void addMap(){
|
void addMap(){
|
||||||
map= new MapView(this);
|
map= new MapView(this);
|
||||||
downloadLayer= MapManager.setupMap(map, TileSources.Purpose.DEFAULT);
|
downloadLayer = MapManager.setupMap(map);
|
||||||
|
|
||||||
WorkoutLayer workoutLayer= new WorkoutLayer(samples, getThemePrimaryColor());
|
WorkoutLayer workoutLayer= new WorkoutLayer(samples, getThemePrimaryColor());
|
||||||
map.addLayer(workoutLayer);
|
map.addLayer(workoutLayer);
|
||||||
@ -297,9 +293,15 @@ public abstract class WorkoutActivity extends FitoTrackActivity {
|
|||||||
return getWindowManager().getDefaultDisplay().getWidth()*3/4;
|
return getWindowManager().getDefaultDisplay().getWidth()*3/4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasSamples() {
|
||||||
|
return samples.size() > 1;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
map.destroyAll();
|
if (map != null) {
|
||||||
|
map.destroyAll();
|
||||||
|
}
|
||||||
AndroidGraphicFactory.clearResourceMemoryCache();
|
AndroidGraphicFactory.clearResourceMemoryCache();
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
@ -307,12 +309,16 @@ public abstract class WorkoutActivity extends FitoTrackActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void onPause(){
|
public void onPause(){
|
||||||
super.onPause();
|
super.onPause();
|
||||||
downloadLayer.onPause();
|
if (downloadLayer != null) {
|
||||||
|
downloadLayer.onPause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onResume(){
|
public void onResume(){
|
||||||
super.onResume();
|
super.onResume();
|
||||||
downloadLayer.onResume();
|
if (downloadLayer != null) {
|
||||||
|
downloadLayer.onResume();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
*
|
*
|
||||||
* This file is part of FitoTrack
|
* This file is part of FitoTrack
|
||||||
*
|
*
|
||||||
@ -22,7 +22,7 @@ package de.tadris.fitness.data;
|
|||||||
import androidx.room.Database;
|
import androidx.room.Database;
|
||||||
import androidx.room.RoomDatabase;
|
import androidx.room.RoomDatabase;
|
||||||
|
|
||||||
@Database(version = 2, entities = {Workout.class, WorkoutSample.class})
|
@Database(version = 3, entities = {Workout.class, WorkoutSample.class})
|
||||||
public abstract class AppDatabase extends RoomDatabase {
|
public abstract class AppDatabase extends RoomDatabase {
|
||||||
public abstract WorkoutDao workoutDao();
|
public abstract WorkoutDao workoutDao();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
*
|
*
|
||||||
* This file is part of FitoTrack
|
* This file is part of FitoTrack
|
||||||
*
|
*
|
||||||
@ -19,10 +19,13 @@
|
|||||||
|
|
||||||
package de.tadris.fitness.data;
|
package de.tadris.fitness.data;
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo;
|
||||||
import androidx.room.Entity;
|
import androidx.room.Entity;
|
||||||
import androidx.room.PrimaryKey;
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -31,10 +34,6 @@ import java.util.Date;
|
|||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class Workout{
|
public class Workout{
|
||||||
|
|
||||||
public static final String WORKOUT_TYPE_RUNNING= "running";
|
|
||||||
public static final String WORKOUT_TYPE_HIKING= "hiking";
|
|
||||||
public static final String WORKOUT_TYPE_CYCLING= "cycling";
|
|
||||||
|
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
public long id;
|
public long id;
|
||||||
|
|
||||||
@ -63,12 +62,13 @@ public class Workout{
|
|||||||
public double topSpeed;
|
public double topSpeed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Average pace of workout in km/min
|
* Average pace of workout in min/km
|
||||||
*/
|
*/
|
||||||
public double avgPace;
|
public double avgPace;
|
||||||
|
|
||||||
public String workoutType;
|
@ColumnInfo(name = "workoutType")
|
||||||
|
@JsonProperty(value = "workoutType")
|
||||||
|
public String workoutTypeId;
|
||||||
|
|
||||||
public float ascent;
|
public float ascent;
|
||||||
|
|
||||||
@ -76,6 +76,8 @@ public class Workout{
|
|||||||
|
|
||||||
public int calorie;
|
public int calorie;
|
||||||
|
|
||||||
|
public boolean edited;
|
||||||
|
|
||||||
public String toString(){
|
public String toString(){
|
||||||
if(comment.length() > 2){
|
if(comment.length() > 2){
|
||||||
return comment;
|
return comment;
|
||||||
@ -84,9 +86,20 @@ public class Workout{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
public String getDateString(){
|
public String getDateString(){
|
||||||
return SimpleDateFormat.getDateTimeInstance().format(new Date(start));
|
return SimpleDateFormat.getDateTimeInstance().format(new Date(start));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public WorkoutType getWorkoutType() {
|
||||||
|
return WorkoutType.getTypeById(workoutTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public void setWorkoutType(WorkoutType workoutType) {
|
||||||
|
this.workoutTypeId = workoutType.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
122
app/src/main/java/de/tadris/fitness/data/WorkoutBuilder.java
Normal file
122
app/src/main/java/de/tadris/fitness/data/WorkoutBuilder.java
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.data;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import de.tadris.fitness.Instance;
|
||||||
|
import de.tadris.fitness.util.CalorieCalculator;
|
||||||
|
|
||||||
|
public class WorkoutBuilder {
|
||||||
|
|
||||||
|
private WorkoutType workoutType;
|
||||||
|
|
||||||
|
private Calendar start;
|
||||||
|
private long duration;
|
||||||
|
|
||||||
|
private int length;
|
||||||
|
|
||||||
|
private String comment;
|
||||||
|
|
||||||
|
public WorkoutBuilder() {
|
||||||
|
workoutType = WorkoutType.RUNNING;
|
||||||
|
start = Calendar.getInstance();
|
||||||
|
duration = 1000L * 60 * 10;
|
||||||
|
length = 500;
|
||||||
|
comment = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Workout create(Context context) {
|
||||||
|
Workout workout = new Workout();
|
||||||
|
|
||||||
|
// Calculate values
|
||||||
|
workout.start = start.getTimeInMillis();
|
||||||
|
workout.duration = duration;
|
||||||
|
workout.end = workout.start + workout.duration;
|
||||||
|
|
||||||
|
workout.id = workout.start;
|
||||||
|
workout.setWorkoutType(workoutType);
|
||||||
|
|
||||||
|
workout.length = length;
|
||||||
|
|
||||||
|
workout.avgSpeed = (double) length / (double) (duration / 1000);
|
||||||
|
workout.topSpeed = 0;
|
||||||
|
workout.avgPace = ((double) workout.duration / 1000 / 60) / ((double) workout.length / 1000);
|
||||||
|
|
||||||
|
workout.pauseDuration = 0;
|
||||||
|
workout.ascent = 0;
|
||||||
|
workout.descent = 0;
|
||||||
|
|
||||||
|
workout.calorie = CalorieCalculator.calculateCalories(workout, Instance.getInstance(context).userPreferences.getUserWeight());
|
||||||
|
workout.comment = comment;
|
||||||
|
|
||||||
|
workout.edited = true;
|
||||||
|
|
||||||
|
return workout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Workout insertWorkout(Context context) {
|
||||||
|
Workout workout = create(context);
|
||||||
|
Instance.getInstance(context).db.workoutDao().insertWorkout(workout);
|
||||||
|
return workout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkoutType getWorkoutType() {
|
||||||
|
return workoutType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWorkoutType(WorkoutType workoutType) {
|
||||||
|
this.workoutType = workoutType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Calendar getStart() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStart(Calendar start) {
|
||||||
|
this.start = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDuration() {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDuration(long duration) {
|
||||||
|
this.duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLength(int length) {
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComment(String comment) {
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
59
app/src/main/java/de/tadris/fitness/data/WorkoutType.java
Normal file
59
app/src/main/java/de/tadris/fitness/data/WorkoutType.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.data;
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.annotation.StyleRes;
|
||||||
|
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
|
||||||
|
public enum WorkoutType {
|
||||||
|
|
||||||
|
RUNNING("running", R.string.workoutTypeRunning, 7, true, R.style.Running, R.style.RunningDark),
|
||||||
|
HIKING("hiking", R.string.workoutTypeHiking, 7, true, R.style.Hiking, R.style.HikingDark),
|
||||||
|
CYCLING("cycling", R.string.workoutTypeCycling, 12, true, R.style.Bicycling, R.style.BicyclingDark),
|
||||||
|
OTHER("other", R.string.workoutTypeOther, 7, true, R.style.AppTheme, R.style.AppThemeDark);
|
||||||
|
|
||||||
|
public String id;
|
||||||
|
@StringRes
|
||||||
|
public int title;
|
||||||
|
public int minDistance; // Minimum distance between samples
|
||||||
|
public boolean hasGPS;
|
||||||
|
@StyleRes
|
||||||
|
public int lightTheme, darkTheme;
|
||||||
|
|
||||||
|
WorkoutType(String id, int title, int minDistance, boolean hasGPS, int lightTheme, int darkTheme) {
|
||||||
|
this.id = id;
|
||||||
|
this.title = title;
|
||||||
|
this.minDistance = minDistance;
|
||||||
|
this.hasGPS = hasGPS;
|
||||||
|
this.lightTheme = lightTheme;
|
||||||
|
this.darkTheme = darkTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WorkoutType getTypeById(String id) {
|
||||||
|
for (WorkoutType type : values()) {
|
||||||
|
if (type.id.equals(id)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.dialog;
|
||||||
|
|
||||||
|
import android.app.DatePickerDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.app.DialogFragment;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.widget.DatePicker;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
|
||||||
|
|
||||||
|
public DatePickerCallback callback;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
// Use the current date as the default date in the picker
|
||||||
|
final Calendar c = Calendar.getInstance();
|
||||||
|
c.setTimeInMillis(System.currentTimeMillis());
|
||||||
|
int year = c.get(Calendar.YEAR);
|
||||||
|
int month = c.get(Calendar.MONTH);
|
||||||
|
int day = c.get(Calendar.DAY_OF_MONTH);
|
||||||
|
|
||||||
|
// Create a new instance of DatePickerDialog and return it
|
||||||
|
return new DatePickerDialog(getActivity(), this, year, month, day);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDateSet(DatePicker view, int year, int month, int day) {
|
||||||
|
callback.onDatePick(year, month, day);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface DatePickerCallback {
|
||||||
|
void onDatePick(int year, int month, int day);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.dialog;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.NumberPicker;
|
||||||
|
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
|
||||||
|
public class DurationPickerDialogFragment {
|
||||||
|
|
||||||
|
public Activity context;
|
||||||
|
public DurationPickListener listener;
|
||||||
|
public long initialDuration;
|
||||||
|
|
||||||
|
public DurationPickerDialogFragment(Activity context, DurationPickListener listener, long initialDuration) {
|
||||||
|
this.context = context;
|
||||||
|
this.listener = listener;
|
||||||
|
this.initialDuration = initialDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
final AlertDialog.Builder d = new AlertDialog.Builder(context);
|
||||||
|
d.setTitle(R.string.setDuration);
|
||||||
|
View v = context.getLayoutInflater().inflate(R.layout.dialog_duration_picker, null);
|
||||||
|
NumberPicker hours = v.findViewById(R.id.durationPickerHours);
|
||||||
|
hours.setFormatter(value -> value + " " + context.getString(R.string.timeHourShort));
|
||||||
|
hours.setMinValue(0);
|
||||||
|
hours.setMaxValue(24);
|
||||||
|
hours.setValue(getInitialHours());
|
||||||
|
|
||||||
|
NumberPicker minutes = v.findViewById(R.id.durationPickerMinutes);
|
||||||
|
minutes.setFormatter(value -> value + " " + context.getString(R.string.timeMinuteShort));
|
||||||
|
minutes.setMinValue(0);
|
||||||
|
minutes.setMaxValue(60);
|
||||||
|
minutes.setValue(getInitialMinutes());
|
||||||
|
|
||||||
|
NumberPicker seconds = v.findViewById(R.id.durationPickerSeconds);
|
||||||
|
seconds.setFormatter(value -> value + " " + context.getString(R.string.timeSecondsShort));
|
||||||
|
seconds.setMinValue(0);
|
||||||
|
seconds.setMaxValue(60);
|
||||||
|
seconds.setValue(getInitialSeconds());
|
||||||
|
|
||||||
|
d.setView(v);
|
||||||
|
|
||||||
|
d.setNegativeButton(R.string.cancel, null);
|
||||||
|
d.setPositiveButton(R.string.okay, (dialog, which) -> {
|
||||||
|
listener.onDurationPick(getMillisFromPick(hours.getValue(), minutes.getValue(), seconds.getValue()));
|
||||||
|
});
|
||||||
|
|
||||||
|
d.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getInitialHours() {
|
||||||
|
return (int) (initialDuration / 1000 / 60 / 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getInitialMinutes() {
|
||||||
|
return (int) (initialDuration / 1000 / 60 % 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getInitialSeconds() {
|
||||||
|
return (int) (initialDuration / 1000 % 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long getMillisFromPick(int hours, int minutes, int seconds) {
|
||||||
|
long secondInMillis = 1000L;
|
||||||
|
long minuteInMillis = secondInMillis * 60;
|
||||||
|
long hourInMillis = minuteInMillis * 60;
|
||||||
|
return hours * hourInMillis + minutes * minuteInMillis + seconds * secondInMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface DurationPickListener {
|
||||||
|
void onDurationPick(long duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.dialog;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
import de.tadris.fitness.data.WorkoutType;
|
||||||
|
|
||||||
|
public class SelectWorkoutTypeDialog {
|
||||||
|
|
||||||
|
private Activity context;
|
||||||
|
private WorkoutTypeSelectListener listener;
|
||||||
|
private WorkoutType[] options;
|
||||||
|
|
||||||
|
public SelectWorkoutTypeDialog(Activity context, WorkoutTypeSelectListener listener) {
|
||||||
|
this.context = context;
|
||||||
|
this.listener = listener;
|
||||||
|
this.options = WorkoutType.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
AlertDialog.Builder builderSingle = new AlertDialog.Builder(context);
|
||||||
|
|
||||||
|
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(context, R.layout.select_dialog_singlechoice_material);
|
||||||
|
for (WorkoutType type : options) {
|
||||||
|
arrayAdapter.add(context.getString(type.title));
|
||||||
|
}
|
||||||
|
|
||||||
|
builderSingle.setAdapter(arrayAdapter, (dialog, which) -> listener.onSelectWorkoutType(options[which]));
|
||||||
|
builderSingle.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface WorkoutTypeSelectListener {
|
||||||
|
void onSelectWorkoutType(WorkoutType workoutType);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.dialog;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.app.DialogFragment;
|
||||||
|
import android.app.TimePickerDialog;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.format.DateFormat;
|
||||||
|
import android.widget.TimePicker;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
public class TimePickerFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener {
|
||||||
|
|
||||||
|
public TimePickerCallback callback;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
// Use the current time as the default values for the picker
|
||||||
|
final Calendar c = Calendar.getInstance();
|
||||||
|
int hour = c.get(Calendar.HOUR_OF_DAY);
|
||||||
|
int minute = c.get(Calendar.MINUTE);
|
||||||
|
|
||||||
|
// Create a new instance of TimePickerDialog and return it
|
||||||
|
return new TimePickerDialog(getActivity(), this, hour, minute, DateFormat.is24HourFormat(getActivity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
|
||||||
|
callback.onTimePick(hourOfDay, minute);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface TimePickerCallback {
|
||||||
|
void onTimePick(int hour, int minute);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -30,11 +30,10 @@ import de.tadris.fitness.map.tilesource.FitoTrackTileSource;
|
|||||||
import de.tadris.fitness.map.tilesource.HumanitarianTileSource;
|
import de.tadris.fitness.map.tilesource.HumanitarianTileSource;
|
||||||
import de.tadris.fitness.map.tilesource.MapnikTileSource;
|
import de.tadris.fitness.map.tilesource.MapnikTileSource;
|
||||||
import de.tadris.fitness.map.tilesource.ThunderforestTileSource;
|
import de.tadris.fitness.map.tilesource.ThunderforestTileSource;
|
||||||
import de.tadris.fitness.map.tilesource.TileSources;
|
|
||||||
|
|
||||||
public class MapManager {
|
public class MapManager {
|
||||||
|
|
||||||
public static TileDownloadLayer setupMap(MapView mapView, TileSources.Purpose purpose){
|
public static TileDownloadLayer setupMap(MapView mapView) {
|
||||||
FitoTrackTileSource tileSource;
|
FitoTrackTileSource tileSource;
|
||||||
|
|
||||||
String chosenTileLayer= Instance.getInstance(mapView.getContext()).userPreferences.getMapStyle();
|
String chosenTileLayer= Instance.getInstance(mapView.getContext()).userPreferences.getMapStyle();
|
||||||
|
|||||||
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
|
||||||
*
|
|
||||||
* This file is part of FitoTrack
|
|
||||||
*
|
|
||||||
* FitoTrack is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* FitoTrack is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.tadris.fitness.map.tilesource;
|
|
||||||
|
|
||||||
|
|
||||||
public class TileSources {
|
|
||||||
|
|
||||||
public static FitoTrackTileSource[] tileSources= new FitoTrackTileSource[]{
|
|
||||||
MapnikTileSource.INSTANCE, HumanitarianTileSource.INSTANCE, ThunderforestTileSource.OUTDOORS, ThunderforestTileSource.CYCLE_MAP
|
|
||||||
};
|
|
||||||
|
|
||||||
public enum Purpose{
|
|
||||||
DEFAULT, OUTDOOR, CYCLING
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -32,21 +32,11 @@ import java.util.List;
|
|||||||
import de.tadris.fitness.Instance;
|
import de.tadris.fitness.Instance;
|
||||||
import de.tadris.fitness.data.Workout;
|
import de.tadris.fitness.data.Workout;
|
||||||
import de.tadris.fitness.data.WorkoutSample;
|
import de.tadris.fitness.data.WorkoutSample;
|
||||||
|
import de.tadris.fitness.data.WorkoutType;
|
||||||
import de.tadris.fitness.util.CalorieCalculator;
|
import de.tadris.fitness.util.CalorieCalculator;
|
||||||
|
|
||||||
public class WorkoutRecorder implements LocationListener.LocationChangeListener {
|
public class WorkoutRecorder implements LocationListener.LocationChangeListener {
|
||||||
|
|
||||||
private static int getMinDistance(String workoutType){
|
|
||||||
switch (workoutType){
|
|
||||||
case Workout.WORKOUT_TYPE_HIKING:
|
|
||||||
case Workout.WORKOUT_TYPE_RUNNING:
|
|
||||||
return 8;
|
|
||||||
case Workout.WORKOUT_TYPE_CYCLING:
|
|
||||||
return 15;
|
|
||||||
default: return 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int PAUSE_TIME= 10000;
|
private static final int PAUSE_TIME= 10000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,17 +62,18 @@ public class WorkoutRecorder implements LocationListener.LocationChangeListener
|
|||||||
private final WorkoutRecorderListener workoutRecorderListener;
|
private final WorkoutRecorderListener workoutRecorderListener;
|
||||||
private GpsState gpsState= GpsState.SIGNAL_LOST;
|
private GpsState gpsState= GpsState.SIGNAL_LOST;
|
||||||
|
|
||||||
public WorkoutRecorder(Context context, String workoutType, WorkoutRecorderListener workoutRecorderListener) {
|
public WorkoutRecorder(Context context, WorkoutType workoutType, WorkoutRecorderListener workoutRecorderListener) {
|
||||||
this.context= context;
|
this.context= context;
|
||||||
this.state= RecordingState.IDLE;
|
this.state= RecordingState.IDLE;
|
||||||
this.workoutRecorderListener = workoutRecorderListener;
|
this.workoutRecorderListener = workoutRecorderListener;
|
||||||
|
|
||||||
this.workout= new Workout();
|
this.workout= new Workout();
|
||||||
|
workout.edited = false;
|
||||||
|
|
||||||
// Default values
|
// Default values
|
||||||
this.workout.comment= "";
|
this.workout.comment= "";
|
||||||
|
|
||||||
this.workout.workoutType= workoutType;
|
this.workout.setWorkoutType(workoutType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(){
|
public void start(){
|
||||||
@ -214,7 +205,7 @@ public class WorkoutRecorder implements LocationListener.LocationChangeListener
|
|||||||
WorkoutSample lastSample= samples.get(samples.size() - 1);
|
WorkoutSample lastSample= samples.get(samples.size() - 1);
|
||||||
distance= LocationListener.locationToLatLong(location).sphericalDistance(new LatLong(lastSample.lat, lastSample.lon));
|
distance= LocationListener.locationToLatLong(location).sphericalDistance(new LatLong(lastSample.lat, lastSample.lon));
|
||||||
long timediff= lastSample.absoluteTime - location.getTime();
|
long timediff= lastSample.absoluteTime - location.getTime();
|
||||||
if(distance < getMinDistance(workout.workoutType) && timediff < 500){
|
if (distance < workout.getWorkoutType().minDistance && timediff < 500) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,12 +23,14 @@ import android.content.Context;
|
|||||||
import android.hardware.SensorManager;
|
import android.hardware.SensorManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.tadris.fitness.Instance;
|
import de.tadris.fitness.Instance;
|
||||||
import de.tadris.fitness.data.AppDatabase;
|
import de.tadris.fitness.data.AppDatabase;
|
||||||
import de.tadris.fitness.data.Workout;
|
import de.tadris.fitness.data.Workout;
|
||||||
import de.tadris.fitness.data.WorkoutSample;
|
import de.tadris.fitness.data.WorkoutSample;
|
||||||
|
import de.tadris.fitness.util.AltitudeCorrection;
|
||||||
import de.tadris.fitness.util.CalorieCalculator;
|
import de.tadris.fitness.util.CalorieCalculator;
|
||||||
|
|
||||||
class WorkoutSaver {
|
class WorkoutSaver {
|
||||||
@ -51,7 +53,7 @@ class WorkoutSaver {
|
|||||||
setSimpleValues();
|
setSimpleValues();
|
||||||
setTopSpeed();
|
setTopSpeed();
|
||||||
|
|
||||||
setRealElevation();
|
setElevation();
|
||||||
setAscentAndDescent();
|
setAscentAndDescent();
|
||||||
|
|
||||||
setCalories();
|
setCalories();
|
||||||
@ -84,9 +86,7 @@ class WorkoutSaver {
|
|||||||
double length= 0;
|
double length= 0;
|
||||||
for(int i= 1; i < samples.size(); i++){
|
for(int i= 1; i < samples.size(); i++){
|
||||||
double sampleLength= samples.get(i - 1).toLatLong().sphericalDistance(samples.get(i).toLatLong());
|
double sampleLength= samples.get(i - 1).toLatLong().sphericalDistance(samples.get(i).toLatLong());
|
||||||
long timeDiff= (samples.get(i).relativeTime - samples.get(i - 1).relativeTime) / 1000;
|
|
||||||
length+= sampleLength;
|
length+= sampleLength;
|
||||||
samples.get(i).speed= Math.abs(sampleLength / timeDiff);
|
|
||||||
}
|
}
|
||||||
workout.length= (int)length;
|
workout.length= (int)length;
|
||||||
workout.avgSpeed= ((double) workout.length) / ((double) workout.duration / 1000);
|
workout.avgSpeed= ((double) workout.length) / ((double) workout.duration / 1000);
|
||||||
@ -103,7 +103,27 @@ class WorkoutSaver {
|
|||||||
workout.topSpeed= topSpeed;
|
workout.topSpeed= topSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRealElevation(){
|
private void setElevation() {
|
||||||
|
setCorrectedElevation();
|
||||||
|
setPressureElevation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCorrectedElevation() {
|
||||||
|
// Please see the AltitudeCorrection.java for the reason of this
|
||||||
|
try {
|
||||||
|
int lat = (int) Math.round(samples.get(0).lat);
|
||||||
|
int lon = (int) Math.round(samples.get(0).lon);
|
||||||
|
AltitudeCorrection correction = new AltitudeCorrection(context, lat, lon);
|
||||||
|
for (WorkoutSample sample : samples) {
|
||||||
|
sample.elevation = correction.getHeightOverSeaLevel(sample.elevation);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// If we can't read the file, we cannot correct the values
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPressureElevation() {
|
||||||
boolean pressureDataAvailable= samples.get(0).tmpPressure != -1;
|
boolean pressureDataAvailable= samples.get(0).tmpPressure != -1;
|
||||||
|
|
||||||
if(!pressureDataAvailable){
|
if(!pressureDataAvailable){
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.tadris.fitness.announcement;
|
package de.tadris.fitness.recording.announcement;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.tadris.fitness.announcement;
|
package de.tadris.fitness.recording.announcement;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.tadris.fitness.announcement;
|
package de.tadris.fitness.recording.announcement;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.tadris.fitness.announcement;
|
package de.tadris.fitness.recording.announcement;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.tadris.fitness.announcement;
|
package de.tadris.fitness.recording.announcement;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.tadris.fitness.announcement;
|
package de.tadris.fitness.recording.announcement;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.tadris.fitness.announcement;
|
package de.tadris.fitness.recording.announcement;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
@ -17,8 +17,10 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.tadris.fitness.announcement;
|
package de.tadris.fitness.recording.announcement;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothHeadset;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.speech.tts.TextToSpeech;
|
import android.speech.tts.TextToSpeech;
|
||||||
@ -115,7 +117,7 @@ public class VoiceAnnouncements {
|
|||||||
// Cannot speak
|
// Cannot speak
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (currentMode == AnnouncementMode.HEADPHONES && !audioManager.isWiredHeadsetOn()) {
|
if (currentMode == AnnouncementMode.HEADPHONES && !isHeadsetOn()) {
|
||||||
// Not allowed to speak
|
// Not allowed to speak
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -123,6 +125,14 @@ public class VoiceAnnouncements {
|
|||||||
textToSpeech.speak(text, TextToSpeech.QUEUE_ADD, null, "announcement" + (++speakId));
|
textToSpeech.speak(text, TextToSpeech.QUEUE_ADD, null, "announcement" + (++speakId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isHeadsetOn() {
|
||||||
|
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
boolean bluetoothHeadsetConnected = mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()
|
||||||
|
&& mBluetoothAdapter.getProfileConnectionState(BluetoothHeadset.HEADSET) == BluetoothHeadset.STATE_CONNECTED;
|
||||||
|
|
||||||
|
return audioManager.isWiredHeadsetOn() || bluetoothHeadsetConnected;
|
||||||
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
textToSpeech.shutdown();
|
textToSpeech.shutdown();
|
||||||
}
|
}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.util;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class has the task to correct the altitude.
|
||||||
|
* <p>
|
||||||
|
* In Germany or UK for example the GPS height differs
|
||||||
|
* roughly 50m from the real elevation over sea level.
|
||||||
|
* <p>
|
||||||
|
* The altitude given by GPS is the altitude over the WGS84 reference ellipsoid
|
||||||
|
* but we want the height over the sea level. That's why we have to correct the height.
|
||||||
|
* Luckily I found a file containing the corrections for all places around the world.
|
||||||
|
* <p>
|
||||||
|
* The geoids.csv is from https://github.com/vectorstofinal/geoid_heights licensed under MIT
|
||||||
|
*/
|
||||||
|
public class AltitudeCorrection {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private int latitude, longitude;
|
||||||
|
private double offset; // Basically how much higher the sea-level than the ellipsoid is
|
||||||
|
|
||||||
|
public AltitudeCorrection(Context context, int latitude, int longitude) throws IOException {
|
||||||
|
this.context = context;
|
||||||
|
this.latitude = latitude;
|
||||||
|
this.longitude = longitude;
|
||||||
|
findOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findOffset() throws IOException {
|
||||||
|
InputStream inputStream = context.getResources().openRawResource(R.raw.geoids);
|
||||||
|
List<String> list = IOUtils.readLines(inputStream, StandardCharsets.UTF_8);
|
||||||
|
for (String line : list) {
|
||||||
|
String[] data = line.split(",");
|
||||||
|
int lat = Integer.parseInt(data[0]);
|
||||||
|
int lon = Integer.parseInt(data[1]);
|
||||||
|
double offset = Double.parseDouble(data[2]);
|
||||||
|
if (lat == this.latitude && lon == this.longitude) {
|
||||||
|
this.offset = offset;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeightOverSeaLevel(double heightOverEllipsoid) {
|
||||||
|
return heightOverEllipsoid - offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -20,6 +20,7 @@
|
|||||||
package de.tadris.fitness.util;
|
package de.tadris.fitness.util;
|
||||||
|
|
||||||
import de.tadris.fitness.data.Workout;
|
import de.tadris.fitness.data.Workout;
|
||||||
|
import de.tadris.fitness.data.WorkoutType;
|
||||||
|
|
||||||
public class CalorieCalculator {
|
public class CalorieCalculator {
|
||||||
|
|
||||||
@ -47,15 +48,14 @@ public class CalorieCalculator {
|
|||||||
*/
|
*/
|
||||||
private static double getMET(Workout workout) {
|
private static double getMET(Workout workout) {
|
||||||
double speedInKmh= workout.avgSpeed * 3.6;
|
double speedInKmh= workout.avgSpeed * 3.6;
|
||||||
if(workout.workoutType.equals(Workout.WORKOUT_TYPE_RUNNING) || workout.workoutType.equals(Workout.WORKOUT_TYPE_HIKING)){
|
WorkoutType type = workout.getWorkoutType();
|
||||||
// This is a linear graph based on the website linked above
|
if (type == WorkoutType.RUNNING || type == WorkoutType.HIKING) {
|
||||||
return Math.max(1.5, speedInKmh*1.117 - 2.1906);
|
return Math.max(1.5, speedInKmh*1.117 - 2.1906);
|
||||||
}
|
}
|
||||||
if(workout.workoutType.equals(Workout.WORKOUT_TYPE_CYCLING)){
|
if (type == WorkoutType.CYCLING) {
|
||||||
// This is a linear graph based on the website linked above
|
|
||||||
return Math.max(3, (speedInKmh-10) / 1.5);
|
return Math.max(3, (speedInKmh-10) / 1.5);
|
||||||
}
|
}
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.util;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import androidx.annotation.StyleRes;
|
||||||
|
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
import de.tadris.fitness.data.WorkoutType;
|
||||||
|
|
||||||
|
public class FitoTrackThemes {
|
||||||
|
|
||||||
|
private static final int THEME_SETTING_LIGHT = 0;
|
||||||
|
private static final int THEME_SETTING_DARK = 1;
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
public FitoTrackThemes(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@StyleRes
|
||||||
|
public int getDefaultTheme() {
|
||||||
|
if (shouldUseLightMode()) {
|
||||||
|
return R.style.AppTheme;
|
||||||
|
} else {
|
||||||
|
return R.style.AppThemeDark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@StyleRes
|
||||||
|
public int getWorkoutTypeTheme(WorkoutType type) {
|
||||||
|
if (shouldUseLightMode()) {
|
||||||
|
return type.lightTheme;
|
||||||
|
} else {
|
||||||
|
return type.darkTheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldUseLightMode() {
|
||||||
|
switch (getThemeSetting()) {
|
||||||
|
default:
|
||||||
|
case THEME_SETTING_LIGHT:
|
||||||
|
return true;
|
||||||
|
case THEME_SETTING_DARK:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getThemeSetting() {
|
||||||
|
String setting = PreferenceManager.getDefaultSharedPreferences(context).getString("themeSetting", String.valueOf(THEME_SETTING_LIGHT));
|
||||||
|
assert setting != null;
|
||||||
|
return Integer.parseInt(setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
|
||||||
*
|
|
||||||
* This file is part of FitoTrack
|
|
||||||
*
|
|
||||||
* FitoTrack is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* FitoTrack is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.tadris.fitness.util;
|
|
||||||
|
|
||||||
import de.tadris.fitness.R;
|
|
||||||
import de.tadris.fitness.data.Workout;
|
|
||||||
|
|
||||||
public class ThemeManager {
|
|
||||||
|
|
||||||
public static int getThemeByWorkoutType(String type){
|
|
||||||
switch (type){
|
|
||||||
case Workout.WORKOUT_TYPE_RUNNING: return R.style.Running;
|
|
||||||
case Workout.WORKOUT_TYPE_CYCLING: return R.style.Bicycling;
|
|
||||||
case Workout.WORKOUT_TYPE_HIKING: return R.style.Hiking;
|
|
||||||
default: return R.style.AppTheme;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getThemeByWorkout(Workout workout){
|
|
||||||
return getThemeByWorkoutType(workout.workoutType);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
|
||||||
*
|
|
||||||
* This file is part of FitoTrack
|
|
||||||
*
|
|
||||||
* FitoTrack is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* FitoTrack is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.tadris.fitness.util;
|
|
||||||
|
|
||||||
import de.tadris.fitness.R;
|
|
||||||
import de.tadris.fitness.data.Workout;
|
|
||||||
|
|
||||||
public class WorkoutTypeCalculator {
|
|
||||||
|
|
||||||
public static int getType(Workout workout){
|
|
||||||
if(workout.workoutType.equals(Workout.WORKOUT_TYPE_RUNNING)){
|
|
||||||
if(workout.avgSpeed < 1.9){
|
|
||||||
return R.string.workoutTypeWalking;
|
|
||||||
}else if(workout.avgSpeed < 2.7){
|
|
||||||
return R.string.workoutTypeJogging;
|
|
||||||
}else{
|
|
||||||
return R.string.workoutTypeRunning;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(workout.workoutType.equals(Workout.WORKOUT_TYPE_CYCLING)){
|
|
||||||
return R.string.workoutTypeCycling;
|
|
||||||
}
|
|
||||||
if(workout.workoutType.equals(Workout.WORKOUT_TYPE_HIKING)){
|
|
||||||
return R.string.workoutTypeHiking;
|
|
||||||
}
|
|
||||||
return R.string.workoutTypeUnknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -61,7 +61,7 @@ public class GpxExporter {
|
|||||||
track.cmt= workout.comment;
|
track.cmt= workout.comment;
|
||||||
track.desc= workout.comment;
|
track.desc= workout.comment;
|
||||||
track.src= "FitoTrack";
|
track.src= "FitoTrack";
|
||||||
track.type= workout.workoutType;
|
track.type = workout.getWorkoutType().id;
|
||||||
track.trkseg= new ArrayList<>();
|
track.trkseg= new ArrayList<>();
|
||||||
|
|
||||||
TrackSegment segment= new TrackSegment();
|
TrackSegment segment= new TrackSegment();
|
||||||
|
|||||||
@ -32,7 +32,6 @@ import java.util.Date;
|
|||||||
|
|
||||||
import de.tadris.fitness.R;
|
import de.tadris.fitness.R;
|
||||||
import de.tadris.fitness.data.Workout;
|
import de.tadris.fitness.data.Workout;
|
||||||
import de.tadris.fitness.util.WorkoutTypeCalculator;
|
|
||||||
import de.tadris.fitness.util.unit.UnitUtils;
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
|
|
||||||
public class WorkoutAdapter extends RecyclerView.Adapter<WorkoutAdapter.WorkoutViewHolder>{
|
public class WorkoutAdapter extends RecyclerView.Adapter<WorkoutAdapter.WorkoutViewHolder>{
|
||||||
@ -78,7 +77,7 @@ public class WorkoutAdapter extends RecyclerView.Adapter<WorkoutAdapter.WorkoutV
|
|||||||
public void onBindViewHolder(WorkoutViewHolder holder, final int position) {
|
public void onBindViewHolder(WorkoutViewHolder holder, final int position) {
|
||||||
Workout workout= workouts[position];
|
Workout workout= workouts[position];
|
||||||
holder.dateText.setText(SimpleDateFormat.getDateTimeInstance().format(new Date(workout.start)));
|
holder.dateText.setText(SimpleDateFormat.getDateTimeInstance().format(new Date(workout.start)));
|
||||||
holder.typeText.setText(WorkoutTypeCalculator.getType(workout));
|
holder.typeText.setText(workout.getWorkoutType().title);
|
||||||
if(workout.comment != null){
|
if(workout.comment != null){
|
||||||
if(workout.comment.length() > 33){
|
if(workout.comment.length() > 33){
|
||||||
holder.commentText.setText(workout.comment.substring(0, 30) + "...");
|
holder.commentText.setText(workout.comment.substring(0, 30) + "...");
|
||||||
|
|||||||
32
app/src/main/res/layout/activity_enter_workout.xml
Normal file
32
app/src/main/res/layout/activity_enter_workout.xml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
~
|
||||||
|
~ This file is part of FitoTrack
|
||||||
|
~
|
||||||
|
~ FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".activity.EnterWorkoutActivity">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/enterWorkoutRoot"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="15dp" />
|
||||||
|
</ScrollView>
|
||||||
@ -72,6 +72,16 @@
|
|||||||
app:fab_label="@string/workoutTypeCycling"
|
app:fab_label="@string/workoutTypeCycling"
|
||||||
app:fab_size="normal" />
|
app:fab_size="normal" />
|
||||||
|
|
||||||
|
<com.github.clans.fab.FloatingActionButton
|
||||||
|
android:id="@+id/workoutListEnter"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_add_white"
|
||||||
|
app:fab_colorNormal="@color/colorPrimary"
|
||||||
|
app:fab_colorPressed="@color/colorPrimaryDark"
|
||||||
|
app:fab_label="@string/enterWorkout"
|
||||||
|
app:fab_size="normal" />
|
||||||
|
|
||||||
</com.github.clans.fab.FloatingActionMenu>
|
</com.github.clans.fab.FloatingActionMenu>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -55,6 +55,15 @@
|
|||||||
android:text="@string/gps"
|
android:text="@string/gps"
|
||||||
android:textColor="@android:color/transparent" />
|
android:textColor="@android:color/transparent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/recordMapAttribution"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|center"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:textColor="@color/textColorLight"
|
||||||
|
android:text="@string/OpenStreetMapAttribution" />
|
||||||
|
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
@ -74,7 +83,7 @@
|
|||||||
android:fontFamily="sans-serif-black"
|
android:fontFamily="sans-serif-black"
|
||||||
android:text="0:44:08"
|
android:text="0:44:08"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textColor="@android:color/black"
|
android:textColor="?android:textColorPrimary"
|
||||||
android:textSize="30sp"
|
android:textSize="30sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
@ -116,7 +125,7 @@
|
|||||||
android:text="2,06 km"
|
android:text="2,06 km"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@android:color/black"
|
android:textColor="?android:textColorPrimary"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
@ -136,7 +145,7 @@
|
|||||||
android:text="30 kcal"
|
android:text="30 kcal"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@android:color/black"
|
android:textColor="?android:textColorPrimary"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
@ -167,7 +176,7 @@
|
|||||||
android:text="7 km/h"
|
android:text="7 km/h"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@android:color/black"
|
android:textColor="?android:textColorPrimary"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
@ -187,7 +196,7 @@
|
|||||||
android:text="30 kcal"
|
android:text="30 kcal"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@android:color/black"
|
android:textColor="?android:textColorPrimary"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
|||||||
54
app/src/main/res/layout/dialog_duration_picker.xml
Normal file
54
app/src/main/res/layout/dialog_duration_picker.xml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
~
|
||||||
|
~ This file is part of FitoTrack
|
||||||
|
~
|
||||||
|
~ FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<NumberPicker
|
||||||
|
android:id="@+id/durationPickerHours"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="30dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text=":" />
|
||||||
|
|
||||||
|
<NumberPicker
|
||||||
|
android:id="@+id/durationPickerMinutes"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="30dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text=":" />
|
||||||
|
|
||||||
|
<NumberPicker
|
||||||
|
android:id="@+id/durationPickerSeconds"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="30dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
71
app/src/main/res/layout/enter_workout_line.xml
Normal file
71
app/src/main/res/layout/enter_workout_line.xml
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
~
|
||||||
|
~ This file is part of FitoTrack
|
||||||
|
~
|
||||||
|
~ FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_marginLeft="-15dp"
|
||||||
|
android:layout_marginRight="-15dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:background="?android:selectableItemBackground">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:paddingStart="15dp"
|
||||||
|
android:paddingEnd="15dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/lineKey"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Medium" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/lineViewRoot"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toStartOf="@+id/lineValue"
|
||||||
|
android:layout_toEndOf="@+id/lineKey"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:gravity="right|center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/lineValue"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:textAlignment="textEnd"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Medium" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?android:dividerHorizontal" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
~
|
||||||
|
~ This file is part of FitoTrack
|
||||||
|
~
|
||||||
|
~ FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@android:id/text1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableStart="?android:attr/listChoiceIndicatorSingle"
|
||||||
|
android:drawablePadding="20dp"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:minHeight="48dip"
|
||||||
|
android:paddingStart="20dp"
|
||||||
|
android:paddingEnd="24dp"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Medium"
|
||||||
|
android:textColor="?android:attr/textColorAlertDialogListItem" />
|
||||||
@ -41,7 +41,7 @@
|
|||||||
android:fontFamily="sans-serif-black"
|
android:fontFamily="sans-serif-black"
|
||||||
android:text=""
|
android:text=""
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:textColor="@color/textColorLight"
|
android:textColor="?android:textColorSecondary"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -51,7 +51,7 @@
|
|||||||
android:fontFamily="sans-serif-black"
|
android:fontFamily="sans-serif-black"
|
||||||
android:text=""
|
android:text=""
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@color/textLighterBlack"
|
android:textColor="?android:textColorPrimary"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@ -73,7 +73,7 @@
|
|||||||
android:fontFamily="sans-serif-black"
|
android:fontFamily="sans-serif-black"
|
||||||
android:text=""
|
android:text=""
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:textColor="@color/textColorLight"
|
android:textColor="?android:textColorSecondary"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -83,7 +83,7 @@
|
|||||||
android:fontFamily="sans-serif-black"
|
android:fontFamily="sans-serif-black"
|
||||||
android:text=""
|
android:text=""
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@color/textLighterBlack"
|
android:textColor="?android:textColorPrimary"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="Aug 19, 2019 20:15"
|
android:text="Aug 19, 2019 20:15"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:textColor="@color/textLighterBlack"
|
android:textColor="?android:textColorPrimary"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
@ -80,7 +80,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="27min"
|
android:text="27min"
|
||||||
android:textColor="@color/textLighterBlack"
|
android:textColor="?android:textColorPrimary"
|
||||||
android:textSize="30sp" />
|
android:textSize="30sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
27
app/src/main/res/menu/enter_workout_menu.xml
Normal file
27
app/src/main/res/menu/enter_workout_menu.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
~
|
||||||
|
~ This file is part of FitoTrack
|
||||||
|
~
|
||||||
|
~ FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/actionEnterWorkoutAdd"
|
||||||
|
android:icon="@drawable/ic_add_white"
|
||||||
|
android:showAsAction="always"
|
||||||
|
android:title="@string/save" />
|
||||||
|
</menu>
|
||||||
65341
app/src/main/res/raw/geoids.csv
Normal file
65341
app/src/main/res/raw/geoids.csv
Normal file
File diff suppressed because it is too large
Load Diff
@ -129,4 +129,20 @@
|
|||||||
<string name="savedToDownloads">Im Downloadordner gespeichert</string>
|
<string name="savedToDownloads">Im Downloadordner gespeichert</string>
|
||||||
<string name="savingFailed">Speichern fehlgeschlagen</string>
|
<string name="savingFailed">Speichern fehlgeschlagen</string>
|
||||||
<string name="share">Teilen</string>
|
<string name="share">Teilen</string>
|
||||||
|
<string name="timeMinuteShort">min</string>
|
||||||
|
<string name="timeHourShort">h</string>
|
||||||
|
<string name="timeSecondsShort">s</string>
|
||||||
|
<string name="errorEnterValidNumber">Gebe eine gültige Zahl ein</string>
|
||||||
|
<string name="errorWorkoutAddFuture">Das Workout kann sich nicht in der Zukunft befinden</string>
|
||||||
|
<string name="errorEnterValidDuration">Gebe eine gültige Dauer ein</string>
|
||||||
|
<string name="workoutEdited">Dieses Workout wurde bearbeitet.</string>
|
||||||
|
<string name="workoutTypeOther">Anderes</string>
|
||||||
|
<string name="type">Typ</string>
|
||||||
|
<string name="enterWorkout">Workout eingeben</string>
|
||||||
|
<string name="setDuration">Dauer setzen</string>
|
||||||
|
<string name="info">Info</string>
|
||||||
|
<string name="OpenStreetMapAttribution">© OpenStreetMap Mitwirkende</string>
|
||||||
|
<string name="theme">Thema</string>
|
||||||
|
<string name="hintRestart">Bitte die App neustarten, damit die Änderungen wirksam werden</string>
|
||||||
|
<string name="noComment">Kein Kommentar</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
27
app/src/main/res/values-de/theme_setting.xml
Normal file
27
app/src/main/res/values-de/theme_setting.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
~
|
||||||
|
~ This file is part of FitoTrack
|
||||||
|
~
|
||||||
|
~ FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string-array name="pref_theme_setting">
|
||||||
|
<item>Hell</item>
|
||||||
|
<item>Dunkel</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@ -50,10 +50,17 @@
|
|||||||
|
|
||||||
<string name="timeMinuteSingular">Perc</string>
|
<string name="timeMinuteSingular">Perc</string>
|
||||||
<string name="timeMinutePlural">Perc</string>
|
<string name="timeMinutePlural">Perc</string>
|
||||||
|
<string name="timeMinuteShort">p</string>
|
||||||
<string name="timeHourSingular">Óra</string>
|
<string name="timeHourSingular">Óra</string>
|
||||||
<string name="timeHourPlural">Óra</string>
|
<string name="timeHourPlural">Óra</string>
|
||||||
|
<string name="timeHourShort">ó</string>
|
||||||
|
<string name="timeSecondsShort">mp</string>
|
||||||
<string name="and">és</string>
|
<string name="and">és</string>
|
||||||
|
|
||||||
|
<string name="errorEnterValidNumber">Adjon meg egy érvényes számot</string>
|
||||||
|
<string name="errorWorkoutAddFuture">Az edzés nem lehet a jövőben</string>
|
||||||
|
<string name="errorEnterValidDuration">Adjon meg egy érvényes időtartamot</string>
|
||||||
|
|
||||||
<string name="announcementGPSStatus">GPS állapota</string>
|
<string name="announcementGPSStatus">GPS állapota</string>
|
||||||
|
|
||||||
<string name="voiceAnnouncementsTitle">Hangos közlemények</string>
|
<string name="voiceAnnouncementsTitle">Hangos közlemények</string>
|
||||||
@ -84,6 +91,7 @@
|
|||||||
<string name="workoutBurnedEnergy">Elégetett energia</string>
|
<string name="workoutBurnedEnergy">Elégetett energia</string>
|
||||||
<string name="workoutTotalEnergy">Összes energia</string>
|
<string name="workoutTotalEnergy">Összes energia</string>
|
||||||
<string name="workoutEnergyConsumption">Energiafogyasztás</string>
|
<string name="workoutEnergyConsumption">Energiafogyasztás</string>
|
||||||
|
<string name="workoutEdited">Ez az edzés szerkesztve lett.</string>
|
||||||
<string name="uploading">Feltöltés</string>
|
<string name="uploading">Feltöltés</string>
|
||||||
<string name="enterVerificationCode">Hitelesítési kód megadása</string>
|
<string name="enterVerificationCode">Hitelesítési kód megadása</string>
|
||||||
<string name="authenticationFailed">A hitelesítés sikertelen.</string>
|
<string name="authenticationFailed">A hitelesítés sikertelen.</string>
|
||||||
@ -103,7 +111,14 @@
|
|||||||
<string name="workoutTypeJogging">Kocogás</string>
|
<string name="workoutTypeJogging">Kocogás</string>
|
||||||
<string name="workoutTypeCycling">Kerékpározás</string>
|
<string name="workoutTypeCycling">Kerékpározás</string>
|
||||||
<string name="workoutTypeHiking">Túrázás</string>
|
<string name="workoutTypeHiking">Túrázás</string>
|
||||||
|
<string name="workoutTypeOther">Egyéb</string>
|
||||||
<string name="workoutTypeUnknown">Ismeretlen</string>
|
<string name="workoutTypeUnknown">Ismeretlen</string>
|
||||||
|
<string name="type">Típus</string>
|
||||||
|
|
||||||
|
<string name="enterWorkout">Edzés megadása</string>
|
||||||
|
|
||||||
|
<string name="setDuration">Időtartam beállítása</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="recordWorkout">Edzés rögzítése</string>
|
<string name="recordWorkout">Edzés rögzítése</string>
|
||||||
|
|
||||||
@ -156,4 +171,9 @@
|
|||||||
<string name="share">Megosztás</string>
|
<string name="share">Megosztás</string>
|
||||||
<string name="savedToDownloads">Elmentve a letöltésekbe</string>
|
<string name="savedToDownloads">Elmentve a letöltésekbe</string>
|
||||||
<string name="savingFailed">A mentés sikertelen</string>
|
<string name="savingFailed">A mentés sikertelen</string>
|
||||||
|
<string name="info">Információ</string>
|
||||||
|
<string name="OpenStreetMapAttribution">© OpenStreetMap közreműködők</string>
|
||||||
|
<string name="theme">Téma</string>
|
||||||
|
<string name="hintRestart">Indítsa újra az alkalmazást a változtatások alkalmazásához</string>
|
||||||
|
<string name="noComment">Nincs megjegyzés</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
28
app/src/main/res/values-hu/theme_setting.xml
Normal file
28
app/src/main/res/values-hu/theme_setting.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
~ Copyright (c) 2020 Balázs Úr <balazs@urbalazs.hu>
|
||||||
|
~
|
||||||
|
~ This file is part of FitoTrack
|
||||||
|
~
|
||||||
|
~ FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string-array name="pref_theme_setting">
|
||||||
|
<item>Világos</item>
|
||||||
|
<item>Sötét</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@ -97,11 +97,11 @@
|
|||||||
<string name="height">Hoogte</string>
|
<string name="height">Hoogte</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="workoutTypeRunning">Rennen</string>
|
<string name="workoutTypeRunning">Hardlopen</string>
|
||||||
<string name="workoutTypeWalking">Lopen</string>
|
<string name="workoutTypeWalking">Wandelen</string>
|
||||||
<string name="workoutTypeJogging">Joggen</string>
|
<string name="workoutTypeJogging">Joggen</string>
|
||||||
<string name="workoutTypeCycling">Fietsen</string>
|
<string name="workoutTypeCycling">Fietsen</string>
|
||||||
<string name="workoutTypeHiking">Hiking</string>
|
<string name="workoutTypeHiking">Bergwandelen</string>
|
||||||
<string name="workoutTypeUnknown">Onbekend</string>
|
<string name="workoutTypeUnknown">Onbekend</string>
|
||||||
|
|
||||||
<string name="recordWorkout">Training opnemen</string>
|
<string name="recordWorkout">Training opnemen</string>
|
||||||
|
|||||||
@ -27,6 +27,9 @@
|
|||||||
<color name="colorPrimaryBicycling">#523220</color>
|
<color name="colorPrimaryBicycling">#523220</color>
|
||||||
<color name="colorPrimaryDarkBicycling">#462A1D</color>
|
<color name="colorPrimaryDarkBicycling">#462A1D</color>
|
||||||
|
|
||||||
|
<color name="colorPrimaryBicyclingLighter">#6E422A</color>
|
||||||
|
<color name="colorPrimaryDarkBicyclingLighter">#5A3625</color>
|
||||||
|
|
||||||
<color name="colorAccent">#4CAF50</color>
|
<color name="colorAccent">#4CAF50</color>
|
||||||
<color name="colorAccentDark">#2E7D32</color>
|
<color name="colorAccentDark">#2E7D32</color>
|
||||||
|
|
||||||
@ -34,5 +37,6 @@
|
|||||||
<color name="colorPrimaryDarkHiking">#007267</color>
|
<color name="colorPrimaryDarkHiking">#007267</color>
|
||||||
|
|
||||||
<color name="textLighterBlack">#C8000000</color>
|
<color name="textLighterBlack">#C8000000</color>
|
||||||
|
<color name="textDarkerWhite">#C8FFFFFF</color>
|
||||||
<color name="textColorLight">#C8414141</color>
|
<color name="textColorLight">#C8414141</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@ -49,10 +49,17 @@
|
|||||||
|
|
||||||
<string name="timeMinuteSingular">Minute</string>
|
<string name="timeMinuteSingular">Minute</string>
|
||||||
<string name="timeMinutePlural">Minutes</string>
|
<string name="timeMinutePlural">Minutes</string>
|
||||||
|
<string name="timeMinuteShort">min</string>
|
||||||
<string name="timeHourSingular">Hour</string>
|
<string name="timeHourSingular">Hour</string>
|
||||||
<string name="timeHourPlural">Hours</string>
|
<string name="timeHourPlural">Hours</string>
|
||||||
|
<string name="timeHourShort">h</string>
|
||||||
|
<string name="timeSecondsShort">s</string>
|
||||||
<string name="and">and</string>
|
<string name="and">and</string>
|
||||||
|
|
||||||
|
<string name="errorEnterValidNumber">Enter a valid number</string>
|
||||||
|
<string name="errorWorkoutAddFuture">The workout cannot be in the future</string>
|
||||||
|
<string name="errorEnterValidDuration">Enter a valid duration</string>
|
||||||
|
|
||||||
<string name="announcementGPSStatus">GPS Status</string>
|
<string name="announcementGPSStatus">GPS Status</string>
|
||||||
|
|
||||||
<string name="voiceAnnouncementsTitle">Voice Announcements</string>
|
<string name="voiceAnnouncementsTitle">Voice Announcements</string>
|
||||||
@ -83,6 +90,7 @@
|
|||||||
<string name="workoutBurnedEnergy">Burned Energy</string>
|
<string name="workoutBurnedEnergy">Burned Energy</string>
|
||||||
<string name="workoutTotalEnergy">Total Energy</string>
|
<string name="workoutTotalEnergy">Total Energy</string>
|
||||||
<string name="workoutEnergyConsumption">Energy Consumption</string>
|
<string name="workoutEnergyConsumption">Energy Consumption</string>
|
||||||
|
<string name="workoutEdited">This workout has been edited.</string>
|
||||||
<string name="uploading">Uploading</string>
|
<string name="uploading">Uploading</string>
|
||||||
<string name="enterVerificationCode">Enter Verification Code</string>
|
<string name="enterVerificationCode">Enter Verification Code</string>
|
||||||
<string name="authenticationFailed">Authentication failed.</string>
|
<string name="authenticationFailed">Authentication failed.</string>
|
||||||
@ -102,7 +110,14 @@
|
|||||||
<string name="workoutTypeJogging">Jogging</string>
|
<string name="workoutTypeJogging">Jogging</string>
|
||||||
<string name="workoutTypeCycling">Cycling</string>
|
<string name="workoutTypeCycling">Cycling</string>
|
||||||
<string name="workoutTypeHiking">Hiking</string>
|
<string name="workoutTypeHiking">Hiking</string>
|
||||||
|
<string name="workoutTypeOther">Other</string>
|
||||||
<string name="workoutTypeUnknown">Unknown</string>
|
<string name="workoutTypeUnknown">Unknown</string>
|
||||||
|
<string name="type">Type</string>
|
||||||
|
|
||||||
|
<string name="enterWorkout">Enter Workout</string>
|
||||||
|
|
||||||
|
<string name="setDuration">Set Duration</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="recordWorkout">Record Workout</string>
|
<string name="recordWorkout">Record Workout</string>
|
||||||
|
|
||||||
@ -155,4 +170,9 @@
|
|||||||
<string name="share">Share</string>
|
<string name="share">Share</string>
|
||||||
<string name="savedToDownloads">Saved to Downloads</string>
|
<string name="savedToDownloads">Saved to Downloads</string>
|
||||||
<string name="savingFailed">Saving failed</string>
|
<string name="savingFailed">Saving failed</string>
|
||||||
|
<string name="info">Info</string>
|
||||||
|
<string name="OpenStreetMapAttribution">© OpenStreetMap contributors</string>
|
||||||
|
<string name="theme">Theme</string>
|
||||||
|
<string name="hintRestart">Please restart the app to apply changes</string>
|
||||||
|
<string name="noComment">No comment</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
~ Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
~
|
~
|
||||||
~ This file is part of FitoTrack
|
~ This file is part of FitoTrack
|
||||||
~
|
~
|
||||||
@ -20,42 +20,54 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="AppThemeNoActionbar" parent="android:Theme.Material.Light.NoActionBar">
|
<style name="AppThemeNoActionbar" parent="android:Theme.Material.Light.NoActionBar">
|
||||||
<!-- Customize your theme here. -->
|
|
||||||
<item name="android:colorPrimary">@color/colorPrimary</item>
|
<item name="android:colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
<item name="android:colorAccent">@color/colorAccent</item>
|
<item name="android:colorAccent">@color/colorAccent</item>
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Base application theme. -->
|
|
||||||
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
|
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
|
||||||
<!-- Custom<color name="colorPrimaryBicycling">#523220</color>
|
|
||||||
<color name="colorPrimaryDarkBicycling">#462A1D</color>ize your theme here. -->
|
|
||||||
<item name="android:colorPrimary">@color/colorPrimary</item>
|
<item name="android:colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
<item name="android:colorAccent">@color/colorAccent</item>
|
<item name="android:colorAccent">@color/colorAccent</item>
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Base application theme. -->
|
|
||||||
<style name="Running" parent="AppTheme">
|
<style name="Running" parent="AppTheme">
|
||||||
<!-- Customize your theme here. -->
|
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryRunning</item>
|
<item name="android:colorPrimary">@color/colorPrimaryRunning</item>
|
||||||
<item name="android:colorPrimaryDark">@color/colorPrimaryDarkRunning</item>
|
<item name="android:colorPrimaryDark">@color/colorPrimaryDarkRunning</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Base application theme. -->
|
|
||||||
<style name="Bicycling" parent="AppTheme">
|
<style name="Bicycling" parent="AppTheme">
|
||||||
<!-- Customize your theme here. -->
|
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryBicycling</item>
|
<item name="android:colorPrimary">@color/colorPrimaryBicycling</item>
|
||||||
<item name="android:colorPrimaryDark">@color/colorPrimaryDarkBicycling</item>
|
<item name="android:colorPrimaryDark">@color/colorPrimaryDarkBicycling</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Base application theme. -->
|
|
||||||
<style name="Hiking" parent="AppTheme">
|
<style name="Hiking" parent="AppTheme">
|
||||||
<!-- Customize your theme here. -->
|
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryHiking</item>
|
<item name="android:colorPrimary">@color/colorPrimaryHiking</item>
|
||||||
<item name="android:colorPrimaryDark">@color/colorPrimaryDarkHiking</item>
|
<item name="android:colorPrimaryDark">@color/colorPrimaryDarkHiking</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<style name="AppThemeDark" parent="android:Theme.Material">
|
||||||
|
<item name="android:colorPrimary">@color/colorPrimary</item>
|
||||||
|
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
<item name="android:colorAccent">@color/colorAccent</item>
|
||||||
|
<item name="android:windowBackground">@android:color/black</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="RunningDark" parent="AppThemeDark">
|
||||||
|
<item name="android:colorPrimary">@color/colorPrimaryRunning</item>
|
||||||
|
<item name="android:colorPrimaryDark">@color/colorPrimaryDarkRunning</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="BicyclingDark" parent="AppThemeDark">
|
||||||
|
<item name="android:colorPrimary">@color/colorPrimaryBicycling</item>
|
||||||
|
<item name="android:colorPrimaryDark">@color/colorPrimaryDarkBicycling</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="HikingDark" parent="AppThemeDark">
|
||||||
|
<item name="android:colorPrimary">@color/colorPrimaryHiking</item>
|
||||||
|
<item name="android:colorPrimaryDark">@color/colorPrimaryDarkHiking</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
32
app/src/main/res/values/theme_setting.xml
Normal file
32
app/src/main/res/values/theme_setting.xml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
~
|
||||||
|
~ This file is part of FitoTrack
|
||||||
|
~
|
||||||
|
~ FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string-array name="pref_theme_setting">
|
||||||
|
<item>Light</item>
|
||||||
|
<item>Dark</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="pref_theme_setting_values">
|
||||||
|
<item>0</item>
|
||||||
|
<item>1</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@ -33,6 +33,13 @@
|
|||||||
android:summary="@string/pref_weight_summary"
|
android:summary="@string/pref_weight_summary"
|
||||||
android:title="@string/pref_weight" />
|
android:title="@string/pref_weight" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:entries="@array/pref_theme_setting"
|
||||||
|
android:entryValues="@array/pref_theme_setting_values"
|
||||||
|
android:key="themeSetting"
|
||||||
|
android:title="@string/theme" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="osm.mapnik"
|
android:defaultValue="osm.mapnik"
|
||||||
android:entries="@array/pref_map_layers"
|
android:entries="@array/pref_map_layers"
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import org.junit.Assert;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import de.tadris.fitness.data.Workout;
|
import de.tadris.fitness.data.Workout;
|
||||||
|
import de.tadris.fitness.data.WorkoutType;
|
||||||
import de.tadris.fitness.util.CalorieCalculator;
|
import de.tadris.fitness.util.CalorieCalculator;
|
||||||
|
|
||||||
public class CalorieCalculatorTest {
|
public class CalorieCalculatorTest {
|
||||||
@ -31,7 +32,7 @@ public class CalorieCalculatorTest {
|
|||||||
public void testCalculation() {
|
public void testCalculation() {
|
||||||
Workout workout = new Workout();
|
Workout workout = new Workout();
|
||||||
workout.avgSpeed = 2.7d;
|
workout.avgSpeed = 2.7d;
|
||||||
workout.workoutType = Workout.WORKOUT_TYPE_RUNNING;
|
workout.setWorkoutType(WorkoutType.RUNNING);
|
||||||
workout.duration = 1000L * 60 * 10;
|
workout.duration = 1000L * 60 * 10;
|
||||||
int calorie = CalorieCalculator.calculateCalories(workout, 80);
|
int calorie = CalorieCalculator.calculateCalories(workout, 80);
|
||||||
System.out.println("Calories: " + calorie);
|
System.out.println("Calories: " + calorie);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
* Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
*
|
*
|
||||||
* This file is part of FitoTrack
|
* This file is part of FitoTrack
|
||||||
*
|
*
|
||||||
@ -26,7 +26,7 @@ buildscript {
|
|||||||
|
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
classpath 'com.android.tools.build:gradle:3.6.1'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|||||||
19
gradle.properties
Normal file
19
gradle.properties
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2020 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
#
|
||||||
|
# This file is part of FitoTrack
|
||||||
|
#
|
||||||
|
# FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
android.useAndroidX=true
|
||||||
16
metadata/en-US/changelogs/500.txt
Normal file
16
metadata/en-US/changelogs/500.txt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
New features:
|
||||||
|
- Manually add workouts (#53)
|
||||||
|
- Dark Mode (#48)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Altitude correction
|
||||||
|
- Detect bluetooth headsets (#51)
|
||||||
|
- Show recording on lock screen (#45)
|
||||||
|
- OpenStreetMap attribution in the record screen (#52)
|
||||||
|
|
||||||
|
Bug-Fixes:
|
||||||
|
- Wrong speed values after GPS-signal was lost for some time (#47)
|
||||||
|
|
||||||
|
Localisation:
|
||||||
|
- update Dutch thanks to albertheres and didierm (#57, #58)
|
||||||
|
- update Hungarian thanks to urbalazs (#59)
|
||||||
@ -1 +1 @@
|
|||||||
Een Fitness Tracker die je privacy respecteerd
|
Een Fitness Tracker die je privacy respecteert
|
||||||
Loading…
x
Reference in New Issue
Block a user