Skip to content

Commit 24239f7

Browse files
committed
Show dialog for Retry/Select root storage path again in case of load crash
1 parent 5e54af1 commit 24239f7

File tree

11 files changed

+98
-39
lines changed

11 files changed

+98
-39
lines changed

app/src/main/java/dev/arkbuilders/arkmemo/di/RepositoryModule.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import dev.arkbuilders.arklib.user.properties.PropertiesStorageRepo
99
import dev.arkbuilders.arkmemo.models.GraphicNote
1010
import dev.arkbuilders.arkmemo.models.TextNote
1111
import dev.arkbuilders.arkmemo.models.VoiceNote
12-
import dev.arkbuilders.arkmemo.preferences.MemoPreferences
1312
import dev.arkbuilders.arkmemo.repo.NotesRepo
1413
import dev.arkbuilders.arkmemo.repo.NotesRepoHelper
1514
import dev.arkbuilders.arkmemo.repo.graphics.GraphicNotesRepo
@@ -38,8 +37,7 @@ object RepoHelperModule {
3837
@Singleton
3938
@Provides
4039
fun provideNotesRepoHelper(
41-
memoPreferences: MemoPreferences,
4240
propertiesStorageRepo: PropertiesStorageRepo,
4341
@Named(IO_DISPATCHER) coroutineDispatcher: CoroutineDispatcher,
44-
) = NotesRepoHelper(memoPreferences, propertiesStorageRepo, coroutineDispatcher)
42+
) = NotesRepoHelper(propertiesStorageRepo, coroutineDispatcher)
4543
}

app/src/main/java/dev/arkbuilders/arkmemo/preferences/MemoPreferences.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@ interface MemoPreferences {
1414
fun getCrashReportEnabled(): Boolean
1515

1616
fun storageNotAvailable(): Boolean
17+
18+
fun isLastLaunchSuccess(): Boolean
19+
20+
fun setLastLaunchSuccess(success: Boolean)
1721
}

app/src/main/java/dev/arkbuilders/arkmemo/preferences/MemoPreferencesImpl.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import kotlin.io.path.exists
1111

1212
private const val NAME = "memo_prefs"
1313
private const val CURRENT_NOTES_PATH = "current_notes_path"
14+
private const val PREF_LAST_LAUNCH_SUCCESS = "pref_last_launch_success"
1415

1516
class MemoPreferencesImpl
1617
@Inject
@@ -38,4 +39,12 @@ class MemoPreferencesImpl
3839
override fun storageNotAvailable(): Boolean {
3940
return getPath().isEmpty() || !getNotesStorage().exists()
4041
}
42+
43+
override fun isLastLaunchSuccess(): Boolean {
44+
return sharedPreferences.getBoolean(PREF_LAST_LAUNCH_SUCCESS, true)
45+
}
46+
47+
override fun setLastLaunchSuccess(success: Boolean) {
48+
prefEditor.putBoolean(PREF_LAST_LAUNCH_SUCCESS, success).apply()
49+
}
4150
}

app/src/main/java/dev/arkbuilders/arkmemo/repo/NotesRepoHelper.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import dev.arkbuilders.arklib.user.properties.PropertiesStorage
99
import dev.arkbuilders.arklib.user.properties.PropertiesStorageRepo
1010
import dev.arkbuilders.arkmemo.di.IO_DISPATCHER
1111
import dev.arkbuilders.arkmemo.models.Note
12-
import dev.arkbuilders.arkmemo.preferences.MemoPreferences
1312
import dev.arkbuilders.arkmemo.utils.isEqual
1413
import kotlinx.coroutines.CoroutineDispatcher
1514
import kotlinx.coroutines.CoroutineScope
@@ -30,7 +29,6 @@ import kotlin.io.path.name
3029
class NotesRepoHelper
3130
@Inject
3231
constructor(
33-
private val memoPreferences: MemoPreferences,
3432
private val propertiesStorageRepo: PropertiesStorageRepo,
3533
@Named(IO_DISPATCHER) private val iODispatcher: CoroutineDispatcher,
3634
) {
@@ -40,7 +38,6 @@ class NotesRepoHelper
4038
private val lazyPropertiesStorage by lazy {
4139
CoroutineScope(iODispatcher).async {
4240
val propertyStorage = propertiesStorageRepo.provide(RootIndex.provide(root))
43-
memoPreferences.storePath(root.toString())
4441
propertyStorage
4542
}
4643
}

app/src/main/java/dev/arkbuilders/arkmemo/ui/activities/MainActivity.kt

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,42 +67,39 @@ class MainActivity : AppCompatActivity(R.layout.activity_main) {
6767
onBackPressedDispatcher.onBackPressed()
6868
}
6969

70+
supportFragmentManager.onArkPathPicked(this) {
71+
memoPreferences.storePath(it.toString())
72+
showFragment(savedInstanceState)
73+
}
74+
7075
val storageFolderExisting = memoPreferences.getNotesStorage().exists()
7176
if (memoPreferences.storageNotAvailable()) {
7277
if (!storageFolderExisting) {
7378
showNoNoteStorageDialog(RootNotFound(rootPath = memoPreferences.getPath()))
7479
} else {
7580
FilePickerDialog.show(this, supportFragmentManager)
7681
}
77-
78-
supportFragmentManager.onArkPathPicked(this) {
79-
showFragment(savedInstanceState, it.toString())
80-
}
8182
} else {
82-
showFragment(savedInstanceState, memoPreferences.getPath())
83+
if (memoPreferences.isLastLaunchSuccess()) {
84+
showFragment(savedInstanceState)
85+
} else {
86+
showRetrySelectRootDialog(
87+
rootPath = memoPreferences.getPath(),
88+
savedInstanceState = savedInstanceState,
89+
)
90+
}
8391
}
8492
}
8593

