Skip to content

Commit d3960dd

Browse files
committed
Enhance sort view
1 parent 646a3b6 commit d3960dd

20 files changed

Lines changed: 196 additions & 100 deletions

File tree

app/src/main/java/com/ismartcoding/plain/ui/base/MediaTopBar.kt

Lines changed: 12 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,10 @@ package com.ismartcoding.plain.ui.base
22

33
import androidx.compose.foundation.ExperimentalFoundationApi
44
import androidx.compose.material3.ExperimentalMaterial3Api
5-
import androidx.compose.material3.Icon
65
import androidx.compose.material3.MaterialTheme
7-
import androidx.compose.material3.Text
86
import androidx.compose.material3.TopAppBarScrollBehavior
97
import androidx.compose.runtime.Composable
10-
import androidx.compose.runtime.getValue
11-
import androidx.compose.runtime.mutableStateOf
12-
import androidx.compose.runtime.remember
13-
import androidx.compose.runtime.rememberCoroutineScope
14-
import androidx.compose.runtime.setValue
158
import androidx.compose.ui.platform.LocalContext
16-
import androidx.compose.ui.res.painterResource
179
import androidx.compose.ui.res.stringResource
1810
import androidx.compose.ui.unit.dp
1911
import androidx.navigation.NavHostController
@@ -23,15 +15,12 @@ import com.ismartcoding.plain.data.DMediaBucket
2315
import com.ismartcoding.plain.data.IData
2416
import com.ismartcoding.plain.enums.DataType
2517
import com.ismartcoding.plain.features.file.FileSortBy
26-
import com.ismartcoding.plain.preferences.DocTabsModePreference
2718
import com.ismartcoding.plain.ui.base.dragselect.DragSelectState
19+
import com.ismartcoding.plain.ui.components.SortAndBrowseDialog
2820
import com.ismartcoding.plain.ui.models.CastViewModel
2921
import com.ismartcoding.plain.ui.models.BaseMediaViewModel
30-
import com.ismartcoding.plain.ui.models.DocsViewModel
3122
import com.ismartcoding.plain.ui.models.TagsViewModel
3223
import com.ismartcoding.plain.ui.models.enterSearchMode
33-
import kotlinx.coroutines.Dispatchers
34-
import kotlinx.coroutines.launch
3524

