Merge pull request #776 from theimpulson/menu

Switch to toolbar APIs for working with menu
This commit is contained in:
Torsten Grote 2024-10-17 13:41:18 -03:00 committed by GitHub
commit 3fd615477d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 478 additions and 361 deletions

View file

@ -11,6 +11,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.stevesoltys.seedvault.R import com.stevesoltys.seedvault.R
import com.stevesoltys.seedvault.transport.backup.PackageService import com.stevesoltys.seedvault.transport.backup.PackageService
@ -41,12 +42,11 @@ class AboutDialogFragment : Fragment() {
contributorsView.movementMethod = linkMovementMethod contributorsView.movementMethod = linkMovementMethod
orgsView.movementMethod = linkMovementMethod orgsView.movementMethod = linkMovementMethod
v.requireViewById<Toolbar>(R.id.toolbar).setNavigationOnClickListener {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
return v return v
} }
override fun onStart() {
super.onStart()
activity?.setTitle(R.string.about_title)
}
} }

View file

@ -7,14 +7,13 @@ package com.stevesoltys.seedvault.settings
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.View.INVISIBLE import android.view.View.INVISIBLE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ProgressBar import android.widget.ProgressBar
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -32,7 +31,6 @@ class AppStatusFragment : Fragment(), AppStatusToggleListener {
private val layoutManager = LinearLayoutManager(context) private val layoutManager = LinearLayoutManager(context)
private val adapter = AppStatusAdapter(this) private val adapter = AppStatusAdapter(this)
private lateinit var appEditMenuItem: MenuItem
private lateinit var list: RecyclerView private lateinit var list: RecyclerView
private lateinit var progressBar: ProgressBar private lateinit var progressBar: ProgressBar
@ -41,7 +39,6 @@ class AppStatusFragment : Fragment(), AppStatusToggleListener {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle?, savedInstanceState: Bundle?,
): View { ): View {
setHasOptionsMenu(true)
val v: View = inflater.inflate(R.layout.fragment_app_status, container, false) val v: View = inflater.inflate(R.layout.fragment_app_status, container, false)
progressBar = v.requireViewById(R.id.progressBar) progressBar = v.requireViewById(R.id.progressBar)
@ -53,7 +50,17 @@ class AppStatusFragment : Fragment(), AppStatusToggleListener {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
activity?.setTitle(R.string.settings_backup_status_title) val toolbar = view.requireViewById<Toolbar>(R.id.toolbar).apply {
setOnMenuItemClickListener(::onMenuItemSelected)
setNavigationOnClickListener {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
}
viewModel.appEditMode.observe(viewLifecycleOwner) { enabled ->
toolbar.menu.findItem(R.id.edit_app_blacklist)?.isChecked = enabled
adapter.setEditMode(enabled)
}
list.apply { list.apply {
layoutManager = this@AppStatusFragment.layoutManager layoutManager = this@AppStatusFragment.layoutManager
@ -67,24 +74,12 @@ class AppStatusFragment : Fragment(), AppStatusToggleListener {
} }
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { private fun onMenuItemSelected(item: MenuItem): Boolean = when (item.itemId) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.app_status_menu, menu)
appEditMenuItem = menu.findItem(R.id.edit_app_blacklist)
// observe edit mode changes here where we are sure to have the MenuItem
viewModel.appEditMode.observe(viewLifecycleOwner) { enabled ->
appEditMenuItem.isChecked = enabled
adapter.setEditMode(enabled)
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
R.id.edit_app_blacklist -> { R.id.edit_app_blacklist -> {
viewModel.setEditMode(!item.isChecked) viewModel.setEditMode(!item.isChecked)
true true
} }
else -> super.onOptionsItemSelected(item) else -> false
} }
override fun onAppStatusToggled(status: AppStatus) { override fun onAppStatusToggled(status: AppStatus) {

View file

@ -7,7 +7,9 @@ package com.stevesoltys.seedvault.settings
import android.app.backup.IBackupManager import android.app.backup.IBackupManager
import android.os.Bundle import android.os.Bundle
import android.view.View
import androidx.activity.result.contract.ActivityResultContracts.CreateDocument import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
import androidx.appcompat.widget.Toolbar
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.Preference.OnPreferenceChangeListener import androidx.preference.Preference.OnPreferenceChangeListener
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
@ -66,9 +68,19 @@ class ExpertSettingsFragment : PreferenceFragmentCompat() {
} }
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.requireViewById<Toolbar>(R.id.toolbar).apply {
title = getString(R.string.settings_expert_title)
setNavigationOnClickListener {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
}
}
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
activity?.setTitle(R.string.settings_expert_title)
apkBackup.isEnabled = backupManager.isBackupEnabled apkBackup.isEnabled = backupManager.isBackupEnabled
} }
} }

View file

@ -8,6 +8,7 @@ package com.stevesoltys.seedvault.settings
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.widget.Toolbar
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceCategory import androidx.preference.PreferenceCategory
@ -39,6 +40,13 @@ class SchedulingFragment : PreferenceFragmentCompat(),
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
view.requireViewById<Toolbar>(R.id.toolbar).apply {
title = getString(R.string.settings_backup_scheduling_title)
setNavigationOnClickListener {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
}
val storage = backendManager.backendProperties val storage = backendManager.backendProperties
if (storage?.isUsb == true) { if (storage?.isUsb == true) {
findPreference<PreferenceCategory>("scheduling_category_conditions")?.isEnabled = false findPreference<PreferenceCategory>("scheduling_category_conditions")?.isEnabled = false
@ -60,12 +68,6 @@ class SchedulingFragment : PreferenceFragmentCompat(),
} }
} }
override fun onStart() {
super.onStart()
activity?.setTitle(R.string.settings_backup_scheduling_title)
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
settingsManager.registerOnSharedPreferenceChangeListener(this) settingsManager.registerOnSharedPreferenceChangeListener(this)

View file

@ -30,9 +30,6 @@ class SettingsActivity : RequireProvisioningActivity(), OnPreferenceStartFragmen
setContentView(R.layout.activity_fragment_container) setContentView(R.layout.activity_fragment_container)
setSupportActionBar(requireViewById(R.id.toolbar))
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
if (savedInstanceState == null && viewModel.isFirstStart) { if (savedInstanceState == null && viewModel.isFirstStart) {
// let user choose whether to restore on first start // let user choose whether to restore on first start
FirstRunFragment().show(supportFragmentManager, null) FirstRunFragment().show(supportFragmentManager, null)

View file

@ -11,12 +11,11 @@ import android.os.Bundle
import android.os.PowerManager import android.os.PowerManager
import android.os.RemoteException import android.os.RemoteException
import android.util.Log import android.util.Log
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import android.widget.Toast.LENGTH_LONG import android.widget.Toast.LENGTH_LONG
import androidx.appcompat.widget.Toolbar
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.Preference.OnPreferenceChangeListener import androidx.preference.Preference.OnPreferenceChangeListener
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
@ -53,9 +52,6 @@ class SettingsFragment : PreferenceFragmentCompat() {
private lateinit var backupStorage: TwoStatePreference private lateinit var backupStorage: TwoStatePreference
private lateinit var backupRecoveryCode: Preference private lateinit var backupRecoveryCode: Preference
private var menuBackupNow: MenuItem? = null
private var menuRestore: MenuItem? = null
private val backendProperties: BackendProperties<*>? private val backendProperties: BackendProperties<*>?
get() = backendManager.backendProperties get() = backendManager.backendProperties
@ -63,7 +59,6 @@ class SettingsFragment : PreferenceFragmentCompat() {
permitDiskReads { permitDiskReads {
setPreferencesFromResource(R.xml.settings, rootKey) setPreferencesFromResource(R.xml.settings, rootKey)
} }
setHasOptionsMenu(true)
backup = findPreference("backup")!! backup = findPreference("backup")!!
backup.onPreferenceChangeListener = OnPreferenceChangeListener { _, newValue -> backup.onPreferenceChangeListener = OnPreferenceChangeListener { _, newValue ->
@ -141,6 +136,20 @@ class SettingsFragment : PreferenceFragmentCompat() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val toolbar = view.requireViewById<Toolbar>(R.id.toolbar).apply {
title = getString(R.string.backup)
inflateMenu(R.menu.settings_menu)
setOnMenuItemClickListener(::onMenuItemSelected)
setNavigationOnClickListener {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
}
viewModel.backupPossible.observe(viewLifecycleOwner) { possible ->
toolbar.menu.findItem(R.id.action_backup)?.isEnabled = possible
toolbar.menu.findItem(R.id.action_restore)?.isEnabled = possible
}
viewModel.lastBackupTime.observe(viewLifecycleOwner) { time -> viewModel.lastBackupTime.observe(viewLifecycleOwner) { time ->
setAppBackupStatusSummary(time) setAppBackupStatusSummary(time)
} }
@ -157,9 +166,6 @@ class SettingsFragment : PreferenceFragmentCompat() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
// we need to re-set the title when returning to this fragment
activity?.setTitle(R.string.backup)
setBackupEnabledState() setBackupEnabledState()
setBackupLocationSummary() setBackupLocationSummary()
setAutoRestoreState() setAutoRestoreState()
@ -185,18 +191,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
} }
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { private fun onMenuItemSelected(item: MenuItem): Boolean = when (item.itemId) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.settings_menu, menu)
menuBackupNow = menu.findItem(R.id.action_backup)
menuRestore = menu.findItem(R.id.action_restore)
viewModel.backupPossible.observe(viewLifecycleOwner) { possible ->
menuBackupNow?.isEnabled = possible
menuRestore?.isEnabled = possible
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
R.id.action_backup -> { R.id.action_backup -> {
viewModel.backupNow() viewModel.backupNow()
true true
@ -219,7 +214,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
.commit() .commit()
true true
} }
else -> super.onOptionsItemSelected(item) else -> false
} }
private fun trySetBackupEnabled(enabled: Boolean): Boolean { private fun trySetBackupEnabled(enabled: Boolean): Boolean {

View file

@ -6,8 +6,6 @@
package com.stevesoltys.seedvault.ui package com.stevesoltys.seedvault.ui
import android.os.Bundle import android.os.Bundle
import android.view.MenuItem
import androidx.annotation.CallSuper
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.stevesoltys.seedvault.R import com.stevesoltys.seedvault.R
@ -19,15 +17,6 @@ abstract class BackupActivity : AppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
} }
@CallSuper
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
android.R.id.home -> {
onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
}
protected fun showFragment(f: Fragment, addToBackStack: Boolean = false, tag: String? = null) { protected fun showFragment(f: Fragment, addToBackStack: Boolean = false, tag: String? = null) {
supportFragmentManager.beginTransaction().apply { supportFragmentManager.beginTransaction().apply {
replace(R.id.fragment, f, tag) replace(R.id.fragment, f, tag)

View file

@ -6,9 +6,8 @@
package com.stevesoltys.seedvault.ui.files package com.stevesoltys.seedvault.ui.files
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import androidx.appcompat.widget.Toolbar
import com.stevesoltys.seedvault.R import com.stevesoltys.seedvault.R
import com.stevesoltys.seedvault.settings.SettingsViewModel import com.stevesoltys.seedvault.settings.SettingsViewModel
import org.calyxos.backup.storage.ui.backup.BackupContentFragment import org.calyxos.backup.storage.ui.backup.BackupContentFragment
@ -20,13 +19,15 @@ class FileSelectionFragment : BackupContentFragment() {
override val viewModel by viewModel<FileSelectionViewModel>() override val viewModel by viewModel<FileSelectionViewModel>()
private val settingsViewModel by sharedViewModel<SettingsViewModel>() private val settingsViewModel by sharedViewModel<SettingsViewModel>()
override fun onCreateView( override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
inflater: LayoutInflater, super.onViewCreated(view, savedInstanceState)
container: ViewGroup?,
savedInstanceState: Bundle?, view.requireViewById<Toolbar>(R.id.toolbar).apply {
): View { title = getString(R.string.settings_backup_files_title)
requireActivity().setTitle(R.string.settings_backup_files_title) setNavigationOnClickListener {
return super.onCreateView(inflater, container, savedInstanceState) requireActivity().onBackPressedDispatcher.onBackPressed()
}
}
} }
override fun onDestroy() { override fun onDestroy() {

View file

@ -6,7 +6,6 @@
package com.stevesoltys.seedvault.ui.recoverycode package com.stevesoltys.seedvault.ui.recoverycode
import android.os.Bundle import android.os.Bundle
import android.view.MenuItem
import android.view.WindowManager.LayoutParams.FLAG_SECURE import android.view.WindowManager.LayoutParams.FLAG_SECURE
import com.stevesoltys.seedvault.R import com.stevesoltys.seedvault.R
import com.stevesoltys.seedvault.isDebugBuild import com.stevesoltys.seedvault.isDebugBuild
@ -42,16 +41,6 @@ class RecoveryCodeActivity : BackupActivity() {
} }
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
}
}
private fun showOutput() { private fun showOutput() {
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.add(R.id.fragment, RecoveryCodeOutputFragment(), "Code") .add(R.id.fragment, RecoveryCodeOutputFragment(), "Code")

View file

@ -26,6 +26,7 @@ import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import android.widget.Toast.LENGTH_LONG import android.widget.Toast.LENGTH_LONG
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.appcompat.widget.Toolbar
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat.getMainExecutor import androidx.core.content.ContextCompat.getMainExecutor
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -105,7 +106,11 @@ class RecoveryCodeInputFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
activity?.setTitle(R.string.recovery_code_title) view.requireViewById<Toolbar>(R.id.toolbar).apply {
setNavigationOnClickListener {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
}
if (viewModel.isRestore) { if (viewModel.isRestore) {
introText.setText(R.string.recovery_code_input_intro) introText.setText(R.string.recovery_code_input_intro)

View file

@ -12,6 +12,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager.LayoutParams.FLAG_SECURE import android.view.WindowManager.LayoutParams.FLAG_SECURE
import android.widget.Button import android.widget.Button
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -44,6 +45,12 @@ class RecoveryCodeOutputFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
view.requireViewById<Toolbar>(R.id.toolbar).apply {
setNavigationOnClickListener {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
}
setGridParameters(wordList) setGridParameters(wordList)
wordList.adapter = RecoveryCodeAdapter(viewModel.wordList) wordList.adapter = RecoveryCodeAdapter(viewModel.wordList)

View file

@ -8,13 +8,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme" />
<FrameLayout <FrameLayout
android:id="@+id/fragment" android:id="@+id/fragment"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -3,151 +3,165 @@
SPDX-FileCopyrightText: 2020 The Calyx Institute SPDX-FileCopyrightText: 2020 The Calyx Institute
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
--> -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
app:navigationIcon="?attr/homeAsUpIndicator"
app:title="@string/about_title" />
<ImageView <ScrollView
android:id="@+id/logoView" android:layout_width="match_parent"
android:layout_width="128dp" android:layout_height="match_parent">
android:layout_height="128dp"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/ic_launcher"
tools:ignore="ContentDescription" />
<TextView <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/appNameView" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:text="@string/app_name"
android:textColor="?android:textColorPrimary"
android:textSize="26sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/backupNameView"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/logoView" />
<TextView <ImageView
android:id="@+id/backupNameView" android:id="@+id/logoView"
android:layout_width="wrap_content" android:layout_width="128dp"
android:layout_height="wrap_content" android:layout_height="128dp"
android:layout_marginTop="16dp" android:layout_marginStart="16dp"
android:layout_marginEnd="16dp" android:layout_marginTop="32dp"
android:text="@string/backup" android:layout_marginEnd="16dp"
android:textColor="?android:textColorPrimary" app:layout_constraintEnd_toEndOf="parent"
android:textSize="26sp" app:layout_constraintStart_toStartOf="parent"
android:textStyle="bold" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:srcCompat="@mipmap/ic_launcher"
app:layout_constraintHorizontal_bias="0.5" tools:ignore="ContentDescription" />
app:layout_constraintStart_toEndOf="@+id/appNameView"
app:layout_constraintTop_toBottomOf="@+id/logoView" />
<TextView <TextView
android:id="@+id/versionView" android:id="@+id/appNameView"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="16dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="8dp"
android:gravity="center_horizontal" android:text="@string/app_name"
android:text="@string/about_version" android:textColor="?android:textColorPrimary"
android:textSize="16sp" android:textSize="26sp"
app:layout_constraintEnd_toEndOf="parent" android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/backupNameView"
app:layout_constraintTop_toBottomOf="@+id/appNameView" /> app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/logoView" />
<TextView <TextView
android:id="@+id/summaryView" android:id="@+id/backupNameView"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginTop="16dp"
android:layout_marginTop="16dp" android:layout_marginEnd="16dp"
android:layout_marginEnd="16dp" android:text="@string/backup"
android:text="@string/about_summary" android:textColor="?android:textColorPrimary"
android:textSize="16sp" android:textSize="26sp"
app:layout_constraintEnd_toEndOf="parent" android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/versionView" /> app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/appNameView"
app:layout_constraintTop_toBottomOf="@+id/logoView" />
<TextView <TextView
android:id="@+id/contributorHeadline" android:id="@+id/versionView"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="16dp" android:layout_marginTop="8dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:text="@string/about_contributor_headline" android:gravity="center_horizontal"
android:textColor="?android:textColorPrimary" android:text="@string/about_version"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintTop_toBottomOf="@+id/appNameView" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/summaryView" />
<TextView <TextView
android:id="@+id/contributorView" android:id="@+id/summaryView"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="16dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:lineSpacingExtra="8dp" android:text="@string/about_summary"
android:text="@string/about_contributor_content" android:textSize="16sp"
android:textSize="16sp" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintTop_toBottomOf="@+id/versionView" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/contributorHeadline" />
<TextView <TextView
android:id="@+id/about_contributing_organizations_title" android:id="@+id/contributorHeadline"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:text="@string/about_contributing_organizations_title" android:text="@string/about_contributor_headline"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/contributorView" /> app:layout_constraintTop_toBottomOf="@+id/summaryView" />
<TextView <TextView
android:id="@+id/about_contributing_organizations_content" android:id="@+id/contributorView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp" android:lineSpacingExtra="8dp"
android:lineSpacingExtra="8dp" android:text="@string/about_contributor_content"
android:text="@string/about_contributing_organizations_content" android:textSize="16sp"
android:textSize="16sp" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintTop_toBottomOf="@+id/contributorHeadline" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/about_contributing_organizations_title"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout> <TextView
</ScrollView> android:id="@+id/about_contributing_organizations_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/about_contributing_organizations_title"
android:textColor="?android:textColorPrimary"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/contributorView" />
<TextView
android:id="@+id/about_contributing_organizations_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:lineSpacingExtra="8dp"
android:text="@string/about_contributing_organizations_content"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/about_contributing_organizations_title"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</LinearLayout>

View file

@ -8,6 +8,18 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:menu="@menu/app_status_menu"
app:navigationIcon="?attr/homeAsUpIndicator"
app:title="@string/settings_backup_status_title" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/list" android:id="@+id/list"
android:layout_width="0dp" android:layout_width="0dp"
@ -15,7 +27,7 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toBottomOf="@id/toolbar" />
<ProgressBar <ProgressBar
android:id="@+id/progressBar" android:id="@+id/progressBar"

View file

@ -3,87 +3,100 @@
SPDX-FileCopyrightText: 2020 The Calyx Institute SPDX-FileCopyrightText: 2020 The Calyx Institute
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
--> -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fillViewport="true"> android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:context=".ui.recoverycode.RecoveryCodeInputFragment"> android:minHeight="?attr/actionBarSize"
app:navigationIcon="?attr/homeAsUpIndicator"
app:title="@string/recovery_code_title" />
<ImageView <ScrollView
android:id="@+id/introIcon" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="match_parent"
android:layout_height="wrap_content" android:fillViewport="true">
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:src="@drawable/ic_info_outline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/introText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/recovery_code_confirm_intro"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/introIcon"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/divider"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="16dp"
android:background="@color/divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/introText" />
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/wordList" android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/doneButton" tools:context=".ui.recoverycode.RecoveryCodeInputFragment">
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider">
<include layout="@layout/recovery_code_input" /> <ImageView
android:id="@+id/introIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:src="@drawable/ic_info_outline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/introText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/recovery_code_confirm_intro"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/introIcon"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/divider"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="16dp"
android:background="@color/divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/introText" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/wordList"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/doneButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider">
<include layout="@layout/recovery_code_input" />
</androidx.constraintlayout.widget.ConstraintLayout>
<Button
android:id="@+id/doneButton"
style="@style/SudPrimaryButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="40dp"
android:text="@string/recovery_code_done_button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<Button
android:id="@+id/newCodeButton"
style="@style/SudSecondaryButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:text="@string/recovery_code_verification_generate_new"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<Button </LinearLayout>
android:id="@+id/doneButton"
style="@style/SudPrimaryButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="40dp"
android:text="@string/recovery_code_done_button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<Button
android:id="@+id/newCodeButton"
style="@style/SudSecondaryButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:text="@string/recovery_code_verification_generate_new"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View file

@ -10,6 +10,17 @@
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".ui.recoverycode.RecoveryCodeActivity"> tools:context=".ui.recoverycode.RecoveryCodeActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="?attr/homeAsUpIndicator"
app:title="@string/recovery_code_title" />
<ImageView <ImageView
android:id="@+id/introIcon" android:id="@+id/introIcon"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -18,7 +29,7 @@
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:src="@drawable/ic_info_outline" android:src="@drawable/ic_info_outline"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toBottomOf="@id/toolbar"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<TextView <TextView
@ -32,7 +43,7 @@
android:textSize="16sp" android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/introIcon" app:layout_constraintStart_toEndOf="@+id/introIcon"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toBottomOf="@id/toolbar" />
<TextView <TextView
android:id="@+id/introText2" android:id="@+id/introText2"
@ -78,8 +89,8 @@
style="@style/SudPrimaryButton" style="@style/SudPrimaryButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/recovery_code_confirm_button"
android:layout_marginEnd="40dp" android:layout_marginEnd="40dp"
android:text="@string/recovery_code_confirm_button"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/wordList" /> app:layout_constraintTop_toBottomOf="@+id/wordList" />

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2024 The Calyx Institute
SPDX-License-Identifier: Apache-2.0
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context=".settings.SettingsFragment">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
app:navigationIcon="?attr/homeAsUpIndicator" />
<!-- Required ViewGroup for PreferenceFragmentCompat -->
<FrameLayout
android:id="@android:id/list_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

View file

@ -10,13 +10,17 @@
<item name="colorError">@color/red</item> <item name="colorError">@color/red</item>
<item name="android:windowBackground">@color/background</item> <item name="android:windowBackground">@color/background</item>
<item name="fontFamily">@*android:string/config_bodyFontFamily</item> <item name="fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item> <item name="preferenceTheme">@style/PreferenceTheme</item>
<item name="android:windowLightStatusBar">@bool/isLight</item> <item name="android:windowLightStatusBar">@bool/isLight</item>
<item name="android:statusBarColor">@color/background</item> <item name="android:statusBarColor">@color/background</item>
<item name="android:windowLightNavigationBar">@bool/isLight</item> <item name="android:windowLightNavigationBar">@bool/isLight</item>
<item name="android:navigationBarColor">@color/background</item> <item name="android:navigationBarColor">@color/background</item>
</style> </style>
<style name="PreferenceTheme" parent="PreferenceThemeOverlay">
<item name="android:layout">@layout/fragment_settings</item>
</style>
<!-- Copied from Settings --> <!-- Copied from Settings -->
<style name="ActionPrimaryButton" parent="android:Widget.DeviceDefault.Button.Colored" /> <style name="ActionPrimaryButton" parent="android:Widget.DeviceDefault.Button.Colored" />

View file

@ -9,6 +9,7 @@ import android.app.Application
import android.os.StrictMode import android.os.StrictMode
import android.os.StrictMode.VmPolicy import android.os.StrictMode.VmPolicy
import android.util.Log import android.util.Log
import com.google.android.material.color.DynamicColors
import de.grobox.storagebackuptester.crypto.KeyManager import de.grobox.storagebackuptester.crypto.KeyManager
import de.grobox.storagebackuptester.plugin.TestSafBackend import de.grobox.storagebackuptester.plugin.TestSafBackend
import de.grobox.storagebackuptester.settings.SettingsManager import de.grobox.storagebackuptester.settings.SettingsManager
@ -26,6 +27,7 @@ class App : Application() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
DynamicColors.applyToActivitiesIfAvailable(this)
StrictMode.setThreadPolicy( StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder() StrictMode.ThreadPolicy.Builder()
.detectAll() .detectAll()

View file

@ -11,8 +11,6 @@ import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.provider.Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION import android.provider.Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.View.INVISIBLE import android.view.View.INVISIBLE
@ -22,6 +20,7 @@ import android.widget.Button
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.Toast import android.widget.Toast
import android.widget.Toast.LENGTH_SHORT import android.widget.Toast.LENGTH_SHORT
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -48,7 +47,6 @@ open class LogFragment : Fragment() {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle?, savedInstanceState: Bundle?,
): View { ): View {
setHasOptionsMenu(true)
val v = inflater.inflate(R.layout.fragment_log, container, false) val v = inflater.inflate(R.layout.fragment_log, container, false)
list = v.findViewById(R.id.listView) list = v.findViewById(R.id.listView)
list.adapter = adapter list.adapter = adapter
@ -75,16 +73,16 @@ open class LogFragment : Fragment() {
return v return v
} }
override fun onStart() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onStart() super.onViewCreated(view, savedInstanceState)
requireActivity().setTitle(R.string.app_name)
view.requireViewById<Toolbar>(R.id.toolbar).apply {
title = getString(R.string.app_name)
setOnMenuItemClickListener(::onMenuItemSelected)
}
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { private fun onMenuItemSelected(item: MenuItem): Boolean {
inflater.inflate(R.menu.fragment_main, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) { return when (item.itemId) {
R.id.settings -> { R.id.settings -> {
if (!checkPermission()) return false if (!checkPermission()) return false
@ -108,7 +106,7 @@ open class LogFragment : Fragment() {
startActivity(shareIntent) startActivity(shareIntent)
true true
} }
else -> super.onOptionsItemSelected(item) else -> false
} }
} }

View file

@ -8,6 +8,11 @@ package de.grobox.storagebackuptester
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat.setOnApplyWindowInsetsListener
import androidx.core.view.WindowCompat.setDecorFitsSystemWindows
import androidx.core.view.WindowInsetsCompat.CONSUMED
import androidx.core.view.WindowInsetsCompat.Type.displayCutout
import androidx.core.view.WindowInsetsCompat.Type.systemBars
import de.grobox.storagebackuptester.crypto.KeyManager import de.grobox.storagebackuptester.crypto.KeyManager
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
@ -16,6 +21,13 @@ class MainActivity : AppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
setDecorFitsSystemWindows(window, false)
setOnApplyWindowInsetsListener(window.decorView.rootView) { v, windowInsets ->
val insets = windowInsets.getInsets(systemBars() or displayCutout())
v.setPadding(insets.left, insets.top, insets.right, insets.bottom)
CONSUMED
}
if (savedInstanceState == null) { if (savedInstanceState == null) {
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.replace(R.id.container, LogFragment.newInstance()) .replace(R.id.container, LogFragment.newInstance())

View file

@ -31,7 +31,7 @@ class DemoSnapshotFragment : SnapshotFragment() {
bottomStub.layoutResource = R.layout.footer_snapshot bottomStub.layoutResource = R.layout.footer_snapshot
val footer = bottomStub.inflate() val footer = bottomStub.inflate()
footer.findViewById<Button>(R.id.button).setOnClickListener { footer.findViewById<Button>(R.id.button).setOnClickListener {
requireActivity().onBackPressed() requireActivity().onBackPressedDispatcher.onBackPressed()
} }
return v return v
} }

View file

@ -10,8 +10,6 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.View.FOCUS_DOWN import android.view.View.FOCUS_DOWN
@ -21,6 +19,7 @@ import android.view.ViewGroup
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.TextView import android.widget.TextView
import androidx.annotation.UiThread import androidx.annotation.UiThread
import androidx.appcompat.widget.Toolbar
import androidx.core.widget.NestedScrollView import androidx.core.widget.NestedScrollView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
@ -53,8 +52,6 @@ open class MediaScanFragment : Fragment() {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle?, savedInstanceState: Bundle?,
): View { ): View {
setHasOptionsMenu(true)
requireActivity().title = arguments?.getString("name")
val v = inflater.inflate(R.layout.fragment_scan, container, false) val v = inflater.inflate(R.layout.fragment_scan, container, false)
scrollView = v.findViewById(R.id.scrollView) scrollView = v.findViewById(R.id.scrollView)
logView = v.findViewById(R.id.logView) logView = v.findViewById(R.id.logView)
@ -63,11 +60,19 @@ open class MediaScanFragment : Fragment() {
return v return v
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
inflater.inflate(R.menu.fragment_scan, menu) super.onViewCreated(view, savedInstanceState)
view.requireViewById<Toolbar>(R.id.toolbar).apply {
title = arguments?.getString("name")
setOnMenuItemClickListener(::onMenuItemSelected)
setNavigationOnClickListener {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
}
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { private fun onMenuItemSelected(item: MenuItem): Boolean {
return when (item.itemId) { return when (item.itemId) {
R.id.refresh -> { R.id.refresh -> {
loadText() loadText()
@ -85,7 +90,7 @@ open class MediaScanFragment : Fragment() {
startActivity(shareIntent) startActivity(shareIntent)
true true
} }
else -> super.onOptionsItemSelected(item) else -> false
} }
} }

View file

@ -9,14 +9,12 @@ import android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
import android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION import android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import android.widget.Toast.LENGTH_SHORT import android.widget.Toast.LENGTH_SHORT
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import de.grobox.storagebackuptester.MainViewModel import de.grobox.storagebackuptester.MainViewModel
@ -44,18 +42,21 @@ class SettingsFragment : BackupContentFragment() {
onBackupUriReceived(uri) onBackupUriReceived(uri)
} }
override fun onCreateView( override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
inflater: LayoutInflater, super.onViewCreated(view, savedInstanceState)
container: ViewGroup?,
savedInstanceState: Bundle?, view.requireViewById<Toolbar>(R.id.toolbar).apply {
): View { title = "Settings"
setHasOptionsMenu(true) inflateMenu(R.menu.fragment_settings)
requireActivity().title = "Settings" onCreateMenu(menu)
return super.onCreateView(inflater, container, savedInstanceState) setOnMenuItemClickListener(::onMenuItemSelected)
setNavigationOnClickListener {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
}
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { private fun onCreateMenu(menu: Menu) {
inflater.inflate(R.menu.fragment_settings, menu)
backupLocationItem = menu.findItem(R.id.backup_location) backupLocationItem = menu.findItem(R.id.backup_location)
backupLocationItem.isChecked = viewModel.hasBackupLocation() backupLocationItem.isChecked = viewModel.hasBackupLocation()
jobItem = menu.findItem(R.id.backup_job) jobItem = menu.findItem(R.id.backup_job)
@ -65,7 +66,7 @@ class SettingsFragment : BackupContentFragment() {
restoreItem.isEnabled = backupLocationItem.isChecked restoreItem.isEnabled = backupLocationItem.isChecked
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { private fun onMenuItemSelected(item: MenuItem): Boolean {
return when (item.itemId) { return when (item.itemId) {
R.id.info -> { R.id.info -> {
parentFragmentManager.beginTransaction() parentFragmentManager.beginTransaction()
@ -102,7 +103,7 @@ class SettingsFragment : BackupContentFragment() {
Toast.makeText(requireContext(), "Cache cleared", LENGTH_SHORT).show() Toast.makeText(requireContext(), "Cache cleared", LENGTH_SHORT).show()
true true
} }
else -> super.onOptionsItemSelected(item) else -> false
} }
} }

View file

@ -9,6 +9,16 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:menu="@menu/fragment_main" />
<ProgressBar <ProgressBar
android:id="@+id/horizontalProgressBar" android:id="@+id/horizontalProgressBar"
style="?android:attr/progressBarStyleHorizontal" style="?android:attr/progressBarStyleHorizontal"
@ -16,7 +26,7 @@
android:layout_height="5dp" android:layout_height="5dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toBottomOf="@id/toolbar"
tools:max="10" tools:max="10"
tools:progress="7" /> tools:progress="7" />

View file

@ -9,13 +9,24 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:menu="@menu/fragment_scan"
app:navigationIcon="?attr/homeAsUpIndicator" />
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:id="@+id/scrollView" android:id="@+id/scrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="0dp"
android:fadeScrollbars="false" android:fadeScrollbars="false"
android:scrollbars="vertical" android:scrollbars="vertical"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toBottomOf="@id/toolbar">
<TextView <TextView
android:id="@+id/logView" android:id="@+id/logView"

View file

@ -4,7 +4,7 @@
--> -->
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Theme.StorageBackupTester" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <style name="Theme.StorageBackupTester" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">@color/matrix</item> <item name="colorPrimary">@color/matrix</item>
<item name="colorPrimaryVariant">@color/purple_700</item> <item name="colorPrimaryVariant">@color/purple_700</item>

View file

@ -4,7 +4,7 @@
--> -->
<resources> <resources>
<style name="Theme.StorageBackupTester" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <style name="Theme.StorageBackupTester" parent="Theme.Material3.DayNight.NoActionBar">
<item name="colorPrimary">@color/matrix</item> <item name="colorPrimary">@color/matrix</item>
<item name="colorPrimaryVariant">@color/purple_700</item> <item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item> <item name="colorOnPrimary">@color/white</item>

View file

@ -3,28 +3,40 @@
SPDX-FileCopyrightText: 2021 The Calyx Institute SPDX-FileCopyrightText: 2021 The Calyx Institute
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
--> -->
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView <androidx.appcompat.widget.Toolbar
android:id="@+id/list" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
app:layoutManager="LinearLayoutManager"
tools:listitem="@layout/item_media" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom|end" android:minHeight="?attr/actionBarSize"
android:layout_margin="16dp" app:navigationIcon="?attr/homeAsUpIndicator" />
android:contentDescription="@string/content_add"
android:src="@drawable/ic_add"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> <androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
app:layoutManager="LinearLayoutManager"
tools:listitem="@layout/item_media" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:contentDescription="@string/content_add"
android:src="@drawable/ic_add"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>