mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-14 18:26:11 -04:00
Settings/Infos
This commit is contained in:
@@ -191,6 +191,8 @@ dependencies {
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:2.3.5"
|
||||
implementation "androidx.navigation:navigation-ui-ktx:2.3.5"
|
||||
|
||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||
|
||||
def work_version = "2.7.1"
|
||||
implementation "androidx.work:work-runtime:${work_version}"
|
||||
testImplementation "androidx.work:work-testing:${work_version}"
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package eu.darken.capod.common
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.concurrent.withLock
|
||||
|
||||
@Singleton
|
||||
class ClipboardHelper @Inject constructor(
|
||||
@ApplicationContext private val context: Context
|
||||
) {
|
||||
private val clipboard: ClipboardManager by lazy {
|
||||
return@lazy if (Looper.getMainLooper() == Looper.myLooper()) {
|
||||
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
} else {
|
||||
// java.lang.RuntimeException · Can't create handler inside thread that has not called Looper.prepare()
|
||||
log(TAG) { "Clipboard is not initialized on the main thread, applying workaround" }
|
||||
val lock = ReentrantLock()
|
||||
val lockCondition = lock.newCondition()
|
||||
|
||||
var clipboardManager: ClipboardManager? = null
|
||||
|
||||
Handler(Looper.getMainLooper()).postAtFrontOfQueue {
|
||||
clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
lock.withLock { lockCondition.signal() }
|
||||
}
|
||||
|
||||
lock.withLock { lockCondition.await() }
|
||||
|
||||
clipboardManager!!
|
||||
}
|
||||
}
|
||||
|
||||
fun copyToClipboard(text: String) {
|
||||
val clip = ClipData.newPlainText(context.getString(R.string.app_name), text)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = logTag("ClipboardHelper")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package eu.darken.capod.common
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dagger.Reusable
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
|
||||
@Reusable
|
||||
class EmailTool @Inject constructor(
|
||||
@ApplicationContext val context: Context
|
||||
) {
|
||||
|
||||
fun build(email: Email, offerChooser: Boolean = false): Intent {
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
intent.type = "message/rfc822"
|
||||
intent.putExtra(Intent.EXTRA_EMAIL, email.receipients.toTypedArray())
|
||||
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, email.subject)
|
||||
intent.putExtra(Intent.EXTRA_TEXT, email.body)
|
||||
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
return if (offerChooser) Intent.createChooser(intent, null) else intent
|
||||
}
|
||||
|
||||
data class Email(
|
||||
val receipients: List<String>,
|
||||
val subject: String,
|
||||
val body: String
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package eu.darken.capod.common
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import dagger.Reusable
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.ERROR
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
import javax.inject.Inject
|
||||
|
||||
@Reusable
|
||||
class WebpageTool @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
) {
|
||||
|
||||
fun open(address: String) {
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(address)).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
try {
|
||||
context.startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
log(ERROR) { "Failed to launch" }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,7 +12,7 @@ class DebugSettings @Inject constructor(
|
||||
) {
|
||||
|
||||
private val prefs by lazy {
|
||||
context.getSharedPreferences("bugreport_settings", Context.MODE_PRIVATE)
|
||||
context.getSharedPreferences("settings_debug", Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
val isAutoReportEnabled = prefs.createFlowPreference("bugreport.automatic.enabled", true)
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package eu.darken.capod.common.preferences
|
||||
|
||||
import androidx.preference.PreferenceDataStore
|
||||
|
||||
abstract class PreferenceStoreMapper : PreferenceDataStore() {
|
||||
override fun getBoolean(key: String, defValue: Boolean): Boolean {
|
||||
throw NotImplementedError("getBoolean(key=$key, defValue=$defValue)")
|
||||
}
|
||||
|
||||
override fun putBoolean(key: String, value: Boolean) {
|
||||
throw NotImplementedError("putBoolean(key=$key, defValue=$value)")
|
||||
}
|
||||
|
||||
override fun getString(key: String, defValue: String?): String? {
|
||||
throw NotImplementedError("getString(key=$key, defValue=$defValue)")
|
||||
}
|
||||
|
||||
override fun putString(key: String, value: String?) {
|
||||
throw NotImplementedError("putString(key=$key, defValue=$value)")
|
||||
}
|
||||
|
||||
override fun putInt(key: String?, value: Int) {
|
||||
throw NotImplementedError("putInt(key=$key, defValue=$value)")
|
||||
}
|
||||
|
||||
override fun getInt(key: String?, defValue: Int): Int {
|
||||
throw NotImplementedError("getInt(key=$key, defValue=$defValue)")
|
||||
}
|
||||
|
||||
override fun putLong(key: String?, value: Long) {
|
||||
throw NotImplementedError("putLong(key=$key, defValue=$value)")
|
||||
}
|
||||
|
||||
override fun putStringSet(key: String?, values: MutableSet<String>?) {
|
||||
throw NotImplementedError("putStringSet(key=$key, defValue=$values)")
|
||||
}
|
||||
|
||||
override fun getLong(key: String?, defValue: Long): Long {
|
||||
throw NotImplementedError("getLong(key=$key, defValue=$defValue)")
|
||||
}
|
||||
|
||||
override fun getFloat(key: String?, defValue: Float): Float {
|
||||
throw NotImplementedError("getFloat(key=$key, defValue=$defValue)")
|
||||
}
|
||||
|
||||
override fun putFloat(key: String?, value: Float) {
|
||||
throw NotImplementedError("putFloat(key=$key, defValue=$value)")
|
||||
}
|
||||
|
||||
override fun getStringSet(key: String?, defValues: MutableSet<String>?): MutableSet<String> {
|
||||
throw NotImplementedError("getStringSet(key=$key, defValue=$defValues)")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package eu.darken.androidstarter.common.preferences
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.preference.PreferenceDataStore
|
||||
|
||||
abstract class Settings {
|
||||
|
||||
abstract val preferenceDataStore: PreferenceDataStore
|
||||
|
||||
abstract val preferences: SharedPreferences
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package eu.darken.capod.common.uix
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.MenuRes
|
||||
import androidx.annotation.XmlRes
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import eu.darken.androidstarter.common.preferences.Settings
|
||||
import eu.darken.capod.main.ui.settings.SettingsFragment
|
||||
|
||||
abstract class PreferenceFragment2
|
||||
: PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
abstract val settings: Settings
|
||||
|
||||
@get:XmlRes
|
||||
abstract val preferenceFile: Int
|
||||
|
||||
val toolbar: Toolbar
|
||||
get() = (parentFragment as SettingsFragment).toolbar
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
toolbar.menu.clear()
|
||||
return super.onCreateView(inflater, container, savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
preferenceManager.preferenceDataStore = settings.preferenceDataStore
|
||||
settings.preferences.registerOnSharedPreferenceChangeListener(this)
|
||||
refreshPreferenceScreen()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
settings.preferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun getCallbackFragment(): Fragment? = parentFragment
|
||||
|
||||
fun refreshPreferenceScreen() {
|
||||
if (preferenceScreen != null) preferenceScreen = null
|
||||
addPreferencesFromResource(preferenceFile)
|
||||
onPreferencesCreated()
|
||||
}
|
||||
|
||||
open fun onPreferencesCreated() {
|
||||
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
||||
|
||||
}
|
||||
|
||||
fun setupMenu(@MenuRes menuResId: Int, block: (MenuItem) -> Unit) {
|
||||
toolbar.apply {
|
||||
menu.clear()
|
||||
inflateMenu(menuResId)
|
||||
setOnMenuItemClickListener {
|
||||
block(it)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package eu.darken.capod.main.core
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.preference.PreferenceDataStore
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import eu.darken.androidstarter.common.preferences.Settings
|
||||
import eu.darken.capod.common.debug.autoreport.DebugSettings
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.common.preferences.PreferenceStoreMapper
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class GeneralSettings @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val debugSettings: DebugSettings,
|
||||
) : Settings() {
|
||||
|
||||
override val preferenceDataStore: PreferenceDataStore = object : PreferenceStoreMapper() {
|
||||
override fun getBoolean(key: String, defValue: Boolean): Boolean = when (key) {
|
||||
PK_BUGTRACKING_ENABLED -> debugSettings.isAutoReportEnabled.value
|
||||
else -> super.getBoolean(key, defValue)
|
||||
}
|
||||
|
||||
override fun putBoolean(key: String, value: Boolean) = when (key) {
|
||||
PK_BUGTRACKING_ENABLED -> debugSettings.isAutoReportEnabled.update { value }
|
||||
else -> super.putBoolean(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
override val preferences: SharedPreferences = context.getSharedPreferences("settings_general", Context.MODE_PRIVATE)
|
||||
|
||||
companion object {
|
||||
internal val TAG = logTag("Core", "Settings")
|
||||
private const val PK_BUGTRACKING_ENABLED = "core.bugtracking.enabled"
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import eu.darken.capod.common.coroutine.DispatcherProvider
|
||||
import eu.darken.capod.common.debug.recording.core.RecorderModule
|
||||
import eu.darken.capod.common.livedata.SingleLiveEvent
|
||||
import eu.darken.capod.common.navigation.navVia
|
||||
import eu.darken.capod.common.permissions.Permission
|
||||
import eu.darken.capod.common.permissions.isGrantedOrNotRequired
|
||||
import eu.darken.capod.common.uix.ViewModel3
|
||||
@@ -33,7 +34,6 @@ class OverviewFragmentVM @Inject constructor(
|
||||
private val podMonitor: PodMonitor,
|
||||
) : ViewModel3(dispatcherProvider = dispatcherProvider) {
|
||||
|
||||
|
||||
private val enabledState: Flow<Boolean> = flow {
|
||||
emit(false)
|
||||
}
|
||||
@@ -100,7 +100,7 @@ class OverviewFragmentVM @Inject constructor(
|
||||
}
|
||||
|
||||
fun goToSettings() = launch {
|
||||
|
||||
OverviewFragmentDirections.actionOverviewFragmentToSettingsFragment().navVia(this@OverviewFragmentVM)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package eu.darken.capod.main.ui.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.uix.Fragment2
|
||||
import eu.darken.capod.common.viewbinding.viewBinding
|
||||
import eu.darken.capod.databinding.SettingsFragmentBinding
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@AndroidEntryPoint
|
||||
class SettingsFragment : Fragment2(R.layout.settings_fragment),
|
||||
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
|
||||
|
||||
private val vm: SettingsFragmentVM by viewModels()
|
||||
private val ui: SettingsFragmentBinding by viewBinding()
|
||||
|
||||
val toolbar: Toolbar
|
||||
get() = ui.toolbar
|
||||
|
||||
private val screens = ArrayList<Screen>()
|
||||
|
||||
@Parcelize
|
||||
data class Screen(
|
||||
val fragmentClass: String,
|
||||
val screenTitle: String?
|
||||
) : Parcelable
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
childFragmentManager.addOnBackStackChangedListener {
|
||||
val backStackCnt = childFragmentManager.backStackEntryCount
|
||||
val newScreenInfo = when {
|
||||
backStackCnt < screens.size -> {
|
||||
// We popped the backstack, restore the underlying screen infos
|
||||
// If there are none left, we are at the index again
|
||||
screens.removeLastOrNull()
|
||||
screens.lastOrNull() ?: Screen(
|
||||
fragmentClass = SettingsIndexFragment::class.qualifiedName!!,
|
||||
screenTitle = getString(R.string.settings_label)
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
// We added the current fragment to the stack, the new fragment's infos were already set, do nothing.
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
newScreenInfo?.let { setCurrentScreenInfo(it) }
|
||||
}
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
childFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.content_frame, SettingsIndexFragment())
|
||||
.commit()
|
||||
} else {
|
||||
savedInstanceState.getParcelableArrayList<Screen>(BKEY_SCREEN_INFOS)?.let {
|
||||
screens.addAll(it)
|
||||
}
|
||||
screens.lastOrNull()?.let { setCurrentScreenInfo(it) }
|
||||
}
|
||||
|
||||
ui.toolbar.setNavigationOnClickListener { requireActivity().onBackPressed() }
|
||||
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
}
|
||||
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putParcelableArrayList(BKEY_SCREEN_INFOS, screens)
|
||||
}
|
||||
|
||||
override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference): Boolean {
|
||||
val screenInfo = Screen(
|
||||
fragmentClass = pref.fragment,
|
||||
screenTitle = pref.title?.toString()
|
||||
)
|
||||
|
||||
val args = Bundle().apply {
|
||||
putAll(pref.extras)
|
||||
putString(BKEY_SCREEN_TITLE, screenInfo.screenTitle)
|
||||
}
|
||||
|
||||
val fragment = childFragmentManager.fragmentFactory
|
||||
.instantiate(this::class.java.classLoader!!, pref.fragment)
|
||||
.apply {
|
||||
arguments = args
|
||||
setTargetFragment(caller, 0)
|
||||
}
|
||||
|
||||
setCurrentScreenInfo(screenInfo)
|
||||
screens.add(screenInfo)
|
||||
|
||||
childFragmentManager.beginTransaction().apply {
|
||||
replace(R.id.content_frame, fragment)
|
||||
addToBackStack(null)
|
||||
}.commit()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
private fun setCurrentScreenInfo(info: Screen) {
|
||||
ui.toolbar.apply {
|
||||
title = info.screenTitle
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val BKEY_SCREEN_TITLE = "preferenceScreenTitle"
|
||||
private const val BKEY_SCREEN_INFOS = "preferenceScreenInfos"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package eu.darken.capod.main.ui.settings
|
||||
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import eu.darken.capod.common.coroutine.DispatcherProvider
|
||||
import eu.darken.capod.common.uix.ViewModel2
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class SettingsFragmentVM @Inject constructor(
|
||||
private val handle: SavedStateHandle,
|
||||
private val dispatcherProvider: DispatcherProvider,
|
||||
) : ViewModel2(dispatcherProvider)
|
||||
@@ -0,0 +1,41 @@
|
||||
package eu.darken.capod.main.ui.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.preference.Preference
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import eu.darken.androidstarter.common.preferences.Settings
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.BuildConfigWrap
|
||||
import eu.darken.capod.common.WebpageTool
|
||||
import eu.darken.capod.common.uix.PreferenceFragment2
|
||||
import eu.darken.capod.main.core.GeneralSettings
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class SettingsIndexFragment : PreferenceFragment2() {
|
||||
|
||||
@Inject lateinit var generalSettings: GeneralSettings
|
||||
override val settings: Settings
|
||||
get() = generalSettings
|
||||
override val preferenceFile: Int = R.xml.preferences_index
|
||||
|
||||
@Inject lateinit var webpageTool: WebpageTool
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
setupMenu(R.menu.menu_settings_index) { item ->
|
||||
when (item.itemId) {
|
||||
R.id.menu_item_twitter -> {
|
||||
webpageTool.open("https://twitter.com/d4rken")
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onPreferencesCreated() {
|
||||
findPreference<Preference>("core.changelog")!!.summary = BuildConfigWrap.VERSION_DESCRIPTION
|
||||
|
||||
super.onPreferencesCreated()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package eu.darken.capod.main.ui.settings.acks
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import androidx.fragment.app.viewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.uix.PreferenceFragment2
|
||||
import eu.darken.capod.main.core.GeneralSettings
|
||||
import javax.inject.Inject
|
||||
|
||||
@Keep
|
||||
@AndroidEntryPoint
|
||||
class AcknowledgementsFragment : PreferenceFragment2() {
|
||||
|
||||
private val vm: AcknowledgementsFragmentVM by viewModels()
|
||||
|
||||
override val preferenceFile: Int = R.xml.preferences_acknowledgements
|
||||
@Inject lateinit var debugSettings: GeneralSettings
|
||||
|
||||
override val settings: GeneralSettings by lazy { debugSettings }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package eu.darken.capod.main.ui.settings.acks
|
||||
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import dagger.assisted.AssistedInject
|
||||
import eu.darken.capod.common.coroutine.DispatcherProvider
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.common.uix.ViewModel3
|
||||
|
||||
class AcknowledgementsFragmentVM @AssistedInject constructor(
|
||||
private val handle: SavedStateHandle,
|
||||
private val dispatcherProvider: DispatcherProvider
|
||||
) : ViewModel3(dispatcherProvider) {
|
||||
|
||||
companion object {
|
||||
private val TAG = logTag("Settings", "Acknowledgements", "VM")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package eu.darken.capod.main.ui.settings.general
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import androidx.fragment.app.viewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.uix.PreferenceFragment2
|
||||
import eu.darken.capod.main.core.GeneralSettings
|
||||
import javax.inject.Inject
|
||||
|
||||
@Keep
|
||||
@AndroidEntryPoint
|
||||
class GeneralSettingsFragment : PreferenceFragment2() {
|
||||
|
||||
private val vm: GeneralSettingsFragmentVM by viewModels()
|
||||
|
||||
@Inject lateinit var generalSettings: GeneralSettings
|
||||
|
||||
override val settings: GeneralSettings
|
||||
get() = generalSettings
|
||||
|
||||
override val preferenceFile: Int = R.xml.preferences_general
|
||||
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package eu.darken.capod.main.ui.settings.general
|
||||
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import eu.darken.capod.common.coroutine.DispatcherProvider
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.common.uix.ViewModel3
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class GeneralSettingsFragmentVM @Inject constructor(
|
||||
private val handle: SavedStateHandle,
|
||||
private val dispatcherProvider: DispatcherProvider,
|
||||
) : ViewModel3(dispatcherProvider) {
|
||||
|
||||
|
||||
companion object {
|
||||
private val TAG = logTag("Settings", "General", "VM")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package eu.darken.capod.main.ui.settings.support
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.annotation.Keep
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.preference.Preference
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.ClipboardHelper
|
||||
import eu.darken.capod.common.observe2
|
||||
import eu.darken.capod.common.uix.PreferenceFragment2
|
||||
import eu.darken.capod.main.core.GeneralSettings
|
||||
import javax.inject.Inject
|
||||
|
||||
@Keep
|
||||
@AndroidEntryPoint
|
||||
class SupportFragment : PreferenceFragment2() {
|
||||
|
||||
private val vm: SupportFragmentVM by viewModels()
|
||||
|
||||
override val preferenceFile: Int = R.xml.preferences_support
|
||||
@Inject lateinit var generalSettings: GeneralSettings
|
||||
|
||||
override val settings: GeneralSettings by lazy { generalSettings }
|
||||
|
||||
@Inject lateinit var clipboardHelper: ClipboardHelper
|
||||
|
||||
private val installIdPref by lazy { findPreference<Preference>("support.installid")!! }
|
||||
private val supportMailPref by lazy { findPreference<Preference>("support.email.darken")!! }
|
||||
|
||||
override fun onPreferencesCreated() {
|
||||
installIdPref.setOnPreferenceClickListener {
|
||||
vm.copyInstallID()
|
||||
true
|
||||
}
|
||||
supportMailPref.setOnPreferenceClickListener {
|
||||
vm.sendSupportMail()
|
||||
true
|
||||
}
|
||||
|
||||
super.onPreferencesCreated()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
vm.clipboardEvent.observe2(this) { installId ->
|
||||
Snackbar.make(requireView(), installId, Snackbar.LENGTH_INDEFINITE)
|
||||
.setAction(R.string.general_copy_action) {
|
||||
clipboardHelper.copyToClipboard(installId)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
vm.emailEvent.observe2(this) { startActivity(it) }
|
||||
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package eu.darken.capod.main.ui.settings.support
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import eu.darken.capod.common.BuildConfigWrap
|
||||
import eu.darken.capod.common.EmailTool
|
||||
import eu.darken.capod.common.InstallId
|
||||
import eu.darken.capod.common.coroutine.DispatcherProvider
|
||||
import eu.darken.capod.common.livedata.SingleLiveEvent
|
||||
import eu.darken.capod.common.uix.ViewModel3
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class SupportFragmentVM @Inject constructor(
|
||||
private val handle: SavedStateHandle,
|
||||
private val emailTool: EmailTool,
|
||||
private val installId: InstallId,
|
||||
private val dispatcherProvider: DispatcherProvider,
|
||||
) : ViewModel3(dispatcherProvider) {
|
||||
|
||||
val emailEvent = SingleLiveEvent<Intent>()
|
||||
val clipboardEvent = SingleLiveEvent<String>()
|
||||
|
||||
fun sendSupportMail() = launch {
|
||||
|
||||
val bodyInfo = StringBuilder("\n\n\n")
|
||||
|
||||
bodyInfo.append("--- Infos for the developer ---\n")
|
||||
|
||||
bodyInfo.append("App version: ").append(BuildConfigWrap.VERSION_DESCRIPTION).append("\n")
|
||||
|
||||
bodyInfo.append("Device: ").append(Build.FINGERPRINT).append("\n")
|
||||
bodyInfo.append("Install ID: ").append(installId.id).append("\n")
|
||||
|
||||
val email = EmailTool.Email(
|
||||
receipients = listOf("support@darken.eu"),
|
||||
subject = "[CAPod] Question/Suggestion/Request\n",
|
||||
body = bodyInfo.toString()
|
||||
)
|
||||
|
||||
emailEvent.postValue(emailTool.build(email))
|
||||
}
|
||||
|
||||
fun copyInstallID() = launch {
|
||||
clipboardEvent.postValue(installId.id)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M18,2H6c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zM6,4h5v8l-2.5,-1.5L6,12V4z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,19 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M21,12.22C21,6.73 16.74,3 12,3c-4.69,0 -9,3.65 -9,9.28C2.4,12.62 2,13.26 2,14v2c0,1.1 0.9,2 2,2h1v-6.1c0,-3.87 3.13,-7 7,-7s7,3.13 7,7V19h-8v2h8c1.1,0 2,-0.9 2,-2v-1.22c0.59,-0.31 1,-0.92 1,-1.64v-2.3C22,13.14 21.59,12.53 21,12.22z" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M9,13m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M15,13m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M18,11.03C17.52,8.18 15.04,6 12.05,6c-3.03,0 -6.29,2.51 -6.03,6.45c2.47,-1.01 4.33,-3.21 4.86,-5.89C12.19,9.19 14.88,11 18,11.03z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20M5,13V15H16V13H5M5,9V11H19V9H5Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19 3H14.82C14.4 1.84 13.3 1 12 1S9.6 1.84 9.18 3H5C3.9 3 3 3.9 3 5V19C3 20.1 3.9 21 5 21H19C20.1 21 21 20.1 21 19V5C21 3.9 20.1 3 19 3M7 8H9V12H8V9H7V8M10 17V18H7V17.08L9 15H7V14H9.25C9.66 14 10 14.34 10 14.75C10 14.95 9.92 15.14 9.79 15.27L8.12 17H10M11 4C11 3.45 11.45 3 12 3S13 3.45 13 4 12.55 5 12 5 11 4.55 11 4M17 17H12V15H17V17M17 11H12V9H17V11Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M22,24L16.75,19L17.38,21H4.5A2.5,2.5 0 0,1 2,18.5V3.5A2.5,2.5 0 0,1 4.5,1H19.5A2.5,2.5 0 0,1 22,3.5V24M12,6.8C9.32,6.8 7.44,7.95 7.44,7.95C8.47,7.03 10.27,6.5 10.27,6.5L10.1,6.33C8.41,6.36 6.88,7.53 6.88,7.53C5.16,11.12 5.27,14.22 5.27,14.22C6.67,16.03 8.75,15.9 8.75,15.9L9.46,15C8.21,14.73 7.42,13.62 7.42,13.62C7.42,13.62 9.3,14.9 12,14.9C14.7,14.9 16.58,13.62 16.58,13.62C16.58,13.62 15.79,14.73 14.54,15L15.25,15.9C15.25,15.9 17.33,16.03 18.73,14.22C18.73,14.22 18.84,11.12 17.12,7.53C17.12,7.53 15.59,6.36 13.9,6.33L13.73,6.5C13.73,6.5 15.53,7.03 16.56,7.95C16.56,7.95 14.68,6.8 12,6.8M9.93,10.59C10.58,10.59 11.11,11.16 11.1,11.86C11.1,12.55 10.58,13.13 9.93,13.13C9.29,13.13 8.77,12.55 8.77,11.86C8.77,11.16 9.28,10.59 9.93,10.59M14.1,10.59C14.75,10.59 15.27,11.16 15.27,11.86C15.27,12.55 14.75,13.13 14.1,13.13C13.46,13.13 12.94,12.55 12.94,11.86C12.94,11.16 13.45,10.59 14.1,10.59Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,8l-8,5 -8,-5L4,6l8,5 8,-5v2z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20.38,8.53C20.54,8.13 21.06,6.54 20.21,4.39C20.21,4.39 18.9,4 15.91,6C14.66,5.67 13.33,5.62 12,5.62C10.68,5.62 9.34,5.67 8.09,6C5.1,3.97 3.79,4.39 3.79,4.39C2.94,6.54 3.46,8.13 3.63,8.53C2.61,9.62 2,11 2,12.72C2,19.16 6.16,20.61 12,20.61C17.79,20.61 22,19.16 22,12.72C22,11 21.39,9.62 20.38,8.53M12,19.38C7.88,19.38 4.53,19.19 4.53,15.19C4.53,14.24 5,13.34 5.8,12.61C7.14,11.38 9.43,12.03 12,12.03C14.59,12.03 16.85,11.38 18.2,12.61C19,13.34 19.5,14.23 19.5,15.19C19.5,19.18 16.13,19.38 12,19.38M8.86,13.12C8.04,13.12 7.36,14.12 7.36,15.34C7.36,16.57 8.04,17.58 8.86,17.58C9.69,17.58 10.36,16.58 10.36,15.34C10.36,14.11 9.69,13.12 8.86,13.12M15.14,13.12C14.31,13.12 13.64,14.11 13.64,15.34C13.64,16.58 14.31,17.58 15.14,17.58C15.96,17.58 16.64,16.58 16.64,15.34C16.64,14.11 16,13.12 15.14,13.12Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M6,18V8H8V18H6M6,4.5H8V6.5H6V4.5M17,4H19V18H17V17.75C17,17.75 15.67,18 15,18A5,5 0 0,1 10,13A5,5 0 0,1 15,8C15.67,8 17,8.25 17,8.25V4M17,10.25C17,10.25 15.67,10 15,10A3,3 0 0,0 12,13A3,3 0 0,0 15,16C15.67,16 17,15.75 17,15.75V10.25Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M13 2V7.08A5.47 5.47 0 0 0 12 7A5.47 5.47 0 0 0 11 7.08V2M16.9 15A5 5 0 0 1 16.73 15.55L20 17.42V22H18V18.58L15.74 17.29A4.94 4.94 0 0 1 8.26 17.29L6 18.58V22H4V17.42L7.27 15.55A5 5 0 0 1 7.1 15H5.3L2.55 16.83L1.45 15.17L4.7 13H7.1A5 5 0 0 1 7.37 12.12L5.81 11.12L2.24 12L1.76 10L6.19 8.92L8.5 10.45A5 5 0 0 1 15.5 10.45L17.77 8.92L22.24 10L21.76 12L18.19 11.11L16.63 12.11A5 5 0 0 1 16.9 13H19.3L22.55 15.16L21.45 16.82L18.7 15M11 14A1 1 0 1 0 10 15A1 1 0 0 0 11 14M15 14A1 1 0 1 0 14 15A1 1 0 0 0 15 14Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M22.46,6C21.69,6.35 20.86,6.58 20,6.69C20.88,6.16 21.56,5.32 21.88,4.31C21.05,4.81 20.13,5.16 19.16,5.36C18.37,4.5 17.26,4 16,4C13.65,4 11.73,5.92 11.73,8.29C11.73,8.63 11.77,8.96 11.84,9.27C8.28,9.09 5.11,7.38 3,4.79C2.63,5.42 2.42,6.16 2.42,6.94C2.42,8.43 3.17,9.75 4.33,10.5C3.62,10.5 2.96,10.3 2.38,10C2.38,10 2.38,10 2.38,10.03C2.38,12.11 3.86,13.85 5.82,14.24C5.46,14.34 5.08,14.39 4.69,14.39C4.42,14.39 4.15,14.36 3.89,14.31C4.43,16 6,17.26 7.89,17.29C6.43,18.45 4.58,19.13 2.56,19.13C2.22,19.13 1.88,19.11 1.54,19.07C3.44,20.29 5.7,21 8.12,21C16,21 20.33,14.46 20.33,8.79C20.33,8.6 20.33,8.42 20.32,8.23C21.16,7.63 21.88,6.87 22.46,6Z" />
|
||||
</vector>
|
||||
@@ -7,14 +7,16 @@
|
||||
android:orientation="vertical"
|
||||
tools:context=".main.ui.MainActivity">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
<fragment
|
||||
android:id="@+id/nav_host"
|
||||
android:name="eu.darken.capod.main.ui.overview.OverviewFragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:defaultNavHost="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navGraph="@navigation/nav_graph" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,26 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".main.ui.MainActivity">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Widget.MaterialComponents.Toolbar.Primary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navigationIcon="@drawable/ic_baseline_arrow_back_24"
|
||||
app:title="@string/settings_label" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/content_frame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,10 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/menu_item_settings"
|
||||
android:title="@string/settings_general_label" />
|
||||
<item
|
||||
android:id="@+id/menu_item_debuglog"
|
||||
android:title="@string/debug_debuglog_record_action" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_item_settings"
|
||||
android:title="@string/general_settings_label" />
|
||||
</menu>
|
||||
@@ -0,0 +1,12 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="eu.darken.androidstarter.main.ui.MainActivity">
|
||||
<item
|
||||
android:id="@+id/menu_item_twitter"
|
||||
android:icon="@drawable/ic_twitter"
|
||||
android:orderInCategory="100"
|
||||
android:tooltipText="Twitter"
|
||||
android:title="Twitter"
|
||||
app:showAsAction="always" />
|
||||
</menu>
|
||||
@@ -10,6 +10,15 @@
|
||||
android:name="eu.darken.capod.main.ui.overview.OverviewFragment"
|
||||
tools:layout="@layout/main_fragment">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_overviewFragment_to_settingsFragment"
|
||||
app:destination="@id/settingsFragment" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/settingsFragment"
|
||||
android:name="eu.darken.capod.main.ui.settings.SettingsFragment"
|
||||
android:label="SettingsFragment"
|
||||
tools:layout="@layout/settings_fragment" />
|
||||
|
||||
</navigation>
|
||||
@@ -1,33 +1,39 @@
|
||||
<resources>
|
||||
<string name="app_name">CAPod</string>
|
||||
<string name="app_name_pro">CAPod Pro</string>
|
||||
<string name="general_error_label">Error</string>
|
||||
<string name="permission_bluetooth_connect_label">BLUETOOTH CONNECT</string>
|
||||
<string name="permission_bluetooth_connect_description">Required to be able to connect to paired Bluetooth devices.</string>
|
||||
|
||||
<string name="device_status_loading_message">Loading device status</string>
|
||||
<string name="notification_channel_device_status_label">Device status</string>
|
||||
<string name="permission_bluetooth_scan_label">BLUETOOTH SCAN</string>
|
||||
<string name="permission_bluetooth_scan_description">Required to be able to discover and pair nearby Bluetooth devices.</string>
|
||||
|
||||
<string name="general_error_label">Error</string>
|
||||
<string name="general_share_action">Share</string>
|
||||
<string name="general_done_action">Done</string>
|
||||
<string name="general_copy_action">Copy</string>
|
||||
<string name="general_value_unknown_label">Unknown</string>
|
||||
<string name="general_thank_you_label">Thank you</string>
|
||||
<string name="general_value_not_available_label">N/A</string>
|
||||
|
||||
<string name="debug_debuglog_size_label">Size</string>
|
||||
<string name="debug_debuglog_size_compressed_label">Compressed size</string>
|
||||
<string name="debug_notification_channel_label">Debug notifications</string>
|
||||
<string name="debug_debuglog_file_label">Recorded log file</string>
|
||||
<string name="debug_debuglog_record_action">Record debug log</string>
|
||||
<string name="general_settings_label">Settings</string>
|
||||
|
||||
<string name="permission_bluetooth_connect_label">BLUETOOTH CONNECT</string>
|
||||
<string name="permission_bluetooth_connect_description">Required to be able to connect to paired Bluetooth devices.</string>
|
||||
<string name="permission_bluetooth_scan_label">BLUETOOTH SCAN</string>
|
||||
<string name="permission_bluetooth_scan_description">Required to be able to discover and pair nearby Bluetooth devices.</string>
|
||||
<string name="permission_bluetooth_label">BLUETOOTH</string>
|
||||
<string name="permission_bluetooth_description">Allows applications to connect to paired bluetooth devices.</string>
|
||||
<string name="permission_access_fine_location_description">Allows an app to access precise location.</string>
|
||||
<string name="permission_access_fine_location_label">ACCESS_FINE_LOCATION</string>
|
||||
|
||||
<string name="pods_dual_left_label">Left pod</string>
|
||||
<string name="pods_dual_right_label">Right pod</string>
|
||||
<string name="pods_case_status_label">Case</string>
|
||||
<string name="pods_case_status_open_label">Open</string>
|
||||
<string name="pods_case_status_closed_label">Closed</string>
|
||||
<string name="general_value_not_available_label">N/A</string>
|
||||
<string name="pods_unknown_raw_data_label">Raw data</string>
|
||||
<string name="general_value_unknown_label">Unknown</string>
|
||||
<string name="pods_reception_x_label">Reception %s</string>
|
||||
<string name="pods_device_color_white_label">White</string>
|
||||
<string name="pods_device_color_yellow_label">Yellow</string>
|
||||
@@ -49,4 +55,30 @@
|
||||
<string name="pods_connection_state_ringing_label">Ringing</string>
|
||||
<string name="pods_connection_state_hanging_up_label">Hanging up</string>
|
||||
<string name="pods_status_x_label">Status %s</string>
|
||||
|
||||
|
||||
<string name="settings_label">Settings</string>
|
||||
<string name="settings_privacy_policy_label">Privacy policy</string>
|
||||
<string name="settings_privacy_policy_desc">Handling data responsibly.</string>
|
||||
<string name="settings_licenses_label">Licenses</string>
|
||||
<string name="settings_category_other_label">Other</string>
|
||||
<string name="settings_general_label">Settings</string>
|
||||
<string name="settings_general_description">General tweaks that affect the whole app.</string>
|
||||
<string name="settings_acknowledgements_label">Acknowledgements</string>
|
||||
|
||||
<string name="changelog_label">Changelog</string>
|
||||
<string name="documentation_label">Documentation</string>
|
||||
<string name="settings_support_email_developer_label">Email developer</string>
|
||||
|
||||
<string name="settings_support_installid_label">Install ID</string>
|
||||
<string name="settings_support_installid_desc">Automatic error reports are anonymous. Share your install ID if the developer needs to find your error reports.</string>
|
||||
<string name="settings_support_label">Support</string>
|
||||
<string name="settings_support_description">If you need some help.</string>
|
||||
<string name="issue_tracker_label">Issue tracker</string>
|
||||
<string name="issue_tracker_description">A public issue tracker for bug reports and feature requests (english only).</string>
|
||||
<string name="discord_label">Discord</string>
|
||||
<string name="discord_description">A place to hang out in and ask questions.</string>
|
||||
<string name="settings_support_email_developer_description">Note that I can only respond in german or english.</string>
|
||||
<string name="settings_debug_autoreports_label">Automatic bug reports</string>
|
||||
<string name="settings_debug_autoreports_description">Automatically reports issues, e.g. details on an app crash so I can figure out how to fix it.</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<PreferenceCategory
|
||||
android:title="@string/general_thank_you_label"
|
||||
app:iconSpaceReserved="false">
|
||||
<Preference
|
||||
android:key="thanks.maxpatchs"
|
||||
android:summary="Thanks for the lovely icons."
|
||||
android:title="Max Patchs"
|
||||
app:iconSpaceReserved="false">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://twitter.com/maxpatchs" />
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/settings_licenses_label"
|
||||
app:iconSpaceReserved="false">
|
||||
<Preference
|
||||
android:key="license.bugsnag"
|
||||
android:summary="Client side library for crash monitoring via bugsnag.com. (MIT)"
|
||||
android:title="Bugsnag"
|
||||
app:iconSpaceReserved="false">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://github.com/bugsnag/bugsnag-android" />
|
||||
</Preference>
|
||||
<Preference
|
||||
android:key="license.glide"
|
||||
android:summary="An image loading and caching library for Android focused on smooth scrolling. (Multiple licenses)"
|
||||
android:title="Glide"
|
||||
app:iconSpaceReserved="false">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://github.com/bumptech/glide" />
|
||||
</Preference>
|
||||
<Preference
|
||||
android:key="license.materialdesignicons"
|
||||
android:summary="materialdesignicons.com (SIL Open Font License 1.1 / Attribution 4.0 International)"
|
||||
android:title="Material Design Icons"
|
||||
app:iconSpaceReserved="false">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://github.com/Templarian/MaterialDesign" />
|
||||
</Preference>
|
||||
<Preference
|
||||
android:key="license.zwiconiconset"
|
||||
android:summary="Creative Commons Attribution 4.0 International"
|
||||
android:title="Zwicon Icon Set"
|
||||
app:iconSpaceReserved="false">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://iconduck.com/sets/zwicon-icon-set" />
|
||||
</Preference>
|
||||
<Preference
|
||||
android:key="license.lottie"
|
||||
android:summary="Airbnb's Lottie for Android. (APACHE 2.0)"
|
||||
android:title="Lottie"
|
||||
app:iconSpaceReserved="false">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://github.com/airbnb/lottie-android" />
|
||||
</Preference>
|
||||
<Preference
|
||||
android:key="license.kotlin"
|
||||
android:summary="The Kotlin Programming Language. (APACHE 2.0)"
|
||||
android:title="Kotlin"
|
||||
app:iconSpaceReserved="false">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://github.com/JetBrains/kotlin" />
|
||||
</Preference>
|
||||
<Preference
|
||||
android:key="license.dagger"
|
||||
android:summary="A fast dependency injector for Android and Java. (APACHE 2.0)"
|
||||
android:title="Dagger"
|
||||
app:iconSpaceReserved="false">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://github.com/google/dagger" />
|
||||
</Preference>
|
||||
<Preference
|
||||
android:key="android.android"
|
||||
android:summary="Android Open Source Project (APACHE 2.0)"
|
||||
android:title="Android"
|
||||
app:iconSpaceReserved="false">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://source.android.com/source/licenses.html" />
|
||||
</Preference>
|
||||
<Preference
|
||||
android:key="android.logo"
|
||||
android:summary="The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License."
|
||||
android:title="Android"
|
||||
app:iconSpaceReserved="false">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://developer.android.com/distribute/tools/promote/brand.html" />
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<PreferenceCategory android:title="@string/settings_category_other_label">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:icon="@drawable/ic_spider_thread_onsurface"
|
||||
android:key="core.bugtracking.enabled"
|
||||
android:summary="@string/settings_debug_autoreports_description"
|
||||
android:title="@string/settings_debug_autoreports_label" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<Preference
|
||||
android:icon="@drawable/ic_baseline_settings_24"
|
||||
app:fragment="eu.darken.capod.main.ui.settings.general.GeneralSettingsFragment"
|
||||
app:summary="@string/settings_general_description"
|
||||
app:title="@string/settings_general_label" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_baseline_support_agent_24"
|
||||
app:fragment="eu.darken.capod.main.ui.settings.support.SupportFragment"
|
||||
app:summary="@string/settings_support_description"
|
||||
app:title="@string/settings_support_label" />
|
||||
|
||||
<PreferenceCategory android:title="@string/settings_category_other_label">
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_changelog_onsurface"
|
||||
android:key="core.changelog"
|
||||
android:title="@string/changelog_label"
|
||||
app:summary="v?.?.?">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://github.com/d4rken/capod/releases/latest" />
|
||||
</Preference>
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_heart"
|
||||
app:fragment="eu.darken.capod.main.ui.settings.acks.AcknowledgementsFragment"
|
||||
app:summary="@string/general_thank_you_label"
|
||||
app:title="@string/settings_acknowledgements_label" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_baseline_book_24"
|
||||
app:summary="@string/settings_privacy_policy_desc"
|
||||
app:title="@string/settings_privacy_policy_label">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://github.com/d4rken/capod/blob/main/PRIVACY_POLICY.md" />
|
||||
</Preference>
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_github_onsurface"
|
||||
android:summary="@string/issue_tracker_description"
|
||||
android:title="@string/issue_tracker_label">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://github.com/d4rken/capod/issues" />
|
||||
</Preference>
|
||||
<Preference
|
||||
android:icon="@drawable/ic_discord_onsurface"
|
||||
android:summary="@string/discord_description"
|
||||
android:title="@string/discord_label">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="https://discord.gg/rrxxng35jq" />
|
||||
</Preference>
|
||||
<Preference
|
||||
android:icon="@drawable/ic_email_onsurface"
|
||||
android:key="support.email.darken"
|
||||
android:summary="@string/settings_support_email_developer_description"
|
||||
android:title="@string/settings_support_email_developer_label" />
|
||||
|
||||
<PreferenceCategory app:title="@string/settings_category_other_label">
|
||||
<Preference
|
||||
android:icon="@drawable/ic_id_onsurface"
|
||||
android:key="support.installid"
|
||||
android:summary="@string/settings_support_installid_desc"
|
||||
android:title="@string/settings_support_installid_label" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
Reference in New Issue
Block a user