Skip to content

Commit 8f390f1

Browse files
committed
TodoSettingsFragment: Rewrite to Jetpack Compose (#368, #581)
* Add ViewModel for fragment
1 parent 9a83ee0 commit 8f390f1

File tree

6 files changed

+194
-16
lines changed

6 files changed

+194
-16
lines changed
Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,39 @@
11
package com.edricchan.studybuddy.ui.modules.settings.fragment
22

33
import android.os.Bundle
4-
import com.edricchan.studybuddy.R
5-
import com.edricchan.studybuddy.ui.preference.MaterialPreferenceFragment
4+
import android.view.LayoutInflater
5+
import android.view.ViewGroup
6+
import androidx.compose.foundation.layout.WindowInsets
7+
import androidx.compose.foundation.layout.navigationBars
8+
import androidx.compose.foundation.layout.windowInsetsPadding
9+
import androidx.compose.ui.Modifier
10+
import androidx.compose.ui.input.nestedscroll.nestedScroll
11+
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
12+
import androidx.fragment.app.viewModels
13+
import androidx.fragment.compose.content
14+
import com.edricchan.studybuddy.features.settings.task.ui.TaskSettingsScreen
15+
import com.edricchan.studybuddy.features.settings.task.vm.TaskSettingsViewModel
16+
import com.edricchan.studybuddy.ui.common.fragment.BaseFragment
17+
import com.edricchan.studybuddy.ui.theming.compose.StudyBuddyTheme
18+
import dagger.hilt.android.AndroidEntryPoint
619

7-
class TodoSettingsFragment : MaterialPreferenceFragment() {
8-
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
9-
setPreferencesFromResource(R.xml.pref_todos, rootKey)
20+
@AndroidEntryPoint
21+
class TodoSettingsFragment : BaseFragment() {
22+
private val viewModel by viewModels<TaskSettingsViewModel>()
23+
24+
override fun onCreateView(
25+
inflater: LayoutInflater,
26+
container: ViewGroup?,
27+
savedInstanceState: Bundle?
28+
) = content {
29+
val nestedScrollInterop = rememberNestedScrollInteropConnection()
30+
StudyBuddyTheme {
31+
TaskSettingsScreen(
32+
modifier = Modifier
33+
.nestedScroll(nestedScrollInterop)
34+
.windowInsetsPadding(WindowInsets.navigationBars),
35+
viewModel = viewModel
36+
)
37+
}
1038
}
1139
}

app/src/main/res/xml/pref_todos.xml

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.edricchan.studybuddy.features.settings.task.model
2+
3+
import androidx.annotation.StringRes
4+
import com.edricchan.studybuddy.features.settings.R
5+
import com.edricchan.studybuddy.features.settings.task.model.TaskSortOptionCompat.entries
6+
7+
enum class TaskSortOptionCompat(
8+
@StringRes val stringResource: Int,
9+
val value: String
10+
) {
11+
None(
12+
stringResource = R.string.pref_task_default_sort_entry_none,
13+
value = "none"
14+
),
15+
TitleAsc(
16+
stringResource = R.string.pref_task_default_sort_entry_title_asc,
17+
value = "title_asc"
18+
),
19+
TitleDesc(
20+
stringResource = R.string.pref_task_default_sort_entry_title_desc,
21+
value = "title_desc"
22+
),
23+
DueDateNewToOld(
24+
stringResource = R.string.pref_task_default_sort_entry_due_date_new_to_old,
25+
value = "due_date_new_to_old"
26+
),
27+
DueDateOldToNew(
28+
stringResource = R.string.pref_task_default_sort_entry_due_date_old_to_new,
29+
value = "due_date_old_to_new"
30+
);
31+
32+
companion object {
33+
fun fromValue(value: String): TaskSortOptionCompat = entries.first { it.value == value }
34+
}
35+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package com.edricchan.studybuddy.features.settings.task.ui
2+
3+
import androidx.compose.foundation.layout.Column
4+
import androidx.compose.foundation.rememberScrollState
5+
import androidx.compose.foundation.verticalScroll
6+
import androidx.compose.material3.Icon
7+
import androidx.compose.material3.Text
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.runtime.getValue
10+
import androidx.compose.runtime.mutableStateOf
11+
import androidx.compose.runtime.remember
12+
import androidx.compose.runtime.setValue
13+
import androidx.compose.ui.Modifier
14+
import androidx.compose.ui.res.painterResource
15+
import androidx.compose.ui.res.stringResource
16+
import androidx.compose.ui.tooling.preview.Preview
17+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
18+
import com.edricchan.studybuddy.features.settings.R
19+
import com.edricchan.studybuddy.features.settings.task.model.TaskSortOptionCompat
20+
import com.edricchan.studybuddy.features.settings.task.vm.TaskSettingsViewModel
21+
import com.edricchan.studybuddy.ui.preference.compose.ListDialogPreference
22+
import com.edricchan.studybuddy.ui.theming.compose.StudyBuddyTheme
23+
24+
@Composable
25+
private fun TaskDefaultSortPreference(
26+
modifier: Modifier = Modifier,
27+
defaultSort: TaskSortOptionCompat,
28+
onDefaultSortChange: (TaskSortOptionCompat) -> Unit
29+
) {
30+
ListDialogPreference(
31+
modifier = modifier,
32+
icon = { Icon(painterResource(R.drawable.ic_sort_24dp), contentDescription = null) },
33+
title = { Text(text = stringResource(R.string.pref_task_default_sort_title)) },
34+
subtitle = { Text(text = stringResource(defaultSort.stringResource)) },
35+
values = TaskSortOptionCompat.entries,
36+
value = defaultSort,
37+
onValueChanged = onDefaultSortChange,
38+
valueLabel = { Text(text = stringResource(it.stringResource)) }
39+
)
40+
}
41+
42+
@Composable
43+
fun TaskSettingsScreen(
44+
modifier: Modifier = Modifier,
45+
defaultSort: TaskSortOptionCompat,
46+
onDefaultSortChange: (TaskSortOptionCompat) -> Unit
47+
) = Column(
48+
modifier = modifier.verticalScroll(rememberScrollState())
49+
) {
50+
TaskDefaultSortPreference(
51+
defaultSort = defaultSort,
52+
onDefaultSortChange = onDefaultSortChange
53+
)
54+
}
55+
56+
@Composable
57+
fun TaskSettingsScreen(
58+
modifier: Modifier = Modifier,
59+
viewModel: TaskSettingsViewModel
60+
) {
61+
val defaultSort by viewModel.prefDefaultSort.asFlow().collectAsStateWithLifecycle(
62+
TaskSortOptionCompat.None
63+
)
64+
65+
TaskSettingsScreen(
66+
modifier = modifier,
67+
defaultSort = defaultSort,
68+
onDefaultSortChange = viewModel.prefDefaultSort::set
69+
)
70+
}
71+
72+
@Preview
73+
@Composable
74+
private fun TaskSettingsScreenPreview() {
75+
var defaultSort by remember { mutableStateOf(TaskSortOptionCompat.None) }
76+
77+
StudyBuddyTheme {
78+
TaskSettingsScreen(
79+
defaultSort = defaultSort,
80+
onDefaultSortChange = { defaultSort = it }
81+
)
82+
}
83+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.edricchan.studybuddy.features.settings.task.vm
2+
3+
import android.content.Context
4+
import androidx.lifecycle.ViewModel
5+
import com.edricchan.studybuddy.core.settings.tasks.keyPrefTaskDefaultSort
6+
import com.edricchan.studybuddy.exts.androidx.preference.defaultSharedPreferences
7+
import com.edricchan.studybuddy.features.settings.task.model.TaskSortOptionCompat
8+
import com.fredporciuncula.flow.preferences.FlowSharedPreferences
9+
import com.fredporciuncula.flow.preferences.Preference
10+
import com.fredporciuncula.flow.preferences.map
11+
import dagger.hilt.android.lifecycle.HiltViewModel
12+
import dagger.hilt.android.qualifiers.ApplicationContext
13+
import javax.inject.Inject
14+
15+
@HiltViewModel
16+
class TaskSettingsViewModel @Inject constructor(
17+
@ApplicationContext context: Context
18+
) : ViewModel() {
19+
private val appPreferences = FlowSharedPreferences(
20+
context.defaultSharedPreferences
21+
)
22+
23+
val prefDefaultSort: Preference<TaskSortOptionCompat> = appPreferences.getString(
24+
keyPrefTaskDefaultSort
25+
).map(
26+
mapper = TaskSortOptionCompat::fromValue,
27+
reverse = TaskSortOptionCompat::value
28+
)
29+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<!-- TODO: Add a better UI for the default sort -->
4+
<eat-comment />
5+
6+
<!-- Title for the default sort mode setting. -->
7+
<string name="pref_task_default_sort_title">Default sorting mode</string>
8+
9+
<string name="pref_task_default_sort_entry_none">None (Default)</string>
10+
<string name="pref_task_default_sort_entry_title_asc">Title (A to Z)</string>
11+
<string name="pref_task_default_sort_entry_title_desc">Title (Z to A)</string>
12+
<string name="pref_task_default_sort_entry_due_date_new_to_old">Due Date (Newest to Oldest)</string>
13+
<string name="pref_task_default_sort_entry_due_date_old_to_new">Due Date (Oldest to Newest)</string>
14+
</resources>

0 commit comments

Comments
 (0)