WIP: Manage user settings
This commit is contained in:
parent
437bc76b8c
commit
678e5625dd
6 changed files with 110 additions and 6 deletions
|
@ -65,9 +65,9 @@ dependencies {
|
||||||
implementation "androidx.core:core-ktx:1.7.0"
|
implementation "androidx.core:core-ktx:1.7.0"
|
||||||
implementation "androidx.constraintlayout:constraintlayout:2.1.3"
|
implementation "androidx.constraintlayout:constraintlayout:2.1.3"
|
||||||
implementation "androidx.activity:activity-ktx:1.4.0"
|
implementation "androidx.activity:activity-ktx:1.4.0"
|
||||||
implementation "androidx.fragment:fragment-ktx:1.4.0"
|
implementation "androidx.fragment:fragment-ktx:1.4.1"
|
||||||
implementation "androidx.work:work-runtime-ktx:2.7.1"
|
implementation "androidx.work:work-runtime-ktx:2.7.1"
|
||||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
implementation 'androidx.preference:preference-ktx:1.2.0'
|
||||||
|
|
||||||
// JSON serialization
|
// JSON serialization
|
||||||
implementation 'com.google.code.gson:gson:2.8.9'
|
implementation 'com.google.code.gson:gson:2.8.9'
|
||||||
|
|
|
@ -22,10 +22,12 @@ import com.google.gson.Gson
|
||||||
import io.heckel.ntfy.BuildConfig
|
import io.heckel.ntfy.BuildConfig
|
||||||
import io.heckel.ntfy.R
|
import io.heckel.ntfy.R
|
||||||
import io.heckel.ntfy.db.Repository
|
import io.heckel.ntfy.db.Repository
|
||||||
|
import io.heckel.ntfy.db.User
|
||||||
import io.heckel.ntfy.log.Log
|
import io.heckel.ntfy.log.Log
|
||||||
import io.heckel.ntfy.service.SubscriberService
|
import io.heckel.ntfy.service.SubscriberService
|
||||||
import io.heckel.ntfy.util.formatBytes
|
import io.heckel.ntfy.util.formatBytes
|
||||||
import io.heckel.ntfy.util.formatDateShort
|
import io.heckel.ntfy.util.formatDateShort
|
||||||
|
import io.heckel.ntfy.util.shortUrl
|
||||||
import io.heckel.ntfy.util.toPriorityString
|
import io.heckel.ntfy.util.toPriorityString
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -35,7 +37,13 @@ import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class SettingsActivity : AppCompatActivity() {
|
/**
|
||||||
|
* Main settings
|
||||||
|
*
|
||||||
|
* The "nested screen" navigation stuff (for user management) has been taken from
|
||||||
|
* https://github.com/googlearchive/android-preferences/blob/master/app/src/main/java/com/example/androidx/preference/sample/MainActivity.kt
|
||||||
|
*/
|
||||||
|
class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
|
||||||
private lateinit var fragment: SettingsFragment
|
private lateinit var fragment: SettingsFragment
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -50,15 +58,58 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
.beginTransaction()
|
.beginTransaction()
|
||||||
.replace(R.id.settings_layout, fragment)
|
.replace(R.id.settings_layout, fragment)
|
||||||
.commit()
|
.commit()
|
||||||
|
} else {
|
||||||
|
title = savedInstanceState.getCharSequence(TITLE_TAG)
|
||||||
|
}
|
||||||
|
supportFragmentManager.addOnBackStackChangedListener {
|
||||||
|
if (supportFragmentManager.backStackEntryCount == 0) {
|
||||||
|
setTitle(R.string.settings_title)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action bar
|
// Action bar
|
||||||
title = getString(R.string.settings_title)
|
//title = getString(R.string.settings_title)
|
||||||
|
|
||||||
// Show 'Back' button
|
// Show 'Back' button
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
// Save current activity title so we can set it again after a configuration change
|
||||||
|
outState.putCharSequence(TITLE_TAG, title)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSupportNavigateUp(): Boolean {
|
||||||
|
if (supportFragmentManager.popBackStackImmediate()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.onSupportNavigateUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onPreferenceStartFragment(
|
||||||
|
caller: PreferenceFragmentCompat,
|
||||||
|
pref: Preference
|
||||||
|
): Boolean {
|
||||||
|
// Instantiate the new Fragment
|
||||||
|
val args = pref.extras
|
||||||
|
val fragment = supportFragmentManager.fragmentFactory.instantiate(
|
||||||
|
classLoader,
|
||||||
|
pref.fragment!!
|
||||||
|
).apply {
|
||||||
|
arguments = args
|
||||||
|
setTargetFragment(caller, 0)
|
||||||
|
}
|
||||||
|
// Replace the existing Fragment with the new Fragment
|
||||||
|
supportFragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.settings_layout, fragment)
|
||||||
|
.addToBackStack(null)
|
||||||
|
.commit()
|
||||||
|
title = pref.title
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
class SettingsFragment : PreferenceFragmentCompat() {
|
class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
private lateinit var repository: Repository
|
private lateinit var repository: Repository
|
||||||
private var autoDownloadSelection = AUTO_DOWNLOAD_SELECTION_NOT_SET
|
private var autoDownloadSelection = AUTO_DOWNLOAD_SELECTION_NOT_SET
|
||||||
|
@ -463,6 +514,41 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
data class NopasteResponse(val url: String)
|
data class NopasteResponse(val url: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UserSettingsFragment : PreferenceFragmentCompat() {
|
||||||
|
private lateinit var repository: Repository
|
||||||
|
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
setPreferencesFromResource(R.xml.user_preferences, rootKey)
|
||||||
|
|
||||||
|
// Dependencies (Fragments need a default constructor)
|
||||||
|
repository = Repository.getInstance(requireActivity())
|
||||||
|
|
||||||
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val usersByBaseUrl = repository.getUsers().groupBy { it.baseUrl }
|
||||||
|
activity?.runOnUiThread {
|
||||||
|
addUserPreferences(usersByBaseUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addUserPreferences(usersByBaseUrl: Map<String, List<User>>) {
|
||||||
|
usersByBaseUrl.forEach { entry ->
|
||||||
|
val baseUrl = entry.key
|
||||||
|
val users = entry.value
|
||||||
|
|
||||||
|
val preferenceCategory = PreferenceCategory(preferenceScreen.context)
|
||||||
|
preferenceCategory.title = shortUrl(baseUrl)
|
||||||
|
preferenceScreen.addPreference(preferenceCategory)
|
||||||
|
|
||||||
|
users.forEach { user ->
|
||||||
|
val preference = Preference(preferenceScreen.context)
|
||||||
|
preference.title = user.username
|
||||||
|
preferenceCategory.addPreference(preference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
if (requestCode == REQUEST_CODE_WRITE_EXTERNAL_STORAGE_PERMISSION_FOR_AUTO_DOWNLOAD) {
|
if (requestCode == REQUEST_CODE_WRITE_EXTERNAL_STORAGE_PERMISSION_FOR_AUTO_DOWNLOAD) {
|
||||||
|
@ -479,6 +565,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "NtfySettingsActivity"
|
private const val TAG = "NtfySettingsActivity"
|
||||||
|
private const val TITLE_TAG = "title"
|
||||||
private const val REQUEST_CODE_WRITE_EXTERNAL_STORAGE_PERMISSION_FOR_AUTO_DOWNLOAD = 2586
|
private const val REQUEST_CODE_WRITE_EXTERNAL_STORAGE_PERMISSION_FOR_AUTO_DOWNLOAD = 2586
|
||||||
private const val AUTO_DOWNLOAD_SELECTION_NOT_SET = -99L
|
private const val AUTO_DOWNLOAD_SELECTION_NOT_SET = -99L
|
||||||
private const val EXPORT_LOGS_COPY = "copy"
|
private const val EXPORT_LOGS_COPY = "copy"
|
||||||
|
|
|
@ -238,6 +238,11 @@
|
||||||
<string name="settings_appearance_dark_mode_entry_system">Use system default</string>
|
<string name="settings_appearance_dark_mode_entry_system">Use system default</string>
|
||||||
<string name="settings_appearance_dark_mode_entry_light">Light mode</string>
|
<string name="settings_appearance_dark_mode_entry_light">Light mode</string>
|
||||||
<string name="settings_appearance_dark_mode_entry_dark">Dark mode</string>
|
<string name="settings_appearance_dark_mode_entry_dark">Dark mode</string>
|
||||||
|
<string name="settings_users_header">Users</string>
|
||||||
|
<string name="settings_users_key">ManageUsers</string>
|
||||||
|
<string name="settings_users_title">Manage users</string>
|
||||||
|
<string name="settings_users_summary">Add or remove users used for protected topics</string>
|
||||||
|
<string name="settings_users_prefs_title">Users</string>
|
||||||
<string name="settings_unified_push_header">UnifiedPush</string>
|
<string name="settings_unified_push_header">UnifiedPush</string>
|
||||||
<string name="settings_unified_push_header_summary">Allows other apps to use ntfy as a message distributor. Find out more at unifiedpush.org.</string>
|
<string name="settings_unified_push_header_summary">Allows other apps to use ntfy as a message distributor. Find out more at unifiedpush.org.</string>
|
||||||
<string name="settings_unified_push_enabled_key">UnifiedPushEnabled</string>
|
<string name="settings_unified_push_enabled_key">UnifiedPushEnabled</string>
|
||||||
|
|
|
@ -32,6 +32,15 @@
|
||||||
app:entryValues="@array/settings_appearance_dark_mode_values"
|
app:entryValues="@array/settings_appearance_dark_mode_values"
|
||||||
app:defaultValue="-1"/>
|
app:defaultValue="-1"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
<PreferenceCategory
|
||||||
|
app:title="@string/settings_users_header"
|
||||||
|
app:layout="@layout/preference_category_material_edited">
|
||||||
|
<Preference
|
||||||
|
app:key="@string/settings_users_key"
|
||||||
|
app:title="@string/settings_users_title"
|
||||||
|
app:summary="@string/settings_users_summary"
|
||||||
|
app:fragment="io.heckel.ntfy.ui.SettingsActivity$UserSettingsFragment"/>
|
||||||
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
app:title="@string/settings_unified_push_header"
|
app:title="@string/settings_unified_push_header"
|
||||||
app:summary="@string/settings_unified_push_header_summary"
|
app:summary="@string/settings_unified_push_header_summary"
|
||||||
|
|
3
app/src/main/res/xml/user_preferences.xml
Normal file
3
app/src/main/res/xml/user_preferences.xml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
app:title="@string/settings_users_prefs_title">
|
||||||
|
</PreferenceScreen>
|
|
@ -1,3 +1,3 @@
|
||||||
Bug fixes:
|
Bug fixes:
|
||||||
* Fix download issues on SDK 29 "Movement not allowed" (#116)
|
* Fix download issues on SDK 29 "Movement not allowed" (#116, thanks Jakob)
|
||||||
* Fix for Android 12 crashes (#124)
|
* Fix for Android 12 crashes (#124, thanks @eskilop)
|
||||||
|
|
Loading…
Reference in a new issue