86-
private fun showFragment(
87-
savedInstanceState: Bundle?,
88-
storagePath: String,
89-
) {
94+
private fun showFragment(savedInstanceState: Bundle?) {
9095
val textDataFromIntent = intent?.getStringExtra(Intent.EXTRA_TEXT)
9196
if (textDataFromIntent != null) {
9297
fragment = EditTextNotesFragment.newInstance(textDataFromIntent)
93-
fragment.arguments =
94-
Bundle().apply {
95-
putString(BUNDLE_KEY_STORAGE_PATH, storagePath)
96-
}
9798
supportFragmentManager.beginTransaction().apply {
9899
replace(fragContainer, fragment, EditTextNotesFragment.TAG)
99100
commit()
100101
}
101102
} else {
102-
fragment.arguments =
103-
Bundle().apply {
104-
putString(BUNDLE_KEY_STORAGE_PATH, storagePath)
105-
}
106103
if (savedInstanceState == null) {
107104
supportFragmentManager.beginTransaction().apply {
108105
add(fragContainer, fragment, NotesFragment.TAG)
@@ -143,6 +140,35 @@ class MainActivity : AppCompatActivity(R.layout.activity_main) {
143140
loadFailDialog.show(supportFragmentManager, CommonActionDialog.TAG)
144141
}
145142

143+
private fun showRetrySelectRootDialog(
144+
rootPath: String,
145+
savedInstanceState: Bundle?,
146+
) {
147+
val loadFailDialog =
148+
CommonActionDialog(
149+
title = getString(R.string.error_load_notes_crash_title),
150+
message = getString(R.string.error_load_notes_crash_description, rootPath),
151+
positiveText = R.string.error_load_notes_failed_retry_action,
152+
negativeText = R.string.error_load_notes_failed_negative_action,
153+
neutralText = R.string.error_load_notes_failed_positive_action,
154+
isAlert = false,
155+
enableNeutralOption = true,
156+
onPositiveClick = {
157+
showFragment(savedInstanceState)
158+
},
159+
onNegativeClicked = {
160+
finish()
161+
},
162+
onNeutralClicked = {
163+
FilePickerDialog.show(this, supportFragmentManager)
164+
},
165+
onCloseClicked = {
166+
finish()
167+
},
168+
)
169+
loadFailDialog.show(supportFragmentManager, CommonActionDialog.TAG)
170+
}
171+
146172
override fun onSaveInstanceState(outState: Bundle) {
147173
outState.putString(CURRENT_FRAGMENT_TAG, fragment.tag)
148174
super.onSaveInstanceState(outState)
@@ -176,7 +202,6 @@ class MainActivity : AppCompatActivity(R.layout.activity_main) {
176202

177203
companion object {
178204
private const val CURRENT_FRAGMENT_TAG = "current fragment tag"
179-
const val BUNDLE_KEY_STORAGE_PATH = "bundle_key_storage_path"
180205
}
181206
}
182207

app/src/main/java/dev/arkbuilders/arkmemo/ui/dialogs/CommonActionDialog.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import androidx.annotation.StringRes
88
import androidx.fragment.app.DialogFragment
99
import dev.arkbuilders.arkmemo.R
1010
import dev.arkbuilders.arkmemo.databinding.DialogCommonActionBinding
11+
import dev.arkbuilders.arkmemo.utils.visible
1112

1213
/**
1314
* This is a common action dialog that can be used inside app.
@@ -18,9 +19,12 @@ class CommonActionDialog(
1819
private val message: String,
1920
@StringRes private val positiveText: Int,
2021
@StringRes private val negativeText: Int,
22+
@StringRes private val neutralText: Int? = null,
2123
private val isAlert: Boolean = false,
24+
private val enableNeutralOption: Boolean = false,
2225
private val onPositiveClick: (() -> Unit)? = null,
2326
private val onNegativeClicked: (() -> Unit)? = null,
27+
private val onNeutralClicked: (() -> Unit)? = null,
2428
private val onCloseClicked: (() -> Unit)? = null,
2529
) : DialogFragment() {
2630
companion object {
@@ -48,10 +52,15 @@ class CommonActionDialog(
4852
mBinding.tvPositive.setBackgroundResource(R.drawable.bg_red_button)
4953
}
5054

55+
if (enableNeutralOption) {
56+
mBinding.tvNeutral.visible()
57+
}
58+
5159
mBinding.tvTitle.text = title
5260
mBinding.tvMessage.text = message
5361
mBinding.tvPositive.setText(positiveText)
5462
mBinding.tvNegative.setText(negativeText)
63+
neutralText?.let { mBinding.tvNeutral.setText(neutralText) }
5564
mBinding.ivClose.setOnClickListener {
5665
onCloseClicked?.invoke()
5766
dismiss()
@@ -66,6 +75,11 @@ class CommonActionDialog(
6675
onNegativeClicked?.invoke()
6776
dismiss()
6877
}
78+
79+
mBinding.tvNeutral.setOnClickListener {
80+
onNeutralClicked?.invoke()
81+
dismiss()
82+
}
6983
}
7084

7185
override fun onResume() {

app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/EditTextNotesFragment.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import dagger.hilt.android.AndroidEntryPoint
1515
import dev.arkbuilders.arkmemo.R
1616
import dev.arkbuilders.arkmemo.models.Note
1717
import dev.arkbuilders.arkmemo.models.TextNote
18-
import dev.arkbuilders.arkmemo.ui.activities.MainActivity.Companion.BUNDLE_KEY_STORAGE_PATH
1918
import dev.arkbuilders.arkmemo.utils.getParcelableCompat
2019
import dev.arkbuilders.arkmemo.utils.getTextFromClipBoard
2120
import dev.arkbuilders.arkmemo.utils.gone
@@ -76,9 +75,7 @@ class EditTextNotesFragment : BaseEditNoteFragment() {
7675
note = it
7776
}
7877
noteStr = requireArguments().getString(NOTE_STRING_KEY)
79-
arguments?.getString(BUNDLE_KEY_STORAGE_PATH)?.let {
80-
notesViewModel.init(it) {}
81-
}
78+
notesViewModel.init {}
8279
}
8380
}
8481

app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/NotesFragment.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,12 @@ class NotesFragment : BaseFragment() {
168168
initEmptyStateViews()
169169

170170
binding.pbLoading.visible()
171-
val root = arguments?.getString(MainActivity.BUNDLE_KEY_STORAGE_PATH) ?: ""
172171
notesViewModel.apply {
173-
storePath("")
174-
init(root) {
172+
setLastLaunchSuccess(false)
173+
init {
175174
readAllNotes {
176175
onNotesLoaded(it)
177-
storePath(root)
176+
setLastLaunchSuccess(true)
178177
}
179178
}
180179
}

app/src/main/java/dev/arkbuilders/arkmemo/ui/viewmodels/NotesViewModel.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,8 @@ class NotesViewModel
4343
@set:Inject
4444
internal lateinit var memoPreferences: MemoPreferences
4545

46-
fun init(
47-
root: String,
48-
extraBlock: () -> Unit,
49-
) {
46+
fun init(extraBlock: () -> Unit) {
47+
val root = memoPreferences.getPath()
5048
val initJob =
5149
viewModelScope.launch(iODispatcher) {
5250
textNotesRepo.init(root)
@@ -195,7 +193,7 @@ class NotesViewModel
195193
return memoPreferences.getPath()
196194
}
197195

198-
fun storePath(path: String) {
199-
memoPreferences.storePath(path)
196+
fun setLastLaunchSuccess(success: Boolean) {
197+
memoPreferences.setLastLaunchSuccess(success)
200198
}
201199
}

app/src/main/res/layout/dialog_common_action.xml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,21 @@
5555
android:layout_marginTop="24dp"
5656
android:id="@+id/tv_positive"/>
5757

58+
<TextView
59+
android:layout_width="0dp"
60+
android:layout_height="wrap_content"
61+
style="@style/PositiveButton"
62+
android:text="@string/error_load_notes_failed_retry_action"
63+
android:clickable="true"
64+
android:foreground="?attr/selectableItemBackground"
65+
app:layout_constraintStart_toStartOf="@+id/tv_title"
66+
app:layout_constraintEnd_toEndOf="@+id/iv_close"
67+
app:layout_constraintTop_toBottomOf="@+id/tv_positive"
68+
android:layout_marginTop="@dimen/common_padding"
69+
android:id="@+id/tv_neutral"
70+
android:visibility="gone"
71+
android:layout_marginBottom="@dimen/common_padding" />
72+
5873
<TextView
5974
android:layout_width="0dp"
6075
android:layout_height="wrap_content"
@@ -64,7 +79,7 @@
6479
android:foreground="?attr/selectableItemBackground"
6580
app:layout_constraintStart_toStartOf="@+id/tv_title"
6681
app:layout_constraintEnd_toEndOf="@+id/iv_close"
67-
app:layout_constraintTop_toBottomOf="@+id/tv_positive"
82+
app:layout_constraintTop_toBottomOf="@+id/tv_neutral"
6883
app:layout_constraintBottom_toBottomOf="parent"
6984
android:layout_marginTop="@dimen/common_padding"
7085
android:id="@+id/tv_negative"

0 commit comments

Comments
 (0)