Skip to content

Commit

Permalink
Add settings activity
Browse files Browse the repository at this point in the history
It allows switching between light and dark modes, specifying step
width, and step data import/export (closes #70).
  • Loading branch information
0xf4b1 committed Dec 10, 2023
1 parent 2df4b09 commit 8c918c5
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 1 deletion.
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
</intent-filter>
</activity>

<activity
android:name=".ui.SettingsActivity"
android:exported="false"
android:label="@string/title_activity_settings" />

<service
android:name=".service.MotionService"
android:foregroundServiceType="health"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ internal class MainActivity : AppCompatActivity() {
WindowCompat.setDecorFitsSystemWindows(window, false)
setContentView(R.layout.activity_main)

Util.stepWidth = PreferenceManager.getDefaultSharedPreferences(this).getInt("step_width", 70)

mTextViewSteps = findViewById(R.id.textViewSteps)
mTextViewMeters = findViewById(R.id.textViewMeters)
val mRecyclerView = findViewById<RecyclerView>(R.id.recyclerView)
Expand Down Expand Up @@ -128,6 +130,10 @@ internal class MainActivity : AppCompatActivity() {
}
}

mTextViewSteps.setOnClickListener {
startActivity(Intent(this, SettingsActivity::class.java))
}

// initial update of the diagram
setDataForWeek(Util.calendar)

Expand Down
126 changes: 126 additions & 0 deletions app/src/main/java/com/tiefensuche/motionmate/ui/SettingsActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
*/

package com.tiefensuche.motionmate.ui

import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SeekBarPreference
import com.tiefensuche.motionmate.R
import com.tiefensuche.motionmate.util.Database
import com.tiefensuche.motionmate.util.Util
import java.io.FileInputStream
import java.io.FileOutputStream
import java.lang.Exception

class SettingsActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.settings_activity)
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, SettingsFragment())
.commit()
}
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}

class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
findPreference<SeekBarPreference>("step_width")?.setOnPreferenceChangeListener { _, newValue ->
Util.stepWidth = newValue as Int
true
}
findPreference<ListPreference>("theme")?.setOnPreferenceChangeListener { _, newValue ->
Util.applyTheme(newValue.toString())
true
}
findPreference<Preference>("import")?.setOnPreferenceClickListener {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/*"
}
startActivityForResult(intent, 1)
true
}
findPreference<Preference>("export")?.setOnPreferenceClickListener {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/*"
putExtra(Intent.EXTRA_TITLE, "step_data.csv")
}
startActivityForResult(intent, 2)
true
}
}

override fun onActivityResult(
requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (resultCode != Activity.RESULT_OK)
return
resultData?.data?.also { uri ->
when (requestCode) {
1 -> import(uri)
2 -> export(uri)
}
}
}

private fun import(uri: Uri) {
val db = Database.getInstance(requireContext())
try {
requireContext().contentResolver.openFileDescriptor(uri, "r")?.use {
FileInputStream(it.fileDescriptor).bufferedReader().use {
var entries = 0
var failed = 0
for (line in it.readLines()) {
entries += 1
try {
val split = line.split(",")
db.addEntry(split[0].toLong(), split[1].toInt())
} catch (ex: Exception) {
println("Can not import entry, ${ex.message}")
failed += 1
}
}
Toast.makeText(context, "Imported ${entries - failed} entries ($failed failed).", Toast.LENGTH_LONG).show()
}
}
} catch (ex: Exception) {
println("Can not open file, ${ex.message}")
Toast.makeText(context, "Can not open file", Toast.LENGTH_LONG).show()
}
}

private fun export(uri: Uri) {
val db = Database.getInstance(requireContext())
try {
requireContext().contentResolver.openFileDescriptor(uri, "w")?.use {
FileOutputStream(it.fileDescriptor).bufferedWriter().use {
var entries = 0
for (entry in db.getEntries(db.firstEntry, db.lastEntry)) {
it.write("${entry.timestamp},${entry.steps}\r\n")
entries += 1
}
Toast.makeText(context, "Exported $entries entries.", Toast.LENGTH_LONG).show()
}
}
} catch (ex: Exception) {
println("Can not open file, ${ex.message}")
Toast.makeText(context, "Can not open file", Toast.LENGTH_LONG).show()
}
}
}
}
12 changes: 11 additions & 1 deletion app/src/main/java/com/tiefensuche/motionmate/util/Util.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package com.tiefensuche.motionmate.util

import androidx.appcompat.app.AppCompatDelegate
import java.util.*

internal object Util {
Expand All @@ -24,14 +25,23 @@ internal object Util {
}


var stepWidth = 70

/**
* Formula to convert steps to kilometers
*
* @param steps steps
* @return kilometers
*/
internal fun stepsToMeters(steps: Number): Double {
return steps.toInt() * 0.762 / 1000
return (steps.toInt() * stepWidth).toDouble() / 100000
}

internal fun applyTheme(theme: String) {
when (theme) {
"system" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
"light" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
"dark" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
}
}
13 changes: 13 additions & 0 deletions app/src/main/res/layout/settings_activity.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!--
~ SPDX-License-Identifier: GPL-3.0-only
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<FrameLayout
android:id="@+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
17 changes: 17 additions & 0 deletions app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!--
~ SPDX-License-Identifier: GPL-3.0-only
-->

<resources>
<string-array name="theme_entries">
<item>System</item>
<item>Light</item>
<item>Dark</item>
</string-array>

<string-array name="theme_values">
<item>system</item>
<item>light</item>
<item>dark</item>
</string-array>
</resources>
6 changes: 6 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,10 @@
<string name="new_activity">New Activity</string>
<string name="new_activity_started">Started new activity</string>
<string name="no_sensor">Sorry, needed sensor is not present on your device.</string>
<!-- Preference Titles -->
<string name="title_activity_settings">SettingsActivity</string>
<string name="step_width">Step width in cm</string>
<string name="data">Data</string>
<string name="appearance">Appearance</string>
<string name="theme">Theme</string>
</resources>
37 changes: 37 additions & 0 deletions app/src/main/res/xml/root_preferences.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!--
~ SPDX-License-Identifier: GPL-3.0-only
-->

<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">

<PreferenceCategory app:title="@string/step_width">
<SeekBarPreference
app:min="50"
android:max="120"
app:defaultValue="70"
app:showSeekBarValue="true"
app:key="step_width" />
</PreferenceCategory>

<PreferenceCategory app:title="@string/appearance">
<ListPreference
app:defaultValue="system"
app:entries="@array/theme_entries"
app:entryValues="@array/theme_values"
app:key="theme"
app:title="@string/theme"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>

<PreferenceCategory app:title="@string/data">
<Preference
app:key="import"
app:title="Import" />

<Preference
app:key="export"
app:title="Export" />
</PreferenceCategory>

</PreferenceScreen>

0 comments on commit 8c918c5

Please sign in to comment.