3625
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
3726
@Composable
@@ -50,10 +39,7 @@ fun <T : IData> MediaTopBar(
5039
onSearchAction: (context: android.content.Context, tagsViewModel: TagsViewModel) -> Unit
5140
) {
5241
val context = LocalContext.current
53-
val scope = rememberCoroutineScope()
54-
var isSortMenuOpen by remember { mutableStateOf(false) }
5542
val isDocs = mediaVM.dataType == DataType.DOC
56-
val docsVM = mediaVM as? DocsViewModel
5743

5844
val title = getMediaPageTitle(mediaVM.dataType, castVM, bucket = bucketsMap[mediaVM.bucketId.value], dragSelectState, mediaVM.tag, mediaVM.trash)
5945
val containerColor = if (castVM.castMode.value) MaterialTheme.colorScheme.secondaryContainer else null
@@ -116,97 +102,23 @@ fun <T : IData> MediaTopBar(
116102
icon = R.drawable.sort,
117103
contentDescription = stringResource(R.string.sort),
118104
tint = MaterialTheme.colorScheme.onSurface,
119-
click = { isSortMenuOpen = true },
105+
click = { mediaVM.showSortAndBrowseDialog.value = true },
120106
)
121-
PDropdownMenu(
122-
expanded = isSortMenuOpen,
123-
onDismissRequest = { isSortMenuOpen = false }
124-
) {
125-
if (docsVM != null) {
126-
PDropdownMenuItem(
127-
text = { Text(stringResource(R.string.tags)) },
128-
trailingIcon = if (docsVM.tabsShowTags.value) {
129-
{
130-
Icon(
131-
painter = painterResource(R.drawable.check),
132-
contentDescription = null,
133-
tint = MaterialTheme.colorScheme.primary,
134-
)
135-
}
136-
} else {
137-
null
138-
},
139-
onClick = {
140-
isSortMenuOpen = false
141-
if (docsVM.tabsShowTags.value) {
142-
return@PDropdownMenuItem
143-
}
144-
scope.launch(Dispatchers.IO) {
145-
DocTabsModePreference.putAsync(context, true)
146-
docsVM.tabsShowTags.value = true
147-
docsVM.fileType.value = ""
148-
docsVM.tag.value = null
149-
docsVM.trash.value = false
150-
docsVM.loadAsync(context, tagsVM)
151-
}
152-
},
153-
)
154-
PDropdownMenuItem(
155-
text = { Text(stringResource(R.string.type)) },
156-
trailingIcon = if (!docsVM.tabsShowTags.value) {
157-
{
158-
Icon(
159-
painter = painterResource(R.drawable.check),
160-
contentDescription = null,
161-
tint = MaterialTheme.colorScheme.primary,
162-
)
163-
}
164-
} else {
165-
null
166-
},
167-
onClick = {
168-
isSortMenuOpen = false
169-
if (!docsVM.tabsShowTags.value) {
170-
return@PDropdownMenuItem
171-
}
172-
scope.launch(Dispatchers.IO) {
173-
DocTabsModePreference.putAsync(context, false)
174-
docsVM.tabsShowTags.value = false
175-
docsVM.fileType.value = ""
176-
docsVM.tag.value = null
177-
docsVM.trash.value = false
178-
docsVM.loadAsync(context, tagsVM)
179-
}
180-
},
181-
)
182-
}
183-
FileSortBy.entries.forEach { sortByOption ->
184-
if (sortByOption == FileSortBy.TAKEN_AT_DESC && setOf(DataType.AUDIO, DataType.DOC).contains(mediaVM.dataType)) {
185-
return@forEach
186-
}
187-
PDropdownMenuItem(
188-
text = { Text(stringResource(sortByOption.getTextId())) },
189-
trailingIcon = if (mediaVM.sortBy.value == sortByOption) {
190-
{
191-
Icon(
192-
painter = painterResource(R.drawable.check),
193-
contentDescription = null,
194-
tint = MaterialTheme.colorScheme.primary,
195-
)
196-
}
197-
} else null,
198-
onClick = {
199-
isSortMenuOpen = false
200-
onSortSelected(context, sortByOption)
201-
}
202-
)
203-
}
204-
}
205107
}
206108
},
207109
onSearchAction = {
208110
mediaVM.showLoading.value = true
209111
onSearchAction(context, tagsVM)
210112
}
211113
)
114+
115+
if (mediaVM.showSortAndBrowseDialog.value) {
116+
SortAndBrowseDialog(
117+
context = context,
118+
mediaVM = mediaVM,
119+
tagsVM = tagsVM,
120+
onSortSelected = { sortBy -> onSortSelected(context, sortBy) },
121+
onDismiss = { mediaVM.showSortAndBrowseDialog.value = false },
122+
)
123+
}
212124
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package com.ismartcoding.plain.ui.components
2+
3+
import android.content.Context
4+
import androidx.compose.foundation.layout.Spacer
5+
import androidx.compose.foundation.layout.fillMaxWidth
6+
import androidx.compose.foundation.layout.height
7+
import androidx.compose.foundation.lazy.LazyColumn
8+
import androidx.compose.foundation.lazy.items
9+
import androidx.compose.material3.AlertDialog
10+
import androidx.compose.material3.Button
11+
import androidx.compose.material3.ExperimentalMaterial3Api
12+
import androidx.compose.material3.MaterialTheme
13+
import androidx.compose.material3.Text
14+
import androidx.compose.runtime.Composable
15+
import androidx.compose.runtime.rememberCoroutineScope
16+
import androidx.compose.ui.Modifier
17+
import androidx.compose.ui.res.stringResource
18+
import androidx.compose.ui.unit.dp
19+
import com.ismartcoding.plain.R
20+
import com.ismartcoding.plain.data.IData
21+
import com.ismartcoding.plain.enums.DataType
22+
import com.ismartcoding.plain.features.file.FileSortBy
23+
import com.ismartcoding.plain.preferences.DocTabsModePreference
24+
import com.ismartcoding.plain.ui.base.PDialogRadioRow
25+
import com.ismartcoding.plain.ui.models.BaseMediaViewModel
26+
import com.ismartcoding.plain.ui.models.DocsViewModel
27+
import com.ismartcoding.plain.ui.models.TagsViewModel
28+
import kotlinx.coroutines.Dispatchers
29+
import kotlinx.coroutines.launch
30+
31+
@OptIn(ExperimentalMaterial3Api::class)
32+
@Composable
33+
fun <T : IData> SortAndBrowseDialog(
34+
context: Context,
35+
mediaVM: BaseMediaViewModel<T>,
36+
tagsVM: TagsViewModel,
37+
sortByEntries: List<FileSortBy> = FileSortBy.entries.filter { it != FileSortBy.TAKEN_AT_DESC },
38+
onSortSelected: (FileSortBy) -> Unit = {},
39+
onDismiss: () -> Unit = {},
40+
) {
41+
val scope = rememberCoroutineScope()
42+
val isDocs = mediaVM.dataType == DataType.DOC
43+
val docsVM = (mediaVM as? DocsViewModel)
44+
45+
AlertDialog(
46+
modifier = Modifier.fillMaxWidth(),
47+
containerColor = MaterialTheme.colorScheme.surface,
48+
onDismissRequest = onDismiss,
49+
title = null,
50+
text = {
51+
LazyColumn {
52+
// View Mode section (only for docs)
53+
if (isDocs && docsVM != null) {
54+
item {
55+
Text(
56+
text = stringResource(R.string.view_mode),
57+
style = MaterialTheme.typography.titleMedium,
58+
modifier = Modifier.fillMaxWidth()
59+
)
60+
Spacer(modifier = Modifier.height(8.dp))
61+
}
62+
// Browse by tags option
63+
item {
64+
PDialogRadioRow(
65+
selected = docsVM.tabsShowTags.value,
66+
onClick = {
67+
scope.launch(Dispatchers.IO) {
68+
DocTabsModePreference.putAsync(context, true)
69+
docsVM.tabsShowTags.value = true
70+
docsVM.fileType.value = ""
71+
docsVM.tag.value = null
72+
docsVM.trash.value = false
73+
docsVM.loadAsync(context, tagsVM)
74+
}
75+
},
76+
text = stringResource(R.string.browse_by_tags)
77+
)
78+
}
79+
// Browse by file type option
80+
item {
81+
PDialogRadioRow(
82+
selected = !docsVM.tabsShowTags.value,
83+
onClick = {
84+
scope.launch(Dispatchers.IO) {
85+
DocTabsModePreference.putAsync(context, false)
86+
docsVM.tabsShowTags.value = false
87+
docsVM.fileType.value = ""
88+
docsVM.tag.value = null
89+
docsVM.trash.value = false
90+
docsVM.loadAsync(context, tagsVM)
91+
}
92+
},
93+
text = stringResource(R.string.browse_by_file_type)
94+
)
95+
}
96+
// Spacing between sections
97+
item {
98+
Spacer(modifier = Modifier.height(16.dp))
99+
}
100+
}
101+
102+
// Sort rules section
103+
item {
104+
Text(
105+
text = stringResource(R.string.sort),
106+
style = MaterialTheme.typography.titleMedium,
107+
modifier = Modifier.fillMaxWidth()
108+
)
109+
Spacer(modifier = Modifier.height(8.dp))
110+
}
111+
112+
// Sort options
113+
items(sortByEntries) { sortByOption ->
114+
PDialogRadioRow(
115+
selected = mediaVM.sortBy.value == sortByOption,
116+
onClick = {
117+
mediaVM.sortBy.value = sortByOption
118+
onSortSelected(sortByOption)
119+
},
120+
text = stringResource(id = sortByOption.getTextId())
121+
)
122+
}
123+
}
124+
},
125+
confirmButton = {
126+
Button(onClick = onDismiss) {
127+
Text(text = stringResource(id = R.string.close))
128+
}
129+
},
130+
dismissButton = {},
131+
)
132+
}

