From 35a835791e91e6ca08ce66d52f91df25000c2c3d Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Sat, 6 Feb 2021 13:58:36 +0100 Subject: [PATCH 1/5] feat: update core and maps modules dependencies --- .idea/compiler.xml | 6 + .idea/gradle.xml | 1 + .idea/jarRepositories.xml | 25 + build.gradle | 6 +- gn_mobile_core | 2 +- gn_mobile_maps | 2 +- gn_mobile_occtax.iml | 3 +- gradle/wrapper/gradle-wrapper.properties | 4 +- .../geonature/occtax/ui/home/HomeActivity.kt | 355 +++++++++++++- .../geonature/occtax/ui/home/HomeFragment.kt | 448 ------------------ .../ui/home/InputRecyclerViewAdapter.kt | 2 +- .../ui/input/InputPagerFragmentActivity.kt | 6 +- .../occtax/ui/settings/PreferencesActivity.kt | 19 +- .../occtax/ui/settings/PreferencesFragment.kt | 88 ++-- .../{fragment_home.xml => activity_home.xml} | 3 +- occtax/src/main/res/values-fr/prefs.xml | 1 - occtax/src/main/res/values/prefs.xml | 1 - occtax/src/main/res/xml/preferences.xml | 37 -- occtax/src/main/res/xml/preferences_about.xml | 12 + .../src/main/res/xml/preferences_dataset.xml | 11 + .../main/res/xml/preferences_observers.xml | 11 + 21 files changed, 493 insertions(+), 550 deletions(-) create mode 100644 .idea/compiler.xml create mode 100644 .idea/jarRepositories.xml delete mode 100644 occtax/src/main/java/fr/geonature/occtax/ui/home/HomeFragment.kt rename occtax/src/main/res/layout/{fragment_home.xml => activity_home.xml} (97%) delete mode 100644 occtax/src/main/res/xml/preferences.xml create mode 100644 occtax/src/main/res/xml/preferences_about.xml create mode 100644 occtax/src/main/res/xml/preferences_dataset.xml create mode 100644 occtax/src/main/res/xml/preferences_observers.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 00000000..61a9130c --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 54641b57..ffb732d9 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -19,6 +19,7 @@ diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 00000000..a5f05cd8 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 36302f06..7eb12487 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.72' + ext.kotlin_version = '1.4.21' repositories { google() @@ -12,9 +12,9 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'com.android.tools.build:gradle:4.1.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "org.jlleitschuh.gradle:ktlint-gradle:9.1.1" + classpath "org.jlleitschuh.gradle:ktlint-gradle:9.4.1" // NOTE: Do not place application dependencies here; they belong // in the individual module build.gradle files } diff --git a/gn_mobile_core b/gn_mobile_core index fb72771c..dda0fabe 160000 --- a/gn_mobile_core +++ b/gn_mobile_core @@ -1 +1 @@ -Subproject commit fb72771c9b199b2a914c965c8066ef8f2bf1ad65 +Subproject commit dda0fabe35eb70fb7f3a127abded7848b39fd29f diff --git a/gn_mobile_maps b/gn_mobile_maps index 9dc402f1..4048be45 160000 --- a/gn_mobile_maps +++ b/gn_mobile_maps @@ -1 +1 @@ -Subproject commit 9dc402f1386235ebd55693615941f3cf524b37c0 +Subproject commit 4048be451221e00617f664e1fd9710d0c6bc2d25 diff --git a/gn_mobile_occtax.iml b/gn_mobile_occtax.iml index 2658f880..043f8194 100644 --- a/gn_mobile_occtax.iml +++ b/gn_mobile_occtax.iml @@ -8,10 +8,11 @@ - + + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b6c7184c..7fd3b413 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Jun 01 15:04:01 CEST 2020 +#Mon Feb 01 22:04:15 CET 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/home/HomeActivity.kt b/occtax/src/main/java/fr/geonature/occtax/ui/home/HomeActivity.kt index 5d687f40..f0ac94fd 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/home/HomeActivity.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/home/HomeActivity.kt @@ -1,49 +1,267 @@ package fr.geonature.occtax.ui.home +import android.Manifest +import android.annotation.SuppressLint +import android.database.Cursor import android.os.Bundle +import android.os.Vibrator +import android.util.Log +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.view.animation.AnimationUtils +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity +import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.core.content.ContextCompat +import androidx.core.os.bundleOf +import androidx.lifecycle.ViewModelProvider +import androidx.loader.app.LoaderManager +import androidx.loader.content.CursorLoader +import androidx.loader.content.Loader +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.floatingactionbutton.FloatingActionButton +import com.google.android.material.snackbar.BaseTransientBottomBar +import com.google.android.material.snackbar.Snackbar +import fr.geonature.commons.data.AppSync +import fr.geonature.commons.data.helper.Provider +import fr.geonature.commons.ui.adapter.AbstractListItemRecyclerViewAdapter +import fr.geonature.commons.util.PermissionUtils +import fr.geonature.commons.util.observeOnce +import fr.geonature.occtax.R import fr.geonature.occtax.input.Input +import fr.geonature.occtax.input.InputViewModel import fr.geonature.occtax.settings.AppSettings +import fr.geonature.occtax.settings.AppSettingsViewModel import fr.geonature.occtax.ui.input.InputPagerFragmentActivity import fr.geonature.occtax.ui.settings.PreferencesActivity +import fr.geonature.occtax.ui.shared.view.ListItemActionView import fr.geonature.occtax.util.IntentUtils.syncActivity /** * Home screen Activity. * - * @see HomeFragment - * * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) */ -class HomeActivity : AppCompatActivity(), - HomeFragment.OnHomeFragmentListener { +class HomeActivity : AppCompatActivity() { + + private lateinit var appSettingsViewModel: AppSettingsViewModel + private lateinit var inputViewModel: InputViewModel + + private var homeContent: CoordinatorLayout? = null + private var appSyncView: AppSyncView? = null + private var inputRecyclerView: RecyclerView? = null + private var inputEmptyTextView: TextView? = null + private var fab: FloatingActionButton? = null + + private lateinit var adapter: InputRecyclerViewAdapter + + private var appSettings: AppSettings? = null + + private val loaderCallbacks = object : LoaderManager.LoaderCallbacks { + override fun onCreateLoader( + id: Int, + args: Bundle? + ): Loader { + return when (id) { + LOADER_APP_SYNC -> CursorLoader( + this@HomeActivity, + Provider.buildUri( + AppSync.TABLE_NAME, + args?.getString(AppSync.COLUMN_ID) + ?: "" + ), + null, + null, + null, + null + ) + else -> throw IllegalArgumentException() + } + } + + override fun onLoadFinished( + loader: Loader, + data: Cursor? + ) { + + if (data == null) { + Log.w( + TAG, + "Failed to load data from '${(loader as CursorLoader).uri}'" + ) + + return + } + + when (loader.id) { + LOADER_APP_SYNC -> { + if (data.moveToFirst()) { + appSyncView?.setAppSync(AppSync.fromCursor(data)) + } + } + } + } + + override fun onLoaderReset(loader: Loader) { + // nothing to do... + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - if (savedInstanceState == null) { - supportFragmentManager.beginTransaction() - .replace( - android.R.id.content, - HomeFragment.newInstance() + setContentView(R.layout.activity_home) + + homeContent = findViewById(R.id.homeContent) + appSyncView = findViewById(R.id.appSyncView) + inputRecyclerView = findViewById(R.id.inputRecyclerView) + inputEmptyTextView = findViewById(R.id.inputEmptyTextView) + fab = findViewById(R.id.fab) + + appSettingsViewModel = configureAppSettingsViewModel() + inputViewModel = configureInputViewModel() + + appSyncView?.setListener(object : ListItemActionView.OnListItemActionViewListener { + override fun onAction() { + syncActivity(this@HomeActivity)?.also { + startActivity(it) + } + } + }) + + fab?.setOnClickListener { + val appSettings = appSettings ?: return@setOnClickListener + + startInput(appSettings) + } + + adapter = InputRecyclerViewAdapter(object : + AbstractListItemRecyclerViewAdapter.OnListItemRecyclerViewAdapterListener { + override fun onClick(item: Input) { + val appSettings = appSettings ?: return + + Log.i( + TAG, + "input selected: ${item.id}" + ) + + startInput( + appSettings, + item ) - .commit() + } + + override fun onLongClicked( + position: Int, + item: Input + ) { + inputViewModel.deleteInput(item) + + ContextCompat.getSystemService( + this@HomeActivity, + Vibrator::class.java + )?.vibrate(100) + + makeSnackbar(getString(R.string.home_snackbar_input_deleted)) + ?.setAction(R.string.home_snackbar_input_undo) { + inputViewModel.restoreDeletedInput() + } + ?.show() + } + + override fun showEmptyTextView(show: Boolean) { + if (inputEmptyTextView?.visibility == View.VISIBLE == show) { + return + } + + if (show) { + inputEmptyTextView?.startAnimation( + AnimationUtils.loadAnimation( + this@HomeActivity, + android.R.anim.fade_in + ) + ) + inputEmptyTextView?.visibility = View.VISIBLE + } else { + inputEmptyTextView?.startAnimation( + AnimationUtils.loadAnimation( + this@HomeActivity, + android.R.anim.fade_out + ) + ) + inputEmptyTextView?.visibility = View.GONE + } + } + }) + + inputRecyclerView?.apply { + layoutManager = LinearLayoutManager(context) + adapter = this@HomeActivity.adapter + + val dividerItemDecoration = DividerItemDecoration( + context, + (layoutManager as LinearLayoutManager).orientation + ) + addItemDecoration(dividerItemDecoration) + } + + if (checkAppSync()) { + checkPermissions() } } - override fun onShowSettings() { - startActivity(PreferencesActivity.newIntent(this)) + override fun onResume() { + super.onResume() + + LoaderManager.getInstance(this) + .restartLoader( + LOADER_APP_SYNC, + bundleOf(AppSync.COLUMN_ID to packageName), + loaderCallbacks + ) + } + + @SuppressLint("RestrictedApi") + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + menuInflater.inflate( + R.menu.settings, + menu + ) + + return true } - override fun onStartSync() { - syncActivity(this)?.also { - startActivity(it) + override fun onPrepareOptionsMenu(menu: Menu?): Boolean { + menu?.run { + findItem(R.id.menu_settings)?.also { + it.isEnabled = appSettings != null + } + } + + return super.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.menu_settings -> { + startActivity( + PreferencesActivity.newIntent( + this, + appSettings + ) + ) + true + } + else -> super.onOptionsItemSelected(item) } } - override fun onStartInput( + private fun startInput( appSettings: AppSettings, - input: Input? + input: Input? = null ) { startActivity( InputPagerFragmentActivity.newIntent( @@ -53,4 +271,107 @@ class HomeActivity : AppCompatActivity(), ) ) } + + private fun configureAppSettingsViewModel(): AppSettingsViewModel { + return ViewModelProvider( + this, + fr.geonature.commons.settings.AppSettingsViewModel.Factory { + AppSettingsViewModel(application) + } + ).get(AppSettingsViewModel::class.java) + } + + private fun configureInputViewModel(): InputViewModel { + return ViewModelProvider( + this, + fr.geonature.commons.input.InputViewModel.Factory { InputViewModel(this.application) }).get( + InputViewModel::class.java + ) + } + + private fun loadAppSettings() { + appSettingsViewModel.loadAppSettings() + .observeOnce(this) { + if (it?.mapSettings == null) { + fab?.hide() + adapter.clear() + invalidateOptionsMenu() + + makeSnackbar( + getString( + if (it == null) R.string.snackbar_settings_not_found else R.string.snackbar_settings_map_invalid, + appSettingsViewModel.getAppSettingsFilename() + ) + )?.show() + } else { + appSettings = it + fab?.show() + invalidateOptionsMenu() + + loadInputs() + } + } + } + + private fun loadInputs() { + inputViewModel.readInputs().observe( + this, + { + adapter.setItems(it) + } + ) + } + + private fun checkAppSync(): Boolean { + if (syncActivity(this) == null) { + fab?.hide() + appSyncView?.enableActionButton(false) + makeSnackbar(getString(R.string.snackbar_app_sync_not_found))?.show() + + return false + } + + appSyncView?.enableActionButton() + + return true + } + + private fun checkPermissions() { + PermissionUtils.requestPermissions( + this, + listOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), + { result -> + if (result.values.all { it }) { + loadAppSettings() + } else { + makeSnackbar(getString(R.string.snackbar_permissions_not_granted))?.show() + } + }, + { callback -> + makeSnackbar( + getString(R.string.snackbar_permission_external_storage_rationale), + BaseTransientBottomBar.LENGTH_INDEFINITE + )?.setAction(android.R.string.ok) { callback() } + ?.show() + }) + } + + private fun makeSnackbar( + text: CharSequence, + @BaseTransientBottomBar.Duration duration: Int = Snackbar.LENGTH_LONG + ): Snackbar? { + val view = homeContent ?: return null + + return Snackbar.make( + view, + text, + duration + ) + } + + companion object { + private val TAG = HomeActivity::class.java.name + + private const val LOADER_APP_SYNC = 1 + } } diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/home/HomeFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/home/HomeFragment.kt deleted file mode 100644 index 72010580..00000000 --- a/occtax/src/main/java/fr/geonature/occtax/ui/home/HomeFragment.kt +++ /dev/null @@ -1,448 +0,0 @@ -package fr.geonature.occtax.ui.home - -import android.Manifest -import android.content.Context -import android.database.Cursor -import android.os.Bundle -import android.os.Vibrator -import android.util.Log -import android.view.LayoutInflater -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View -import android.view.ViewGroup -import android.view.animation.AnimationUtils -import android.widget.TextView -import androidx.coordinatorlayout.widget.CoordinatorLayout -import androidx.core.content.ContextCompat -import androidx.core.os.bundleOf -import androidx.fragment.app.Fragment -import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModelProvider -import androidx.loader.app.LoaderManager -import androidx.loader.content.CursorLoader -import androidx.loader.content.Loader -import androidx.recyclerview.widget.DividerItemDecoration -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import com.google.android.material.floatingactionbutton.FloatingActionButton -import com.google.android.material.snackbar.Snackbar -import fr.geonature.commons.data.AppSync -import fr.geonature.commons.data.helper.Provider.buildUri -import fr.geonature.commons.ui.adapter.AbstractListItemRecyclerViewAdapter -import fr.geonature.commons.util.PermissionUtils -import fr.geonature.commons.util.PermissionUtils.checkPermissions -import fr.geonature.commons.util.PermissionUtils.checkSelfPermissions -import fr.geonature.commons.util.PermissionUtils.requestPermissions -import fr.geonature.commons.util.observeOnce -import fr.geonature.occtax.R -import fr.geonature.occtax.input.Input -import fr.geonature.occtax.input.InputViewModel -import fr.geonature.occtax.settings.AppSettings -import fr.geonature.occtax.settings.AppSettingsViewModel -import fr.geonature.occtax.ui.shared.view.ListItemActionView -import fr.geonature.occtax.util.IntentUtils.syncActivity - -/** - * Home screen [Fragment]. - * - * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) - */ -class HomeFragment : Fragment() { - - private var listener: OnHomeFragmentListener? = null - private lateinit var adapter: InputRecyclerViewAdapter - private var appSettings: AppSettings? = null - private var appSettingsViewModel: AppSettingsViewModel? = null - private var inputViewModel: InputViewModel? = null - - private var homeContent: CoordinatorLayout? = null - private var appSyncView: AppSyncView? = null - private var inputRecyclerView: RecyclerView? = null - private var inputEmptyTextView: TextView? = null - private var fab: FloatingActionButton? = null - - private val loaderCallbacks = object : LoaderManager.LoaderCallbacks { - override fun onCreateLoader( - id: Int, - args: Bundle? - ): Loader { - return when (id) { - LOADER_APP_SYNC -> CursorLoader( - requireContext(), - buildUri( - AppSync.TABLE_NAME, - args?.getString(AppSync.COLUMN_ID) - ?: "" - ), - null, - null, - null, - null - ) - else -> throw IllegalArgumentException() - } - } - - override fun onLoadFinished( - loader: Loader, - data: Cursor? - ) { - - if (data == null) { - Log.w( - TAG, - "Failed to load data from '${(loader as CursorLoader).uri}'" - ) - - return - } - - when (loader.id) { - LOADER_APP_SYNC -> { - if (data.moveToFirst()) { - appSyncView?.setAppSync(AppSync.fromCursor(data)) - } - } - } - } - - override fun onLoaderReset(loader: Loader) { - // nothing to do... - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - appSettingsViewModel = activity?.run { - ViewModelProvider(this, - fr.geonature.commons.settings.AppSettingsViewModel.Factory { - AppSettingsViewModel( - this.application - ) - }).get(AppSettingsViewModel::class.java) - } - - inputViewModel = activity?.run { - ViewModelProvider(this, - fr.geonature.commons.input.InputViewModel.Factory { InputViewModel(this.application) }).get( - InputViewModel::class.java - ) - } - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - val view = inflater.inflate( - R.layout.fragment_home, - container, - false - ) - - homeContent = view.findViewById(R.id.homeContent) - appSyncView = view.findViewById(R.id.appSyncView) - inputRecyclerView = view.findViewById(R.id.inputRecyclerView) - inputEmptyTextView = view.findViewById(R.id.inputEmptyTextView) - fab = view.findViewById(R.id.fab) - - return view - } - - override fun onViewCreated( - view: View, - savedInstanceState: Bundle? - ) { - super.onViewCreated( - view, - savedInstanceState - ) - - setHasOptionsMenu(true) - - appSyncView?.setListener(object : ListItemActionView.OnListItemActionViewListener { - override fun onAction() { - listener?.onStartSync() - } - }) - - fab?.setOnClickListener { - val appSettings = appSettings ?: return@setOnClickListener - listener?.onStartInput(appSettings) - } - - adapter = InputRecyclerViewAdapter(object : - AbstractListItemRecyclerViewAdapter.OnListItemRecyclerViewAdapterListener { - override fun onClick(item: Input) { - val appSettings = appSettings ?: return - - Log.i( - TAG, - "input selected: ${item.id}" - ) - - listener?.onStartInput( - appSettings, - item - ) - } - - override fun onLongClicked( - position: Int, - item: Input - ) { - inputViewModel?.deleteInput(item) - - context?.run { - @Suppress("DEPRECATION") - ContextCompat.getSystemService( - this, - Vibrator::class.java - )?.vibrate(100) - } - - makeSnackbar(getString(R.string.home_snackbar_input_deleted)) - ?.setAction(R.string.home_snackbar_input_undo) { - inputViewModel?.restoreDeletedInput() - } - ?.show() - } - - override fun showEmptyTextView(show: Boolean) { - if (inputEmptyTextView?.visibility == View.VISIBLE == show) { - return - } - - if (show) { - inputEmptyTextView?.startAnimation( - AnimationUtils.loadAnimation( - context, - android.R.anim.fade_in - ) - ) - inputEmptyTextView?.visibility = View.VISIBLE - } else { - inputEmptyTextView?.startAnimation( - AnimationUtils.loadAnimation( - context, - android.R.anim.fade_out - ) - ) - inputEmptyTextView?.visibility = View.GONE - } - } - }) - - inputRecyclerView?.apply { - layoutManager = LinearLayoutManager(context) - adapter = this@HomeFragment.adapter - } - - val dividerItemDecoration = DividerItemDecoration( - inputRecyclerView?.context, - (inputRecyclerView?.layoutManager as LinearLayoutManager).orientation - ) - inputRecyclerView?.addItemDecoration(dividerItemDecoration) - - if (checkAppSync()) { - checkSelfPermissions() - } - } - - override fun onResume() { - super.onResume() - - LoaderManager.getInstance(this) - .restartLoader( - LOADER_APP_SYNC, - bundleOf(AppSync.COLUMN_ID to requireContext().packageName), - loaderCallbacks - ) - } - - override fun onAttach(context: Context) { - super.onAttach(context) - - if (context is OnHomeFragmentListener) { - listener = context - } else { - throw RuntimeException("$context must implement OnHomeFragmentListener") - } - } - - override fun onDetach() { - super.onDetach() - - listener = null - } - - override fun onCreateOptionsMenu( - menu: Menu, - inflater: MenuInflater - ) { - super.onCreateOptionsMenu( - menu, - inflater - ) - - inflater.inflate( - R.menu.settings, - menu - ) - } - - override fun onPrepareOptionsMenu(menu: Menu) { - super.onPrepareOptionsMenu(menu) - - val menuItemSettings = menu.findItem(R.id.menu_settings) - menuItemSettings.isEnabled = appSettings != null - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { - R.id.menu_settings -> { - listener?.onShowSettings() - true - } - else -> super.onOptionsItemSelected(item) - } - } - - override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, - grantResults: IntArray - ) { - when (requestCode) { - REQUEST_STORAGE_PERMISSIONS -> { - val requestPermissionsResult = checkPermissions(grantResults) - - if (requestPermissionsResult) { - makeSnackbar(getString(R.string.snackbar_permission_external_storage_available))?.show() - loadAppSettings() - } else { - makeSnackbar(getString(R.string.snackbar_permissions_not_granted))?.show() - } - } - else -> super.onRequestPermissionsResult( - requestCode, - permissions, - grantResults - ) - } - } - - private fun checkSelfPermissions() { - val context = context ?: return - - checkSelfPermissions( - context, - object : PermissionUtils.OnCheckSelfPermissionListener { - override fun onPermissionsGranted() { - loadAppSettings() - } - - override fun onRequestPermissions(vararg permissions: String) { - homeContent?.also { - requestPermissions( - this@HomeFragment, - it, - R.string.snackbar_permission_external_storage_rationale, - REQUEST_STORAGE_PERMISSIONS, - *permissions - ) - } - } - }, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) - } - - private fun checkAppSync(): Boolean { - val context = context ?: return true - - if (syncActivity(context) == null) { - fab?.hide() - appSyncView?.enableActionButton(false) - makeSnackbar(getString(R.string.snackbar_app_sync_not_found))?.show() - - return false - } - - appSyncView?.enableActionButton() - - return true - } - - private fun loadAppSettings() { - appSettingsViewModel?.loadAppSettings() - ?.observeOnce(this) { - if (it?.mapSettings == null) { - fab?.hide() - adapter.clear() - activity?.invalidateOptionsMenu() - - makeSnackbar( - getString( - if (it == null) R.string.snackbar_settings_not_found else R.string.snackbar_settings_map_invalid, - appSettingsViewModel?.getAppSettingsFilename() - ) - )?.show() - } else { - appSettings = it - fab?.show() - activity?.invalidateOptionsMenu() - - loadInputs() - } - } - } - - private fun loadInputs() { - inputViewModel?.readInputs() - ?.observe(this, - Observer { - adapter.setItems(it) - }) - } - - private fun makeSnackbar(text: CharSequence): Snackbar? { - val view = homeContent ?: return null - - return Snackbar.make( - view, - text, - Snackbar.LENGTH_LONG - ) - } - - /** - * Callback used by [HomeFragment]. - */ - interface OnHomeFragmentListener { - fun onShowSettings() - fun onStartSync() - fun onStartInput( - appSettings: AppSettings, - input: Input? = null - ) - } - - companion object { - private val TAG = HomeFragment::class.java.name - private const val LOADER_APP_SYNC = 1 - private const val REQUEST_STORAGE_PERMISSIONS = 0 - - /** - * Use this factory method to create a new instance of [HomeFragment]. - * - * @return A new instance of [HomeFragment] - */ - @JvmStatic - fun newInstance() = HomeFragment() - } -} diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/home/InputRecyclerViewAdapter.kt b/occtax/src/main/java/fr/geonature/occtax/ui/home/InputRecyclerViewAdapter.kt index 4769f998..cac08adf 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/home/InputRecyclerViewAdapter.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/home/InputRecyclerViewAdapter.kt @@ -8,7 +8,7 @@ import fr.geonature.occtax.R import fr.geonature.occtax.input.Input /** - * Default RecyclerView Adapter used by [HomeFragment]. + * Default RecyclerView Adapter used by [HomeActivity]. * * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) */ diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt index 28f94521..d8344ae0 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt @@ -7,9 +7,9 @@ import android.util.Log import androidx.lifecycle.ViewModelProvider import androidx.viewpager.widget.ViewPager import fr.geonature.maps.settings.MapSettings -import fr.geonature.maps.util.SettingsUtils.showCompass -import fr.geonature.maps.util.SettingsUtils.showScale -import fr.geonature.maps.util.SettingsUtils.showZoom +import fr.geonature.maps.util.MapSettingsPreferencesUtils.showCompass +import fr.geonature.maps.util.MapSettingsPreferencesUtils.showScale +import fr.geonature.maps.util.MapSettingsPreferencesUtils.showZoom import fr.geonature.occtax.R import fr.geonature.occtax.input.Input import fr.geonature.occtax.input.InputViewModel diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/settings/PreferencesActivity.kt b/occtax/src/main/java/fr/geonature/occtax/ui/settings/PreferencesActivity.kt index 3922e400..445ce51a 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/settings/PreferencesActivity.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/settings/PreferencesActivity.kt @@ -7,6 +7,7 @@ import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity import fr.geonature.occtax.BuildConfig import fr.geonature.occtax.R +import fr.geonature.occtax.settings.AppSettings import java.text.DateFormat import java.util.Date @@ -25,11 +26,13 @@ class PreferencesActivity : AppCompatActivity(), supportActionBar?.setDisplayHomeAsUpEnabled(true) + val appSettings: AppSettings? = intent.getParcelableExtra(EXTRA_APP_SETTINGS) + // Display the fragment as the main content. supportFragmentManager.beginTransaction() .replace( android.R.id.content, - PreferencesFragment.newInstance() + PreferencesFragment.newInstance(appSettings) ) .commit() } @@ -56,8 +59,18 @@ class PreferencesActivity : AppCompatActivity(), companion object { - fun newIntent(context: Context): Intent { - return Intent(context, PreferencesActivity::class.java) + private const val EXTRA_APP_SETTINGS = "extra_app_settings" + + fun newIntent(context: Context, appSettings: AppSettings? = null): Intent { + return Intent( + context, + PreferencesActivity::class.java + ).apply { + putExtra( + EXTRA_APP_SETTINGS, + appSettings + ) + } } } } diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/settings/PreferencesFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/settings/PreferencesFragment.kt index c29bbd18..8e455bc4 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/settings/PreferencesFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/settings/PreferencesFragment.kt @@ -6,6 +6,8 @@ import android.content.Intent import android.database.Cursor import android.os.Bundle import android.widget.ListView +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import androidx.loader.app.LoaderManager import androidx.loader.content.CursorLoader import androidx.loader.content.Loader @@ -15,7 +17,10 @@ import androidx.preference.PreferenceManager import fr.geonature.commons.data.Dataset import fr.geonature.commons.data.InputObserver import fr.geonature.commons.data.helper.Provider.buildUri +import fr.geonature.maps.settings.MapSettings +import fr.geonature.maps.util.MapSettingsPreferencesUtils import fr.geonature.occtax.R +import fr.geonature.occtax.settings.AppSettings import fr.geonature.occtax.ui.dataset.DatasetListActivity import fr.geonature.occtax.ui.observers.InputObserverListActivity import fr.geonature.occtax.util.SettingsUtils.getDefaultDatasetId @@ -29,6 +34,9 @@ import java.util.Locale */ class PreferencesFragment : PreferenceFragmentCompat() { + private lateinit var datasetResultLauncher: ActivityResultLauncher + private lateinit var observerResultLauncher: ActivityResultLauncher + private var listener: OnPreferencesFragmentListener? = null private val loaderCallbacks = object : LoaderManager.LoaderCallbacks { @@ -95,6 +103,31 @@ class PreferencesFragment : PreferenceFragmentCompat() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + datasetResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + if ((it.resultCode != Activity.RESULT_OK) || (it.data == null)) { + return@registerForActivityResult + } + + updateDefaultDatasetPreference( + it.data?.getParcelableExtra( + DatasetListActivity.EXTRA_SELECTED_DATASET + ) + ) + } + observerResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + if ((it.resultCode != Activity.RESULT_OK) || (it.data == null)) { + return@registerForActivityResult + } + + val selectedInputObservers = + it.data?.getParcelableArrayListExtra(InputObserverListActivity.EXTRA_SELECTED_INPUT_OBSERVERS) + ?: ArrayList() + updateDefaultObserverPreference(if (selectedInputObservers.isNotEmpty()) selectedInputObservers[0] else null) + } + + setDefaultPreferences(arguments?.getParcelable(ARG_APP_SETTINGS)) loadDefaultDataset() loadDefaultObserver() @@ -107,7 +140,10 @@ class PreferencesFragment : PreferenceFragmentCompat() { savedInstanceState: Bundle?, rootKey: String? ) { - addPreferencesFromResource(R.xml.preferences) + addPreferencesFromResource(R.xml.preferences_dataset) + addPreferencesFromResource(R.xml.preferences_observers) + addPreferencesFromResource(R.xml.map_preferences) + addPreferencesFromResource(R.xml.preferences_about) } override fun onAttach(context: Context) { @@ -126,28 +162,14 @@ class PreferencesFragment : PreferenceFragmentCompat() { listener = null } - override fun onActivityResult( - requestCode: Int, - resultCode: Int, - data: Intent? - ) { - if ((resultCode != Activity.RESULT_OK) || (data == null)) { - return - } + private fun setDefaultPreferences(appSettings: AppSettings?) { + val context = context ?: return - when (requestCode) { - LOADER_DATASET -> updateDefaultDatasetPreference( - data.getParcelableExtra( - DatasetListActivity.EXTRA_SELECTED_DATASET - ) - ) - LOADER_OBSERVER -> { - val selectedInputObservers = - data.getParcelableArrayListExtra(InputObserverListActivity.EXTRA_SELECTED_INPUT_OBSERVERS) - ?: ArrayList() - updateDefaultObserverPreference(if (selectedInputObservers.isNotEmpty()) selectedInputObservers[0] else null) - } - } + MapSettingsPreferencesUtils.setDefaultPreferences( + context, + MapSettings.Builder.newInstance().from(appSettings?.mapSettings).build(), + preferenceScreen + ) } private fun loadDefaultDataset() { @@ -214,13 +236,13 @@ class PreferencesFragment : PreferenceFragmentCompat() { defaultDatasetPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener { val context = context ?: return@OnPreferenceClickListener false - startActivityForResult( + datasetResultLauncher.launch( DatasetListActivity.newIntent( context, defaultDataset - ), - LOADER_DATASET + ) ) + true } @@ -251,14 +273,14 @@ class PreferencesFragment : PreferenceFragmentCompat() { defaultObserverPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener { val context = context ?: return@OnPreferenceClickListener false - startActivityForResult( + observerResultLauncher.launch( InputObserverListActivity.newIntent( context, ListView.CHOICE_MODE_SINGLE, if (defaultObserver == null) listOf() else listOf(defaultObserver) - ), - LOADER_OBSERVER + ) ) + true } @@ -291,6 +313,7 @@ class PreferencesFragment : PreferenceFragmentCompat() { companion object { + private const val ARG_APP_SETTINGS = "arg_app_settings" private const val LOADER_DATASET = 1 private const val LOADER_OBSERVER = 2 private const val KEY_SELECTED_DATASET = "selected_dataset" @@ -302,8 +325,13 @@ class PreferencesFragment : PreferenceFragmentCompat() { * @return A new instance of [PreferencesFragment] */ @JvmStatic - fun newInstance() = PreferencesFragment().apply { - arguments = Bundle() + fun newInstance(appSettings: AppSettings? = null) = PreferencesFragment().apply { + arguments = Bundle().apply { + putParcelable( + ARG_APP_SETTINGS, + appSettings + ) + } } } } diff --git a/occtax/src/main/res/layout/fragment_home.xml b/occtax/src/main/res/layout/activity_home.xml similarity index 97% rename from occtax/src/main/res/layout/fragment_home.xml rename to occtax/src/main/res/layout/activity_home.xml index 5104c7d9..2b1d10cc 100644 --- a/occtax/src/main/res/layout/fragment_home.xml +++ b/occtax/src/main/res/layout/activity_home.xml @@ -5,7 +5,8 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/homeContent" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + tools:context=".ui.home.HomeActivity"> Observateurs Observateur par défaut Non défini - Pointage A propos Version de l\'application diff --git a/occtax/src/main/res/values/prefs.xml b/occtax/src/main/res/values/prefs.xml index 601d0dc9..9353156f 100644 --- a/occtax/src/main/res/values/prefs.xml +++ b/occtax/src/main/res/values/prefs.xml @@ -9,7 +9,6 @@ observer_default Default observer Not defined - Map About app_version App version diff --git a/occtax/src/main/res/xml/preferences.xml b/occtax/src/main/res/xml/preferences.xml deleted file mode 100644 index 560e696a..00000000 --- a/occtax/src/main/res/xml/preferences.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/occtax/src/main/res/xml/preferences_about.xml b/occtax/src/main/res/xml/preferences_about.xml new file mode 100644 index 00000000..b7c8fa3d --- /dev/null +++ b/occtax/src/main/res/xml/preferences_about.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/occtax/src/main/res/xml/preferences_dataset.xml b/occtax/src/main/res/xml/preferences_dataset.xml new file mode 100644 index 00000000..9cdf395f --- /dev/null +++ b/occtax/src/main/res/xml/preferences_dataset.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/occtax/src/main/res/xml/preferences_observers.xml b/occtax/src/main/res/xml/preferences_observers.xml new file mode 100644 index 00000000..75234413 --- /dev/null +++ b/occtax/src/main/res/xml/preferences_observers.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file From bd05c2ff86455fc36ca0d6d0903fd1b79f704aa2 Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Sat, 6 Feb 2021 14:53:05 +0100 Subject: [PATCH 2/5] fix: #80 --- .../ObserversAndDateInputFragment.kt | 139 +++++++++++------- 1 file changed, 83 insertions(+), 56 deletions(-) diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/observers/ObserversAndDateInputFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/observers/ObserversAndDateInputFragment.kt index 769650f3..e444fa45 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/observers/ObserversAndDateInputFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/observers/ObserversAndDateInputFragment.kt @@ -12,6 +12,8 @@ import android.view.View import android.view.ViewGroup import android.widget.ListView import android.widget.Toast +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.loader.app.LoaderManager @@ -51,6 +53,9 @@ class ObserversAndDateInputFragment : Fragment(), IValidateFragment, IInputFragment { + private lateinit var observersResultLauncher: ActivityResultLauncher + private lateinit var datasetResultLauncher: ActivityResultLauncher + private var input: Input? = null private val selectedInputObservers: MutableList = mutableListOf() private var selectedDataset: Dataset? = null @@ -145,6 +150,9 @@ class ObserversAndDateInputFragment : Fragment(), } updateSelectedObserversActionView(selectedInputObservers) + + LoaderManager.getInstance(this@ObserversAndDateInputFragment) + .destroyLoader(LOADER_OBSERVERS_IDS) } LOADER_DATASET_ID -> { if (data.count == 0) { @@ -158,6 +166,9 @@ class ObserversAndDateInputFragment : Fragment(), } updateSelectedDatasetActionView(selectedDataset) + + LoaderManager.getInstance(this@ObserversAndDateInputFragment) + .destroyLoader(LOADER_DATASET_ID) } LOADER_DEFAULT_NOMENCLATURE_VALUES -> { data.moveToFirst() @@ -188,6 +199,9 @@ class ObserversAndDateInputFragment : Fragment(), data.moveToNext() } + LoaderManager.getInstance(this@ObserversAndDateInputFragment) + .destroyLoader(LOADER_DEFAULT_NOMENCLATURE_VALUES) + (activity as AbstractPagerFragmentActivity?)?.validateCurrentPage() if (input?.properties?.isNotEmpty() == false) { @@ -232,6 +246,31 @@ class ObserversAndDateInputFragment : Fragment(), override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + observersResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + if ((it.resultCode != Activity.RESULT_OK) || (it.data == null)) { + return@registerForActivityResult + } + + updateSelectedObservers( + it.data?.getParcelableArrayListExtra( + InputObserverListActivity.EXTRA_SELECTED_INPUT_OBSERVERS + ) ?: ArrayList() + ) + } + datasetResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + if ((it.resultCode != Activity.RESULT_OK) || (it.data == null)) { + return@registerForActivityResult + } + + updateSelectedDataset( + it.data?.getParcelableExtra( + DatasetListActivity.EXTRA_SELECTED_DATASET + ) + ) + } + val supportFragmentManager = activity?.supportFragmentManager ?: return val dialogFragment = @@ -257,13 +296,12 @@ class ObserversAndDateInputFragment : Fragment(), override fun onAction() { val context = context ?: return - startActivityForResult( + observersResultLauncher.launch( InputObserverListActivity.newIntent( context, ListView.CHOICE_MODE_MULTIPLE, selectedInputObservers - ), - LOADER_OBSERVERS_IDS + ) ) } }) @@ -274,12 +312,11 @@ class ObserversAndDateInputFragment : Fragment(), override fun onAction() { val context = context ?: return - startActivityForResult( + datasetResultLauncher.launch( DatasetListActivity.newIntent( context, selectedDataset - ), - LOADER_DATASET_ID + ) ) } }) @@ -300,54 +337,6 @@ class ObserversAndDateInputFragment : Fragment(), return view } - override fun onActivityResult( - requestCode: Int, - resultCode: Int, - data: Intent? - ) { - if ((resultCode != Activity.RESULT_OK) || (data == null)) { - return - } - - when (requestCode) { - LOADER_OBSERVERS_IDS -> { - selectedInputObservers.clear() - selectedInputObservers.addAll( - data.getParcelableArrayListExtra( - InputObserverListActivity.EXTRA_SELECTED_INPUT_OBSERVERS - ) ?: ArrayList() - ) - - input?.also { - it.clearAllInputObservers() - - if (selectedInputObservers.isEmpty()) { - val context = context ?: return - getDefaultObserverId(context).also { defaultObserverId -> - if (defaultObserverId != null) it.setPrimaryInputObserverId( - defaultObserverId - ) - } - } - - it.setAllInputObservers(selectedInputObservers) - } - - updateSelectedObserversActionView(selectedInputObservers) - } - LOADER_DATASET_ID -> { - selectedDataset = - data.getParcelableExtra(DatasetListActivity.EXTRA_SELECTED_DATASET) - - input?.also { - it.datasetId = selectedDataset?.id - } - - updateSelectedDatasetActionView(selectedDataset) - } - } - } - override fun getResourceTitle(): Int { return R.string.pager_fragment_observers_and_date_input_title } @@ -373,7 +362,7 @@ class ObserversAndDateInputFragment : Fragment(), if (selectedInputObserverIds.isNotEmpty()) { LoaderManager.getInstance(this) - .restartLoader( + .initLoader( LOADER_OBSERVERS_IDS, bundleOf( kotlin.Pair( @@ -391,7 +380,7 @@ class ObserversAndDateInputFragment : Fragment(), if (selectedDatasetId != null) { LoaderManager.getInstance(this) - .restartLoader( + .initLoader( LOADER_DATASET_ID, bundleOf( kotlin.Pair( @@ -439,6 +428,44 @@ class ObserversAndDateInputFragment : Fragment(), this.input = input as Input } + private fun updateSelectedObservers(selectedInputObservers: List) { + this.selectedInputObservers.clear() + this.selectedInputObservers.addAll( + selectedInputObservers + ) + + input?.also { + it.clearAllInputObservers() + + if (selectedInputObservers.isEmpty()) { + val context = context ?: return + getDefaultObserverId(context).also { defaultObserverId -> + if (defaultObserverId != null) it.setPrimaryInputObserverId( + defaultObserverId + ) + } + } + + it.setAllInputObservers(selectedInputObservers) + } + + (activity as AbstractPagerFragmentActivity?)?.validateCurrentPage() + + updateSelectedObserversActionView(selectedInputObservers) + } + + private fun updateSelectedDataset(selectedDataset: Dataset?) { + this.selectedDataset = selectedDataset + + input?.also { + it.datasetId = selectedDataset?.id + } + + (activity as AbstractPagerFragmentActivity?)?.validateCurrentPage() + + updateSelectedDatasetActionView(selectedDataset) + } + private fun updateSelectedObserversActionView(selectedInputObservers: List) { selectedInputObserversActionView?.setTitle( resources.getQuantityString( From 4a0ec65fb88ed39714114c5814c4cb2e3af76917 Mon Sep 17 00:00:00 2001 From: Camille Monchicourt Date: Sat, 6 Feb 2021 20:00:31 +0100 Subject: [PATCH 3/5] Doc install - Precision occtaxmobile_area_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nouveau paramètre ajouté dans GeoNature 2.6.0 --- docs/installation-fr.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/installation-fr.md b/docs/installation-fr.md index 2a5c8537..2dd6e09b 100644 --- a/docs/installation-fr.md +++ b/docs/installation-fr.md @@ -139,8 +139,11 @@ Pour l'affichage et l'utilisation des unités géographiques permettant d'affich la date de dernière observation dans l'unité, il est nécessaire de charger une couche vectorielle des polygones des unités géographiques en respectant quelques règles. +Le code du type de zonage utilisé doit être renseigné dans le paramètre `code_area_type` de gn_mobile_core. Ce même code +doit aussi être renseigné dans le paramètre `occtaxmobile_area_type`de la table `gn_commons.t_parameters`de GeoNature. + Par défaut, si aucune couche vectorielle n'est configurée, l'application va simplement charger la base des taxons sans -les données additionnelles venant des unités géographiques. +les informations additionnelles venant des unités géographiques. - Exemple de fichier WKT : https://github.com/PnX-SI/gn_mobile_maps/blob/develop/maps/src/test/resources/fixtures/features.wkt - Exemple de configuration : https://github.com/PnX-SI/gn_mobile_maps/blob/develop/maps/src/test/resources/fixtures/map_settings.json From 17415a029130c23d7e349d61c1436c2db7582a01 Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Sun, 7 Feb 2021 15:40:25 +0100 Subject: [PATCH 4/5] fix: linter issues... --- .../ui/input/counting/CountingFragment.kt | 163 ++++++++---------- .../counting/EditCountingMetadataFragment.kt | 2 +- .../NomenclatureTypesRecyclerViewAdapter.kt | 6 +- .../input/informations/InformationFragment.kt | 2 +- .../NomenclatureTypesRecyclerViewAdapter.kt | 4 +- .../occtax/ui/input/taxa/TaxaFragment.kt | 45 +++-- .../ui/shared/view/ListItemActionView.kt | 4 +- 7 files changed, 103 insertions(+), 123 deletions(-) diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt index 0efce2e0..c05b5467 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt @@ -9,6 +9,8 @@ import android.view.View import android.view.ViewGroup import android.view.animation.AnimationUtils import android.widget.Toast +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import androidx.core.content.ContextCompat.getSystemService import androidx.fragment.app.Fragment import androidx.recyclerview.widget.DividerItemDecoration @@ -37,9 +39,24 @@ class CountingFragment : Fragment(), IValidateFragment, IInputFragment { + private lateinit var editCountingResultLauncher: ActivityResultLauncher + private var input: Input? = null private var adapter: CountingRecyclerViewAdapter? = null + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + editCountingResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + if ((it.resultCode != Activity.RESULT_OK) || (it.data == null)) { + return@registerForActivityResult + } + + updateCountingMetadata(it.data?.getParcelableExtra(EditCountingMetadataActivity.EXTRA_COUNTING_METADATA)) + } + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -64,44 +81,13 @@ class CountingFragment : Fragment(), empty.text = getString(R.string.counting_no_data) fab.setOnClickListener { - val context = context ?: return@setOnClickListener - - startActivityForResult( - EditCountingMetadataActivity.newIntent( - context, - input?.getCurrentSelectedInputTaxon()?.taxon?.taxonomy - ?: Taxonomy( - Taxonomy.ANY, - Taxonomy.ANY - ), - null, - *(arguments?.getParcelableArray(ARG_PROPERTIES) - ?.map { it as PropertySettings } - ?.toTypedArray() ?: emptyArray()) - ), - 0 - ) + launchEditCountingMetadataActivity() } adapter = CountingRecyclerViewAdapter(object : AbstractListItemRecyclerViewAdapter.OnListItemRecyclerViewAdapterListener { override fun onClick(item: CountingMetadata) { - val context = context ?: return - startActivityForResult( - EditCountingMetadataActivity.newIntent( - context, - input?.getCurrentSelectedInputTaxon()?.taxon?.taxonomy - ?: Taxonomy( - Taxonomy.ANY, - Taxonomy.ANY - ), - item, - *(arguments?.getParcelableArray(ARG_PROPERTIES) - ?.map { it as PropertySettings } - ?.toTypedArray() ?: emptyArray()) - ), - 0 - ) + launchEditCountingMetadataActivity(item) } override fun onLongClicked( @@ -176,51 +162,6 @@ class CountingFragment : Fragment(), } } - override fun onActivityResult( - requestCode: Int, - resultCode: Int, - data: Intent? - ) { - if ((resultCode == Activity.RESULT_OK) && (data != null)) { - val countingMetadata = - data.getParcelableExtra(EditCountingMetadataActivity.EXTRA_COUNTING_METADATA) - - if (countingMetadata == null) { - Toast.makeText( - context, - R.string.counting_toast_empty, - Toast.LENGTH_LONG - ) - .show() - - return - } - - if (countingMetadata.isEmpty()) { - (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.deleteCountingMetadata( - countingMetadata.index - ) - Toast.makeText( - context, - R.string.counting_toast_empty, - Toast.LENGTH_LONG - ) - .show() - - return - } - - (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.addCountingMetadata( - countingMetadata - ) - - val counting = (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.getCounting() - ?: emptyList() - - adapter?.setItems(counting) - } - } - override fun getResourceTitle(): Int { return R.string.pager_fragment_counting_title } @@ -249,18 +190,7 @@ class CountingFragment : Fragment(), adapter?.setItems(counting) if (counting.isEmpty()) { - val context = context ?: return - startActivityForResult( - EditCountingMetadataActivity.newIntent( - context, - input?.getCurrentSelectedInputTaxon()?.taxon?.taxonomy - ?: Taxonomy( - Taxonomy.ANY, - Taxonomy.ANY - ) - ), - 0 - ) + launchEditCountingMetadataActivity() } } @@ -268,6 +198,59 @@ class CountingFragment : Fragment(), this.input = input as Input } + private fun launchEditCountingMetadataActivity(countingMetadata: CountingMetadata? = null) { + val context = context ?: return + + editCountingResultLauncher.launch(EditCountingMetadataActivity.newIntent( + context, + input?.getCurrentSelectedInputTaxon()?.taxon?.taxonomy + ?: Taxonomy( + Taxonomy.ANY, + Taxonomy.ANY + ), + countingMetadata, + *(arguments?.getParcelableArray(ARG_PROPERTIES) + ?.map { it as PropertySettings } + ?.toTypedArray() ?: emptyArray()) + )) + } + + private fun updateCountingMetadata(countingMetadata: CountingMetadata?) { + if (countingMetadata == null) { + Toast.makeText( + context, + R.string.counting_toast_empty, + Toast.LENGTH_LONG + ) + .show() + + return + } + + if (countingMetadata.isEmpty()) { + (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.deleteCountingMetadata( + countingMetadata.index + ) + Toast.makeText( + context, + R.string.counting_toast_empty, + Toast.LENGTH_LONG + ) + .show() + + return + } + + (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.addCountingMetadata( + countingMetadata + ) + + val counting = (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.getCounting() + ?: emptyList() + + adapter?.setItems(counting) + } + companion object { private const val ARG_PROPERTIES = "arg_properties" diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataFragment.kt index 504ffd9c..68b20ed7 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataFragment.kt @@ -158,7 +158,7 @@ class EditCountingMetadataFragment : Fragment(), inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { + ): View { val recyclerView = inflater.inflate( R.layout.recycler_view, container, diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/NomenclatureTypesRecyclerViewAdapter.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/NomenclatureTypesRecyclerViewAdapter.kt index e7407eb6..9096bdd3 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/NomenclatureTypesRecyclerViewAdapter.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/NomenclatureTypesRecyclerViewAdapter.kt @@ -103,11 +103,11 @@ class NomenclatureTypesRecyclerViewAdapter(private val listener: OnNomenclatureT // add default mnemonic filters availableNomenclatureTypes.addAll(mnemonicFilter.filter { it.second != NomenclatureTypeViewType.NOMENCLATURE_TYPE && - (defaultPropertySettings.isEmpty() || defaultPropertySettings.any { p -> p.key == it.first }) + (defaultPropertySettings.isEmpty() || defaultPropertySettings.any { p -> p.key == it.first }) }) } - availableNomenclatureTypes.sortWith(Comparator { o1, o2 -> + availableNomenclatureTypes.sortWith { o1, o2 -> val i1 = mnemonicFilter.indexOfFirst { it.first == o1.first } val i2 = mnemonicFilter.indexOfFirst { it.first == o2.first } @@ -116,7 +116,7 @@ class NomenclatureTypesRecyclerViewAdapter(private val listener: OnNomenclatureT i2 == -1 -> -1 else -> i1 - i2 } - }) + } setNomenclatureTypes(availableNomenclatureTypes) } diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/InformationFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/InformationFragment.kt index d92c896e..b2c0cbf4 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/InformationFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/InformationFragment.kt @@ -136,7 +136,7 @@ class InformationFragment : Fragment(), inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { + ): View { val recyclerView = inflater.inflate( R.layout.recycler_view, container, diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/NomenclatureTypesRecyclerViewAdapter.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/NomenclatureTypesRecyclerViewAdapter.kt index 2be08e13..4853e632 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/NomenclatureTypesRecyclerViewAdapter.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/NomenclatureTypesRecyclerViewAdapter.kt @@ -120,7 +120,7 @@ class NomenclatureTypesRecyclerViewAdapter(private val listener: OnNomenclatureT }) } - availableNomenclatureTypes.sortWith(Comparator { o1, o2 -> + availableNomenclatureTypes.sortWith { o1, o2 -> val i1 = mnemonicFilter.indexOfFirst { it.first == o1.first } val i2 = mnemonicFilter.indexOfFirst { it.first == o2.first } @@ -129,7 +129,7 @@ class NomenclatureTypesRecyclerViewAdapter(private val listener: OnNomenclatureT i2 == -1 -> -1 else -> i1 - i2 } - }) + } val nomenclatureTypes = if (showAllNomenclatureTypes) { availableNomenclatureTypes diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaFragment.kt index ac41d0f1..79e0283c 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaFragment.kt @@ -14,6 +14,8 @@ import android.view.View import android.view.ViewGroup import android.view.animation.AnimationUtils import android.widget.ProgressBar +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.widget.SearchView import androidx.core.view.get import androidx.fragment.app.Fragment @@ -50,9 +52,11 @@ class TaxaFragment : Fragment(), IValidateFragment, IInputFragment { + private lateinit var savedState: Bundle + private lateinit var taxaFilterResultLauncher: ActivityResultLauncher + private var input: Input? = null private var adapter: TaxaRecyclerViewAdapter? = null - private lateinit var savedState: Bundle private var progressBar: ProgressBar? = null private var emptyTextView: View? = null private var filterChipGroup: ChipGroup? = null @@ -187,6 +191,18 @@ class TaxaFragment : Fragment(), super.onCreate(savedInstanceState) savedState = savedInstanceState ?: Bundle() + + taxaFilterResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult -> + if ((activityResult.resultCode != Activity.RESULT_OK) || (activityResult.data == null)) { + return@registerForActivityResult + } + + val selectedFilters = + activityResult.data?.getParcelableArrayExtra(TaxaFilterActivity.EXTRA_SELECTED_FILTERS) + ?.map { it as Filter<*> }?.toTypedArray() ?: emptyArray() + applyFilters(*selectedFilters) + } } override fun onCreateView( @@ -291,25 +307,6 @@ class TaxaFragment : Fragment(), super.onSaveInstanceState(savedState.apply { putAll(outState) }) } - override fun onActivityResult( - requestCode: Int, - resultCode: Int, - data: Intent? - ) { - if ((resultCode != Activity.RESULT_OK) || (data == null)) { - return - } - - when (requestCode) { - RESULT_FILTER -> { - val selectedFilters = - data.getParcelableArrayExtra(TaxaFilterActivity.EXTRA_SELECTED_FILTERS) - ?.map { it as Filter<*> }?.toTypedArray() ?: emptyArray() - applyFilters(*selectedFilters) - } - } - } - override fun onCreateOptionsMenu( menu: Menu, inflater: MenuInflater @@ -354,7 +351,8 @@ class TaxaFragment : Fragment(), return when (item.itemId) { R.id.menu_filter -> { val context = context ?: return true - startActivityForResult( + + taxaFilterResultLauncher.launch( TaxaFilterActivity.newIntent( context, !savedState.getString(KEY_SELECTED_FEATURE_ID).isNullOrEmpty(), @@ -363,9 +361,9 @@ class TaxaFragment : Fragment(), AppSettings.DEFAULT_AREA_OBSERVATION_DURATION ) ?: AppSettings.DEFAULT_AREA_OBSERVATION_DURATION, *getSelectedFilters().toTypedArray() - ), - RESULT_FILTER + ) ) + true } else -> super.onOptionsItemSelected(item) @@ -621,7 +619,6 @@ class TaxaFragment : Fragment(), private const val ARG_AREA_OBSERVATION_DURATION = "arg_area_observation_duration" private const val LOADER_TAXA = 1 private const val LOADER_TAXON = 2 - private const val RESULT_FILTER = 3 private const val KEY_FILTER_BY_NAME = "key_filter_by_name" private const val KEY_SELECTED_FILTERS = "key_selected_filters" private const val KEY_SELECTED_FEATURE_ID = "key_selected_feature_id" diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/shared/view/ListItemActionView.kt b/occtax/src/main/java/fr/geonature/occtax/ui/shared/view/ListItemActionView.kt index 491462e2..a797bea8 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/shared/view/ListItemActionView.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/shared/view/ListItemActionView.kt @@ -275,7 +275,7 @@ open class ListItemActionView : ConstraintLayout { private inner class EditListItemViewRecyclerViewAdapter : RecyclerView.Adapter() { - internal val items: MutableList> = ArrayList() + val items: MutableList> = ArrayList() override fun onCreateViewHolder( parent: ViewGroup, @@ -302,7 +302,7 @@ open class ListItemActionView : ConstraintLayout { notifyDataSetChanged() } - internal inner class ViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder( + inner class ViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder( LayoutInflater.from(parent.context) .inflate( R.layout.list_item_2, From 21bcd38014ed575c29d72a933c8673703ec2333e Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Sun, 7 Feb 2021 16:25:42 +0100 Subject: [PATCH 5/5] chore: 1.2.0 release --- gn_mobile_core | 2 +- occtax/build.gradle | 7 +- .../fr/geonature/occtax/input/InputTaxon.kt | 2 +- .../ui/input/counting/CountingFragment.kt | 65 ++++++----- .../input/summary/InputTaxaSummaryFragment.kt | 104 ++++++++++-------- occtax/version.properties | 4 +- 6 files changed, 104 insertions(+), 80 deletions(-) diff --git a/gn_mobile_core b/gn_mobile_core index dda0fabe..d802d54d 160000 --- a/gn_mobile_core +++ b/gn_mobile_core @@ -1 +1 @@ -Subproject commit dda0fabe35eb70fb7f3a127abded7848b39fd29f +Subproject commit d802d54d226a749c74b14bcfc3332b331f78cb86 diff --git a/occtax/build.gradle b/occtax/build.gradle index e2fdc298..c3e53289 100644 --- a/occtax/build.gradle +++ b/occtax/build.gradle @@ -1,8 +1,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' -version = "1.1.4" +version = "1.2.0" android { compileSdkVersion 29 @@ -66,7 +65,7 @@ dependencies { implementation project(':viewpager') implementation project(':maps') - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.4' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0' @@ -76,7 +75,7 @@ dependencies { implementation 'com.google.android.material:material:1.1.0' implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha03' implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.preference:preference:1.1.1' + implementation 'androidx.preference:preference-ktx:1.1.1' implementation 'com.l4digital.fastscroll:fastscroll:2.0.1' testImplementation 'junit:junit:4.13' diff --git a/occtax/src/main/java/fr/geonature/occtax/input/InputTaxon.kt b/occtax/src/main/java/fr/geonature/occtax/input/InputTaxon.kt index c2f08bca..64b9ee8a 100644 --- a/occtax/src/main/java/fr/geonature/occtax/input/InputTaxon.kt +++ b/occtax/src/main/java/fr/geonature/occtax/input/InputTaxon.kt @@ -85,7 +85,7 @@ class InputTaxon : AbstractInputTaxon { if (countingMetadata.isEmpty()) return val index = if (countingMetadata.index > 0) countingMetadata.index - else this.counting.keys.max()?.plus(1) ?: 1 + else this.counting.keys.maxOrNull()?.plus(1) ?: 1 counting[index] = countingMetadata.apply { this.index = index } } diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt index c05b5467..8aa104af 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt @@ -8,14 +8,17 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.view.animation.AnimationUtils +import android.widget.TextView import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts +import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat.getSystemService import androidx.fragment.app.Fragment import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.snackbar.Snackbar import fr.geonature.commons.data.Taxonomy import fr.geonature.commons.input.AbstractInput @@ -28,7 +31,6 @@ import fr.geonature.occtax.settings.PropertySettings import fr.geonature.occtax.ui.input.IInputFragment import fr.geonature.viewpager.ui.AbstractPagerFragmentActivity import fr.geonature.viewpager.ui.IValidateFragment -import kotlinx.android.synthetic.main.fragment_recycler_view_fab.* /** * [Fragment] to let the user to add additional counting information for the given [Input]. @@ -43,6 +45,10 @@ class CountingFragment : Fragment(), private var input: Input? = null private var adapter: CountingRecyclerViewAdapter? = null + private var contentView: CoordinatorLayout? = null + private var recyclerView: RecyclerView? = null + private var emptyTextView: TextView? = null + private var fab: FloatingActionButton? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -78,9 +84,14 @@ class CountingFragment : Fragment(), savedInstanceState ) - empty.text = getString(R.string.counting_no_data) + contentView = view.findViewById(android.R.id.content) + recyclerView = view.findViewById(android.R.id.list) - fab.setOnClickListener { + emptyTextView = view.findViewById(android.R.id.empty) + emptyTextView?.text = getString(R.string.counting_no_data) + + fab = view.findViewById(R.id.fab) + fab?.setOnClickListener { launchEditCountingMetadataActivity() } @@ -106,51 +117,53 @@ class CountingFragment : Fragment(), )?.vibrate(100) } - Snackbar.make( - content, - R.string.counting_snackbar_counting_deleted, - Snackbar.LENGTH_LONG - ) - .setAction( - R.string.counting_snackbar_counting_undo - ) { - adapter?.add( - item, - position - ) - (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.addCountingMetadata( - item - ) - } - .show() + contentView?.also { + Snackbar.make( + it, + R.string.counting_snackbar_counting_deleted, + Snackbar.LENGTH_LONG + ) + .setAction( + R.string.counting_snackbar_counting_undo + ) { + adapter?.add( + item, + position + ) + (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.addCountingMetadata( + item + ) + } + .show() + } } override fun showEmptyTextView(show: Boolean) { - if (empty.visibility == View.VISIBLE == show) { + if (emptyTextView?.visibility == View.VISIBLE == show) { return } if (show) { - empty.startAnimation( + emptyTextView?.startAnimation( AnimationUtils.loadAnimation( context, android.R.anim.fade_in ) ) - empty.visibility = View.VISIBLE + emptyTextView?.visibility = View.VISIBLE } else { - empty.startAnimation( + emptyTextView?.startAnimation( AnimationUtils.loadAnimation( context, android.R.anim.fade_out ) ) - empty.visibility = View.GONE + emptyTextView?.visibility = View.GONE } } }) - with(list as RecyclerView) { + with(recyclerView as RecyclerView) { layoutManager = LinearLayoutManager(context) adapter = this@CountingFragment.adapter diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryFragment.kt index cd80ac9d..ceac01a2 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryFragment.kt @@ -10,12 +10,15 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.view.animation.AnimationUtils +import android.widget.TextView import android.widget.Toast +import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat.getSystemService import androidx.fragment.app.Fragment import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.Snackbar import fr.geonature.commons.input.AbstractInput @@ -27,7 +30,6 @@ import fr.geonature.occtax.ui.input.IInputFragment import fr.geonature.occtax.ui.shared.dialog.CommentDialogFragment import fr.geonature.viewpager.ui.AbstractPagerFragmentActivity import fr.geonature.viewpager.ui.IValidateFragment -import kotlinx.android.synthetic.main.fragment_recycler_view_fab.* /** * Summary of all edited taxa. @@ -40,6 +42,10 @@ class InputTaxaSummaryFragment : Fragment(), private var input: Input? = null private var adapter: InputTaxaSummaryRecyclerViewAdapter? = null + private var contentView: CoordinatorLayout? = null + private var recyclerView: RecyclerView? = null + private var emptyTextView: TextView? = null + private var fab: FloatingActionButton? = null private val onCommentDialogFragmentListener = object : CommentDialogFragment.OnCommentDialogFragmentListener { @@ -83,9 +89,13 @@ class InputTaxaSummaryFragment : Fragment(), // we have a menu item to show in action bar setHasOptionsMenu(true) - empty.text = getString(R.string.summary_no_data) + contentView = view.findViewById(android.R.id.content) + recyclerView = view.findViewById(android.R.id.list) - fab.setOnClickListener { + emptyTextView = view.findViewById(android.R.id.empty) + emptyTextView?.text = getString(R.string.summary_no_data) + + fab?.setOnClickListener { ((activity as AbstractPagerFragmentActivity?))?.also { input?.clearCurrentSelectedInputTaxon() it.goToPreviousPage() @@ -116,79 +126,81 @@ class InputTaxaSummaryFragment : Fragment(), )?.vibrate(100) } - Snackbar.make( - content, - R.string.summary_snackbar_input_taxon_deleted, - Snackbar.LENGTH_LONG - ) - .setAction( - R.string.summary_snackbar_input_taxon_undo - ) { - adapter?.add( - item, - position - ) - input?.addInputTaxon(item) - } - .addCallback(object : BaseTransientBottomBar.BaseCallback() { - override fun onDismissed( - transientBottomBar: Snackbar?, - event: Int + contentView?.also { + Snackbar.make( + it, + R.string.summary_snackbar_input_taxon_deleted, + Snackbar.LENGTH_LONG + ) + .setAction( + R.string.summary_snackbar_input_taxon_undo ) { - super.onDismissed( - transientBottomBar, - event + adapter?.add( + item, + position ) + input?.addInputTaxon(item) + } + .addCallback(object : BaseTransientBottomBar.BaseCallback() { + override fun onDismissed( + transientBottomBar: Snackbar?, + event: Int + ) { + super.onDismissed( + transientBottomBar, + event + ) - (activity as AbstractPagerFragmentActivity?)?.validateCurrentPage() + (activity as AbstractPagerFragmentActivity?)?.validateCurrentPage() - // check if this step is still valid and apply automatic redirection if any - if (!this@InputTaxaSummaryFragment.validate()) { - val context = context ?: return + // check if this step is still valid and apply automatic redirection if any + if (!this@InputTaxaSummaryFragment.validate()) { + val context = context ?: return - Toast.makeText( - context, - R.string.summary_toast_no_input_taxon, - Toast.LENGTH_LONG - ) - .show() + Toast.makeText( + context, + R.string.summary_toast_no_input_taxon, + Toast.LENGTH_LONG + ) + .show() - ((activity as AbstractPagerFragmentActivity?))?.also { - it.goToPreviousPage() - it.goToNextPage() + ((activity as AbstractPagerFragmentActivity?))?.also { activity -> + activity.goToPreviousPage() + activity.goToNextPage() + } } } - } - }) - .show() + }) + .show() + } } override fun showEmptyTextView(show: Boolean) { - if (empty.visibility == View.VISIBLE == show) { + if (emptyTextView?.visibility == View.VISIBLE == show) { return } if (show) { - empty.startAnimation( + emptyTextView?.startAnimation( AnimationUtils.loadAnimation( context, android.R.anim.fade_in ) ) - empty.visibility = View.VISIBLE + emptyTextView?.visibility = View.VISIBLE } else { - empty.startAnimation( + emptyTextView?.startAnimation( AnimationUtils.loadAnimation( context, android.R.anim.fade_out ) ) - empty.visibility = View.GONE + emptyTextView?.visibility = View.GONE } } }) - with(list as RecyclerView) { + with(recyclerView as RecyclerView) { layoutManager = LinearLayoutManager(context) adapter = this@InputTaxaSummaryFragment.adapter diff --git a/occtax/version.properties b/occtax/version.properties index 1cafe60e..99cc7d24 100644 --- a/occtax/version.properties +++ b/occtax/version.properties @@ -1,2 +1,2 @@ -#Sat Oct 10 15:35:58 CEST 2020 -VERSION_CODE=2035 +#Sun Feb 07 16:17:34 CET 2021 +VERSION_CODE=2070