Implements most of of the changes proposed by @TacoTheDank (thank you!) in this pull request (see https://github.com/y20k/trackbook/pull/91)

master
y20k 2020-11-18 18:19:52 +01:00
parent 1b69980491
commit eb296188d8
No known key found for this signature in database
GPG Key ID: 824D4259F41FAFF6
16 changed files with 79 additions and 76 deletions

View File

@ -10,8 +10,8 @@ android {
applicationId 'org.y20k.trackbook'
minSdkVersion 25
targetSdkVersion 30
versionCode 46
versionName '2.0.9'
versionCode 47
versionName '2.0.10'
resConfigs "en", "da", "de", "fr", "hr", "id", "it", "ja", "nb-rNO", "nl", "pt-rBR", "sv", "tr", "zh-rCN"
}
@ -52,17 +52,17 @@ android {
dependencies {
// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'
// AndroidX
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.core:core-ktx:1.3.2'
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
implementation 'androidx.preference:preference-ktx:1.1.1'
implementation 'com.google.android.material:material:1.2.0-rc01'
implementation 'com.google.android.material:material:1.2.1'
// Gson
implementation 'com.google.code.gson:gson:2.8.6'

View File

@ -77,12 +77,12 @@ class MainActivity : AppCompatActivity() {
navHostFragment.navController.addOnDestinationChangedListener { _, destination, _ ->
when (destination.id) {
R.id.fragment_track -> {
runOnUiThread( Runnable() {
run(){
runOnUiThread {
run {
// mark menu item "Tracks" as checked
bottomNavigationView.menu.findItem(R.id.tracklist_fragment).setChecked(true)
bottomNavigationView.menu.findItem(R.id.tracklist_fragment).isChecked = true
}
})
}
}
else -> {
// do nothing

View File

@ -48,8 +48,8 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
// set the background color
view.setBackgroundColor(resources.getColor(R.color.app_window_background, null))
// add padding - necessary because translucent status bar is used
val topPadding = UiHelper.getStatusBarHeight(activity as Context)
view.setPadding(0, topPadding.toInt(), 0, 0)
val topPadding: Int = UiHelper.getStatusBarHeight(activity as Context)
view.setPadding(0, topPadding, 0, 0)
}
@ -88,7 +88,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
preferenceThemeSelection.setOnPreferenceChangeListener { preference, newValue ->
if (preference is ListPreference) {
val index: Int = preference.entryValues.indexOf(newValue)
preferenceThemeSelection.summary = "${getString(R.string.pref_theme_selection_summary)} ${preference.entries.get(index)}"
preferenceThemeSelection.summary = "${getString(R.string.pref_theme_selection_summary)} ${preference.entries[index]}"
return@setOnPreferenceChangeListener true
} else {
return@setOnPreferenceChangeListener false

View File

@ -185,7 +185,7 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi
try {
startActivityForResult(intent, Keys.REQUEST_SAVE_GPX)
} catch (e: Exception) {
LogHelper.e(TAG, "Unable to save GPX. ")
LogHelper.e(TAG, "Unable to save GPX.")
Toast.makeText(activity as Context, R.string.toast_message_install_file_helper, Toast.LENGTH_LONG).show()
}
}

View File

@ -48,7 +48,7 @@ import kotlin.coroutines.CoroutineContext
/*
* TrackerService class
*/
class TrackerService(): Service(), CoroutineScope, SensorEventListener {
class TrackerService: Service(), CoroutineScope, SensorEventListener {
/* Define log tag */
private val TAG: String = LogHelper.makeLogTag(TrackerService::class.java)
@ -210,7 +210,7 @@ class TrackerService(): Service(), CoroutineScope, SensorEventListener {
// try to mark last waypoint as stopover
if (track.wayPoints.size > 0) {
val lastWayPointIndex = track.wayPoints.size - 1
track.wayPoints.get(lastWayPointIndex).isStopOver = true
track.wayPoints[lastWayPointIndex].isStopOver = true
}
// set resumed flag
resumed = true

View File

@ -31,7 +31,7 @@ import org.y20k.trackbook.helpers.PreferencesHelper
/*
* TrackingToggleTileService class
*/
class TrackingToggleTileService(): TileService() {
class TrackingToggleTileService: TileService() {
/* Define log tag */
private val TAG: String = LogHelper.makeLogTag(TrackingToggleTileService::class.java)

View File

@ -24,6 +24,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.DefaultItemAnimator
@ -68,8 +69,8 @@ class TracklistFragment : Fragment(), TracklistAdapter.TracklistAdapterListener,
tracklistOnboarding = rootView.findViewById(R.id.track_list_onboarding)
// add padding - necessary because translucent status bar is used
val topPadding = UiHelper.getStatusBarHeight(activity as Context)
trackElementList.setPadding(0, topPadding.toInt(), 0, 0)
val topPadding: Int = UiHelper.getStatusBarHeight(activity as Context)
trackElementList.setPadding(0, topPadding, 0, 0)
// set up recycler view
trackElementList.layoutManager = CustomLinearLayoutManager(activity as Context)
@ -97,11 +98,12 @@ class TracklistFragment : Fragment(), TracklistAdapter.TracklistAdapterListener,
/* Overrides onTrackElementTapped from TracklistElementAdapterListener */
override fun onTrackElementTapped(tracklistElement: TracklistElement) {
val bundle: Bundle = Bundle()
bundle.putString(Keys.ARG_TRACK_TITLE, tracklistElement.name)
bundle.putString(Keys.ARG_TRACK_FILE_URI, tracklistElement.trackUriString)
bundle.putString(Keys.ARG_GPX_FILE_URI, tracklistElement.gpxUriString)
bundle.putLong(Keys.ARG_TRACK_ID, TrackHelper.getTrackId(tracklistElement))
val bundle: Bundle = bundleOf(
Keys.ARG_TRACK_TITLE to tracklistElement.name,
Keys.ARG_TRACK_FILE_URI to tracklistElement.trackUriString,
Keys.ARG_GPX_FILE_URI to tracklistElement.gpxUriString,
Keys.ARG_TRACK_ID to TrackHelper.getTrackId(tracklistElement)
)
findNavController().navigate(R.id.fragment_track, bundle)
}

View File

@ -23,6 +23,8 @@ import android.text.method.ScrollingMovementMethod
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.y20k.trackbook.R
import org.y20k.trackbook.helpers.LogHelper
@ -56,25 +58,23 @@ object ErrorDialog {
builder.setView(view)
// set detail view
if (errorDetails.isNotEmpty()) {
// show details link
errorDetailsLinkView.visibility = View.VISIBLE
val detailsNotEmpty = errorDetails.isNotEmpty()
// show/hide details link depending on whether details are empty or not
errorDetailsLinkView.isVisible = detailsNotEmpty
if (detailsNotEmpty) {
// allow scrolling on details view
errorDetailsView.movementMethod = ScrollingMovementMethod()
// show and hide details on click
errorDetailsLinkView.setOnClickListener {
when (errorDetailsView.visibility) {
View.GONE -> errorDetailsView.visibility = View.VISIBLE
View.VISIBLE -> errorDetailsView.visibility = View.GONE
View.GONE -> errorDetailsView.isVisible = true
View.VISIBLE -> errorDetailsView.isGone = true
}
}
// set details text view
errorDetailsView.text = errorDetails
} else {
// hide details link
errorDetailsLinkView.visibility = View.GONE
}
// set text views

View File

@ -84,7 +84,7 @@ class YesNoDialog (private var yesNoDialogListener: YesNoDialogListener) {
}
// handle outside-click as "no"
builder.setOnCancelListener(){
builder.setOnCancelListener{
yesNoDialogListener.onYesNoDialog(type, false, payload, payloadString)
}

View File

@ -34,7 +34,7 @@ object DateTimeHelper {
/* Converts milliseconds to mm:ss or hh:mm:ss */
fun convertToReadableTime(context: Context, milliseconds: Long): String {
var timeString: String = String()
val timeString: String
val hours: Long = TimeUnit.MILLISECONDS.toHours(milliseconds)
val minutes: Long = TimeUnit.MILLISECONDS.toMinutes(milliseconds) % TimeUnit.HOURS.toMinutes(1)
val seconds: Long = TimeUnit.MILLISECONDS.toSeconds(milliseconds) % TimeUnit.MINUTES.toSeconds(1)

View File

@ -35,6 +35,8 @@ import java.text.NumberFormat
import java.util.*
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import kotlin.math.ln
import kotlin.math.pow
/*
@ -259,13 +261,13 @@ object FileHelper {
val jsonString: String = getTrackJsonString(track)
if (jsonString.isNotBlank()) {
// write track file
writeTextFile(jsonString, Uri.parse(track.trackUriString))
writeTextFile(jsonString, track.trackUriString.toUri())
}
if (saveGpxToo) {
val gpxString: String = TrackHelper.createGpxString(track)
if (gpxString.isNotBlank()) {
// write GPX file
writeTextFile(gpxString, Uri.parse(track.gpxUriString))
writeTextFile(gpxString, track.gpxUriString.toUri())
}
}
}
@ -401,13 +403,13 @@ object FileHelper {
if (bytes < unit) return "$bytes B"
// calculate exp
val exp: Int = (Math.log(bytes.toDouble()) / Math.log(unit.toDouble())).toInt()
val exp: Int = (ln(bytes.toDouble()) / ln(unit.toDouble())).toInt()
// determine prefix symbol
val prefix: String = ((if (si) "kMGTPE" else "KMGTPE")[exp - 1] + if (si) "" else "i")
// calculate result and set number format
val result: Double = bytes / Math.pow(unit.toDouble(), exp.toDouble())
val result: Double = bytes / unit.toDouble().pow(exp.toDouble())
val numberFormat = NumberFormat.getNumberInstance()
numberFormat.maximumFractionDigits = 1

View File

@ -20,6 +20,7 @@ package org.y20k.trackbook.helpers
import android.content.Context
import android.location.Location
import android.location.LocationManager
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import org.y20k.trackbook.Keys
import org.y20k.trackbook.extensions.getDouble
@ -48,10 +49,8 @@ object PreferencesHelper {
fun saveZoomLevel(context: Context, zoomLevel: Double) {
// get preferences
val settings = PreferenceManager.getDefaultSharedPreferences(context)
val editor = settings.edit()
// save zoom level
editor.putDouble(Keys.PREF_MAP_ZOOM_LEVEL, zoomLevel)
editor.apply()
settings.edit { putDouble(Keys.PREF_MAP_ZOOM_LEVEL, zoomLevel) }
}
@ -68,10 +67,8 @@ object PreferencesHelper {
fun saveTrackingState(context: Context, trackingState: Int) {
// get preferences
val settings = PreferenceManager.getDefaultSharedPreferences(context)
val editor = settings.edit()
// save tracking state
editor.putInt(Keys.PREF_TRACKING_STATE, trackingState)
editor.apply()
settings.edit { putInt(Keys.PREF_TRACKING_STATE, trackingState) }
}
@ -122,14 +119,14 @@ object PreferencesHelper {
fun saveCurrentBestLocation(context: Context, currentBestLocation: Location) {
// get preferences
val settings = PreferenceManager.getDefaultSharedPreferences(context)
val editor = settings.edit()
// save location
editor.putDouble(Keys.PREF_CURRENT_BEST_LOCATION_LATITUDE, currentBestLocation.latitude)
editor.putDouble(Keys.PREF_CURRENT_BEST_LOCATION_LONGITUDE, currentBestLocation.longitude)
editor.putFloat(Keys.PREF_CURRENT_BEST_LOCATION_ACCURACY, currentBestLocation.accuracy)
editor.putDouble(Keys.PREF_CURRENT_BEST_LOCATION_ALTITUDE, currentBestLocation.altitude)
editor.putLong(Keys.PREF_CURRENT_BEST_LOCATION_TIME, currentBestLocation.time)
editor.apply()
settings.edit {
// save location
putDouble(Keys.PREF_CURRENT_BEST_LOCATION_LATITUDE, currentBestLocation.latitude)
putDouble(Keys.PREF_CURRENT_BEST_LOCATION_LONGITUDE, currentBestLocation.longitude)
putFloat(Keys.PREF_CURRENT_BEST_LOCATION_ACCURACY, currentBestLocation.accuracy)
putDouble(Keys.PREF_CURRENT_BEST_LOCATION_ALTITUDE, currentBestLocation.altitude)
putLong(Keys.PREF_CURRENT_BEST_LOCATION_TIME, currentBestLocation.time)
}
}
@ -149,9 +146,7 @@ object PreferencesHelper {
/* Saves state of housekeeping */
fun saveHouseKeepingNecessaryState(context: Context, state: Boolean = false) {
val settings = PreferenceManager.getDefaultSharedPreferences(context)
val editor = settings.edit()
editor.putBoolean(Keys.PREF_ONE_TIME_HOUSEKEEPING_NECESSARY, state)
editor.apply()
settings.edit { putBoolean(Keys.PREF_ONE_TIME_HOUSEKEEPING_NECESSARY, state) }
}
}

View File

@ -181,11 +181,11 @@ object TrackHelper {
/* Creates name for GPX file */
private fun createGpxName(track: Track): String {
val gpxName = StringBuilder("")
gpxName.append("\t<metadata>\n");
gpxName.append("\t<metadata>\n")
gpxName.append("\t\t<name>")
gpxName.append("Trackbook Recording: ${track.name}")
gpxName.append("</name>\n")
gpxName.append("\t</metadata>\n");
gpxName.append("\t</metadata>\n")
return gpxName.toString()
}

View File

@ -28,6 +28,8 @@ import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.Group
import androidx.core.content.ContextCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import org.osmdroid.api.IMapController
@ -145,7 +147,7 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
/* Save current best location and state of map to shared preferences */
fun saveState(currentBestLocation: Location) {
PreferencesHelper.saveCurrentBestLocation(context, currentBestLocation)
PreferencesHelper.saveZoomLevel(context, mapView.getZoomLevelDouble())
PreferencesHelper.saveZoomLevel(context, mapView.zoomLevelDouble)
// reset user interaction state
userInteraction = false
}
@ -176,11 +178,11 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
when (trackingState) {
Keys.STATE_TRACKING_NOT -> {
recordingButton.setImageResource(R.drawable.ic_fiber_manual_record_white_24dp)
recordingButtonSubMenu.visibility = View.GONE
recordingButtonSubMenu.isGone = true
}
Keys.STATE_TRACKING_ACTIVE -> {
recordingButton.setImageResource(R.drawable.ic_fiber_manual_record_red_24dp)
recordingButtonSubMenu.visibility = View.GONE
recordingButtonSubMenu.isGone = true
}
Keys.STATE_TRACKING_STOPPED -> {
recordingButton.setImageResource(R.drawable.ic_save_white_24dp)
@ -192,8 +194,8 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
/* Toggles visibility of recording button sub menu_bottom_navigation */
fun toggleRecordingButtonSubMenu() {
when (recordingButtonSubMenu.visibility) {
View.VISIBLE -> recordingButtonSubMenu.visibility = View.GONE
else -> recordingButtonSubMenu.visibility = View.VISIBLE
View.VISIBLE -> recordingButtonSubMenu.isGone = true
else -> recordingButtonSubMenu.isVisible = true
}
}

View File

@ -25,6 +25,8 @@ import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.Toast
import androidx.constraintlayout.widget.Group
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.widget.NestedScrollView
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.textview.MaterialTextView
@ -210,12 +212,12 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
// show / hide recording pause
if (track.recordingPaused != 0L) {
recordingPausedLabelView.visibility = View.VISIBLE
recordingPausedView.visibility = View.VISIBLE
recordingPausedLabelView.isVisible = true
recordingPausedView.isVisible = true
recordingPausedView.text = DateTimeHelper.convertToReadableTime(context, track.recordingPaused)
} else {
recordingPausedLabelView.visibility = View.GONE
recordingPausedView.visibility = View.GONE
recordingPausedLabelView.isGone = true
recordingPausedView.isGone = true
}
// inform user about possible accuracy issues with altitude measurements
@ -247,14 +249,14 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
when (newState) {
BottomSheetBehavior.STATE_EXPANDED -> {
statisticsSheet.background = context.getDrawable(R.drawable.shape_statistics_background_expanded)
trackManagementViews.visibility = View.VISIBLE
shareButton.visibility = View.GONE
trackManagementViews.isVisible = true
shareButton.isGone = true
// bottomSheet.setPadding(0,24,0,0)
}
else -> {
statisticsSheet.background = context.getDrawable(R.drawable.shape_statistics_background_collapsed)
trackManagementViews.visibility = View.GONE
shareButton.visibility = View.VISIBLE
trackManagementViews.isGone = true
shareButton.isVisible = true
// bottomSheet.setPadding(0,0,0,0)
}
}
@ -262,12 +264,12 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
override fun onSlide(bottomSheet: View, slideOffset: Float) {
if (slideOffset < 0.125f) {
statisticsSheet.background = context.getDrawable(R.drawable.shape_statistics_background_collapsed)
trackManagementViews.visibility = View.GONE
shareButton.visibility = View.VISIBLE
trackManagementViews.isGone = true
shareButton.isVisible = true
} else {
statisticsSheet.background = context.getDrawable(R.drawable.shape_statistics_background_expanded)
trackManagementViews.visibility = View.VISIBLE
shareButton.visibility = View.GONE
trackManagementViews.isVisible = true
shareButton.isGone = true
}
}
}

View File

@ -3,14 +3,14 @@
buildscript {
ext {
kotlin_version = '1.4.10'
navigation_version = '2.3.0'
navigation_version = '2.3.1'
}
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigation_version"