app/src/main/java/com/ismartcoding/plain/ui/models/BaseMediaViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ abstract class BaseMediaViewModel<T : IData> : ISearchableViewModel<T>, ViewMode
3333
var selectedItem = mutableStateOf<T?>(null)
3434
val showRenameDialog = mutableStateOf(false)
3535
val showTagsDialog = mutableStateOf(false)
36+
val showSortAndBrowseDialog = mutableStateOf(false)
3637

3738
override val showSearchBar = mutableStateOf(false)
3839
override val searchActive = mutableStateOf(false)

app/src/main/res/values-bn/strings_files.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,7 @@
4747
<string name="cannot_copy_folder_into_itself">কোনো ফোল্ডারকে নিজেই বা তার উপ-ফোল্ডারে কপি করা যায় না।</string>
4848
<string name="file_save_to">{{path}} এ ফাইল সংরক্ষিত হয়েছে</string>
4949
<string name="group_by_taken_at">তোলার সময় অনুযায়ী গ্রুপ করুন</string>
50+
<string name="view_mode">দেখার মোড</string>
51+
<string name="browse_by_tags">ট্যাগ অনুযায়ী ব্রাউজ করুন</string>
52+
<string name="browse_by_file_type">ফাইলের ধরন অনুযায়ী ব্রাউজ করুন</string>
5053
</resources>

app/src/main/res/values-de/strings_files.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,7 @@
4747
<string name="cannot_copy_folder_into_itself">Ein Ordner kann nicht in sich selbst oder in einen Unterordner kopiert werden.</string>
4848
<string name="file_save_to">Datei gespeichert unter {{path}}</string>
4949
<string name="group_by_taken_at">Nach Aufnahmezeit gruppieren</string>
50+
<string name="view_mode">Ansichtsmodus</string>
51+
<string name="browse_by_tags">Nach Tags durchsuchen</string>
52+
<string name="browse_by_file_type">Nach Dateityp durchsuchen</string>
5053
</resources>

app/src/main/res/values-es/strings_files.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,7 @@
4747
<string name="cannot_copy_folder_into_itself">No se puede copiar una carpeta dentro de sí misma o de una subcarpeta.</string>
4848
<string name="file_save_to">Archivo guardado en {{path}}</string>
4949
<string name="group_by_taken_at">Agrupar por fecha de captura</string>
50+
<string name="view_mode">Modo de visualización</string>
51+
<string name="browse_by_tags">Explorar por etiquetas</string>
52+
<string name="browse_by_file_type">Explorar por tipo de archivo</string>
5053
</resources>

app/src/main/res/values-fr/strings_files.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,7 @@
4747
<string name="cannot_copy_folder_into_itself">Impossible de copier un dossier dans lui-même ou dans l’un de ses sous-dossiers.</string>
4848
<string name="file_save_to">Fichier enregistré dans {{path}}</string>
4949
<string name="group_by_taken_at">Regrouper par date de prise</string>
50+
<string name="view_mode">Mode d'affichage</string>
51+
<string name="browse_by_tags">Parcourir par tags</string>
52+
<string name="browse_by_file_type">Parcourir par type de fichier</string>
5053
</resources>

app/src/main/res/values-hi/strings_files.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,7 @@
4747
<string name="cannot_copy_folder_into_itself">किसी फ़ोल्डर को उसके भीतर या उसकी उपफ़ोल्डर में कॉपी नहीं किया जा सकता।</string>
4848
<string name="file_save_to">फ़ाइल {{path}} में सहेजी गई</string>
4949
<string name="group_by_taken_at">लिए जाने के समय के अनुसार समूह बनाएं</string>
50+
<string name="view_mode">देखने का मोड</string>
51+
<string name="browse_by_tags">टैग के अनुसार ब्राउज़ करें</string>
52+
<string name="browse_by_file_type">फ़ाइल प्रकार के अनुसार ब्राउज़ करें</string>
5053
</resources>

app/src/main/res/values-it/strings_files.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,7 @@
4747
<string name="cannot_copy_folder_into_itself">Impossibile copiare una cartella in se stessa o in una sua sottocartella.</string>
4848
<string name="file_save_to">File salvato in {{path}}</string>
4949
<string name="group_by_taken_at">Raggruppa per data di acquisizione</string>
50+
<string name="view_mode">Modalità di visualizzazione</string>
51+
<string name="browse_by_tags">Sfoglia per tag</string>
52+
<string name="browse_by_file_type">Sfoglia per tipo di file</string>
5053
</resources>

app/src/main/res/values-ja/strings_files.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,7 @@
4747
<string name="cannot_copy_folder_into_itself">フォルダをそれ自身またはそのサブフォルダ内にコピーできません。</string>
4848
<string name="file_save_to">ファイルを{{path}}に保存しました</string>
4949
<string name="group_by_taken_at">撮影日時でグループ化</string>
50+
<string name="view_mode">表示モード</string>
51+
<string name="browse_by_tags">タグで参照</string>
52+
<string name="browse_by_file_type">ファイルタイプで参照</string>
5053
</resources>

0 commit comments

Comments
 (0)