mirror of
https://github.com/LiveFastEatTrashRaccoon/RaccoonForLemmy.git
synced 2025-02-02 22:57:39 +01:00
feat: community-specific download directory (#581)
This commit is contained in:
parent
1fd2f96a81
commit
9f04030a3e
@ -25,6 +25,8 @@ fun SettingsIntValueRow(
|
||||
onIncrement: () -> Unit,
|
||||
onDecrement: () -> Unit,
|
||||
) {
|
||||
val fullColor = MaterialTheme.colorScheme.onBackground
|
||||
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f)
|
||||
Row(
|
||||
modifier = Modifier.padding(horizontal = Spacing.m),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
@ -35,13 +37,13 @@ fun SettingsIntValueRow(
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
color = fullColor,
|
||||
)
|
||||
if (subtitle != null) {
|
||||
Text(
|
||||
text = subtitle,
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
color = ancillaryColor,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -60,7 +62,7 @@ fun SettingsIntValueRow(
|
||||
textAlign = TextAlign.Center,
|
||||
text = value.toString(),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
color = fullColor,
|
||||
)
|
||||
FeedbackButton(
|
||||
imageVector = Icons.Default.ArrowCircleUp,
|
||||
|
@ -33,6 +33,7 @@ fun SettingsRow(
|
||||
onTap: (() -> Unit)? = null,
|
||||
) {
|
||||
val fullColor = MaterialTheme.colorScheme.onBackground
|
||||
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f)
|
||||
Row(
|
||||
modifier = modifier
|
||||
.padding(vertical = Spacing.s, horizontal = Spacing.m)
|
||||
@ -64,7 +65,7 @@ fun SettingsRow(
|
||||
Text(
|
||||
text = subtitle,
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = fullColor,
|
||||
color = ancillaryColor,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -25,16 +25,18 @@ fun SettingsSwitchRow(
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
val fullColor = MaterialTheme.colorScheme.onBackground
|
||||
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f)
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
color = fullColor,
|
||||
)
|
||||
if (subtitle != null) {
|
||||
Text(
|
||||
text = subtitle,
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
color = ancillaryColor,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">هناك تغييرات لم يتم حفظها، هل أنت متأكد من أنك تريد الخروج؟</string>
|
||||
<string name="button_no_stay">لا، ابق هنا</string>
|
||||
<string name="button_yes_quit">نعم، الخروج</string>
|
||||
<string name="settings_item_image_source_path">حفظ الصور في أدلة فرعية محددة</string>
|
||||
<string name="settings_subtitle_image_source_path">استخدم المجتمع أو مقبض المستخدم في المسارات</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Има незапазени промени, сигурни ли сте, че искате да излезете?</string>
|
||||
<string name="button_no_stay">Не, остани тук</string>
|
||||
<string name="button_yes_quit">Да, изход</string>
|
||||
<string name="settings_item_image_source_path">Запазване на изображения в определени поддиректории</string>
|
||||
<string name="settings_subtitle_image_source_path">използвайте общност или потребителски манипулатор в пътеки</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Existují neuložené změny. Opravdu chcete skončit?</string>
|
||||
<string name="button_no_stay">Ne, zůstaň tady</string>
|
||||
<string name="button_yes_quit">Ano, odejít</string>
|
||||
<string name="settings_item_image_source_path">Ukládejte obrázky do konkrétních podadresářů</string>
|
||||
<string name="settings_subtitle_image_source_path">použijte komunitní nebo uživatelský popisovač v cestách</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Der er ikke-gemte ændringer. Er du sikker på, at du vil afslutte?</string>
|
||||
<string name="button_no_stay">Nej, bliv her</string>
|
||||
<string name="button_yes_quit">Ja, exit</string>
|
||||
<string name="settings_item_image_source_path">Gem billeder i specifikke undermapper</string>
|
||||
<string name="settings_subtitle_image_source_path">bruge fællesskab eller brugerhåndtag i stier</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Es gibt nicht gespeicherte Änderungen. Möchten Sie den Vorgang wirklich beenden?</string>
|
||||
<string name="button_no_stay">Nein, bleib hier</string>
|
||||
<string name="button_yes_quit">Ja, beenden</string>
|
||||
<string name="settings_item_image_source_path">Speichern Sie Bilder in bestimmten Unterverzeichnissen</string>
|
||||
<string name="settings_subtitle_image_source_path">Verwenden Sie Community- oder Benutzer-Handle in Pfaden</string>
|
||||
</resources>
|
||||
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Υπάρχουν μη αποθηκευμένες αλλαγές, είστε βέβαιοι ότι θέλετε να βγείτε;</string>
|
||||
<string name="button_no_stay">Όχι, μείνε εδώ</string>
|
||||
<string name="button_yes_quit">Ναι, βγες</string>
|
||||
<string name="settings_item_image_source_path">Αποθηκεύστε εικόνες σε συγκεκριμένους υποκαταλόγους</string>
|
||||
<string name="settings_subtitle_image_source_path">χρήση κοινότητας ή χειρισμού χρήστη σε μονοπάτια</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Estas nekonservitaj ŝanĝoj, ĉu vi certas, ke vi volas eliri?</string>
|
||||
<string name="button_no_stay">Ne, resti ĉi tie</string>
|
||||
<string name="button_yes_quit">Jes, eliri</string>
|
||||
<string name="settings_item_image_source_path">Konservi bildojn en specifaj subdosierujoj</string>
|
||||
<string name="settings_subtitle_image_source_path">uzi komunumon aŭ uzantan tenilon en vojoj</string>
|
||||
</resources>
|
@ -339,5 +339,7 @@
|
||||
<string name="ban_item_duration_days">Duración (días)</string>
|
||||
<string name="message_unsaved_changes">Hay cambios sin guardar, ¿está seguro de que quiere salir?</string>
|
||||
<string name="button_no_stay">No, quedar aquí</string>
|
||||
<string name="button_yes_quit">si, salir</string>
|
||||
<string name="button_yes_quit">Sí, salir</string>
|
||||
<string name="settings_item_image_source_path">Guardar imágenes en subdirectorios específicos</string>
|
||||
<string name="settings_subtitle_image_source_path">utilizar la comunidad o el identificador de usuario en las rutas</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">On salvestamata muudatusi. Kas soovite kindlasti väljuda?</string>
|
||||
<string name="button_no_stay">Ei, jää siia</string>
|
||||
<string name="button_yes_quit">Jah, välju</string>
|
||||
<string name="settings_item_image_source_path">Salvestage pildid kindlatesse alamkataloogidesse</string>
|
||||
<string name="settings_subtitle_image_source_path">kasutada teedel kommuuni või kasutajakäepidet</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Tallentamattomia muutoksia on. Haluatko varmasti poistua?</string>
|
||||
<string name="button_no_stay">Ei, pysy täällä</string>
|
||||
<string name="button_yes_quit">Kyllä, poistu</string>
|
||||
<string name="settings_item_image_source_path">Tallenna kuvat tiettyihin alihakemistoihin</string>
|
||||
<string name="settings_subtitle_image_source_path">käytä yhteisö- tai käyttäjäkahvaa poluissa</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Il y a des modifications non enregistrées, êtes-vous sûr de vouloir quitter ?</string>
|
||||
<string name="button_no_stay">Non, rester ici</string>
|
||||
<string name="button_yes_quit">Oui, quitter</string>
|
||||
<string name="settings_item_image_source_path">Enregistrez les images dans des sous-répertoires spécifiques</string>
|
||||
<string name="settings_subtitle_image_source_path">utiliser la communauté ou le handle d\'utilisateur dans les chemins</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Tá athruithe gan sábháil, an bhfuil tú cinnte gur mhaith leat scoir?</string>
|
||||
<string name="button_no_stay">Ní hea, fan anseo</string>
|
||||
<string name="button_yes_quit">Sea, scoir</string>
|
||||
<string name="settings_item_image_source_path">Sábháil íomhánna i bhfo-eolaire ar leith</string>
|
||||
<string name="settings_subtitle_image_source_path">úsáid pobail nó láimhseáil úsáideora i gcosáin</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Postoje nespremljene promjene, jeste li sigurni da želite izaći?</string>
|
||||
<string name="button_no_stay">Ne, ostani ovdje</string>
|
||||
<string name="button_yes_quit">Da, izlaz</string>
|
||||
<string name="settings_item_image_source_path">Spremite slike u određene poddirektorije</string>
|
||||
<string name="settings_subtitle_image_source_path">upotrijebite ručku zajednice ili korisnika u stazama</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Vannak nem mentett módosítások. Biztosan kilép?</string>
|
||||
<string name="button_no_stay">Nem, maradj itt</string>
|
||||
<string name="button_yes_quit">Igen, kilép</string>
|
||||
<string name="settings_item_image_source_path">Mentse el a képeket meghatározott alkönyvtárakba</string>
|
||||
<string name="settings_subtitle_image_source_path">közösségi vagy felhasználói fogantyú használata az elérési utakban</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Ci sono modifiche non salvate. Sei sicuro di voler uscire?</string>
|
||||
<string name="button_no_stay">No, resta qui</string>
|
||||
<string name="button_yes_quit">Sì, esci</string>
|
||||
<string name="settings_item_image_source_path">Salva le immagini in sottodirectory specifiche</string>
|
||||
<string name="settings_subtitle_image_source_path">utilizza handle comunità o utente nei percorsi</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Yra neišsaugotų pakeitimų. Ar tikrai norite išeiti?</string>
|
||||
<string name="button_no_stay">Ne, pasilik čia</string>
|
||||
<string name="button_yes_quit">Taip, išeiti</string>
|
||||
<string name="settings_item_image_source_path">Išsaugokite vaizdus tam tikruose pakatalogiuose</string>
|
||||
<string name="settings_subtitle_image_source_path">keliuose naudokite bendruomenės arba vartotojo rankenėlę</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Ir nesaglabātas izmaiņas. Vai tiešām vēlaties iziet?</string>
|
||||
<string name="button_no_stay">Nē, paliec šeit</string>
|
||||
<string name="button_yes_quit">Jā, iziet</string>
|
||||
<string name="settings_item_image_source_path">Saglabājiet attēlus noteiktos apakšdirektorijos</string>
|
||||
<string name="settings_subtitle_image_source_path">ceļos izmantojiet kopienu vai lietotāja rokturi</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Hemm bidliet mhux salvati, żgur li trid toħroġ?</string>
|
||||
<string name="button_no_stay">Le, oqgħod hawn</string>
|
||||
<string name="button_yes_quit">Iva, ħruġ</string>
|
||||
<string name="settings_item_image_source_path">Ħlief immaġini f\'sub-direttorji speċifiċi</string>
|
||||
<string name="settings_subtitle_image_source_path">uża l-komunità jew il-manku tal-utent fil-mogħdijiet</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Er zijn niet-opgeslagen wijzigingen. Weet u zeker dat u wilt afsluiten?</string>
|
||||
<string name="button_no_stay">Nee, blijf hier</string>
|
||||
<string name="button_yes_quit">Ja, vertrek</string>
|
||||
<string name="settings_item_image_source_path">Bewaar afbeeldingen in specifieke submappen</string>
|
||||
<string name="settings_subtitle_image_source_path">gebruik community- of gebruikershandle in paden</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Det er ulagrede endringer, er du sikker på at du vil avslutte?</string>
|
||||
<string name="button_no_stay">Nei, bli her</string>
|
||||
<string name="button_yes_quit">Ja, gå ut</string>
|
||||
<string name="settings_item_image_source_path">Lagre bilder i bestemte underkataloger</string>
|
||||
<string name="settings_subtitle_image_source_path">bruk fellesskap eller brukerhåndtak i baner</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Istnieją niezapisane zmiany. Czy na pewno chcesz wyjść?</string>
|
||||
<string name="button_no_stay">Nie, zostań tutaj</string>
|
||||
<string name="button_yes_quit">Tak, wyjdź</string>
|
||||
<string name="settings_item_image_source_path">Zapisuj obrazy w określonych podkatalogach</string>
|
||||
<string name="settings_subtitle_image_source_path">użyj uchwytu społeczności lub użytkownika w ścieżkach</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Existem alterações não salvas. Tem certeza de que deseja sair?</string>
|
||||
<string name="button_no_stay">Não, ficar aqui</string>
|
||||
<string name="button_yes_quit">Sim, sair</string>
|
||||
<string name="settings_item_image_source_path">Salve imagens em subdiretórios específicos</string>
|
||||
<string name="settings_subtitle_image_source_path">use comunidade ou identificador de usuário em caminhos</string>
|
||||
</resources>
|
||||
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Existem alterações não salvas. Tem certeza de que deseja sair?</string>
|
||||
<string name="button_no_stay">Não, ficar aqui</string>
|
||||
<string name="button_yes_quit">Sim, sair</string>
|
||||
<string name="settings_item_image_source_path">Salve imagens em subdiretórios específicos</string>
|
||||
<string name="settings_subtitle_image_source_path">use comunidade ou identificador de usuário em caminhos</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Există modificări nesalvate, ești sigur că vrei să ieși?</string>
|
||||
<string name="button_no_stay">Nu, stai aici</string>
|
||||
<string name="button_yes_quit">Da, ieși</string>
|
||||
<string name="settings_item_image_source_path">Salvă imaginile în anumite subdirectoare</string>
|
||||
<string name="settings_subtitle_image_source_path">utilizează comunitatea sau identificatorul utilizatorului în căi</string>
|
||||
</resources>
|
@ -339,4 +339,6 @@
|
||||
<string name="message_unsaved_changes">Есть несохраненные изменения. Вы уверены, что хотите выйти?</string>
|
||||
<string name="button_no_stay">Нет, оставайся здесь</string>
|
||||
<string name="button_yes_quit">Да, выход</string>
|
||||
<string name="settings_item_image_source_path">Сохраняйте изображения в определенных подкаталогах.</string>
|
||||
<string name="settings_subtitle_image_source_path">используйте дескриптор сообщества или пользователя в путях</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Det finns osparade ändringar, är du säker på att du vill avsluta?</string>
|
||||
<string name="button_no_stay">Nej, stanna här</string>
|
||||
<string name="button_yes_quit">Ja, avsluta</string>
|
||||
<string name="settings_item_image_source_path">Spara bilder i specifika underkataloger</string>
|
||||
<string name="settings_subtitle_image_source_path">använd gemenskap eller användarhandtag i sökvägar</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Existujú neuložené zmeny. Naozaj chcete skončiť?</string>
|
||||
<string name="button_no_stay">Nie, zostaň tu</string>
|
||||
<string name="button_yes_quit">Áno, odísť</string>
|
||||
<string name="settings_item_image_source_path">Uložte obrázky do konkrétnych podadresárov</string>
|
||||
<string name="settings_subtitle_image_source_path">použite komunitný alebo užívateľský popisovač v cestách</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Obstajajo neshranjene spremembe. Ste prepričani, da želite zapustiti?</string>
|
||||
<string name="button_no_stay">Ne, ostani tukaj</string>
|
||||
<string name="button_yes_quit">Ja, izhod</string>
|
||||
<string name="settings_item_image_source_path">Shranite slike v določene podimenike</string>
|
||||
<string name="settings_subtitle_image_source_path">uporabite ročaj skupnosti ali uporabnika v poteh</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Ka ndryshime të paruajtura, je i sigurt që dëshiron të dalësh?</string>
|
||||
<string name="button_no_stay">Jo, rri këtu</string>
|
||||
<string name="button_yes_quit">Po, dil</string>
|
||||
<string name="settings_item_image_source_path">Ruani imazhet në nën-drejtori të veçanta</string>
|
||||
<string name="settings_subtitle_image_source_path">përdorni bashkësinë ose dorezën e përdoruesit në shtigje</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">sina ante e sona, taso sina awen ala e ona. sina wile ala wile tawa weka?</string>
|
||||
<string name="button_no_stay">o awen</string>
|
||||
<string name="button_yes_quit">o tawa weka</string>
|
||||
<string name="settings_item_image_source_path">o awen e sitelen lon poki pi nimi lili</string>
|
||||
<string name="settings_subtitle_image_source_path">o kepeken e nimi kulupu/nimi jan lon linja</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">Kaydedilmemiş değişiklikler var, çıkmak istediğinizden emin misiniz?</string>
|
||||
<string name="button_no_stay">Hayır, burada kal</string>
|
||||
<string name="button_yes_quit">Evet, çık</string>
|
||||
<string name="settings_item_image_source_path">Görüntüleri belirli alt dizinlere kaydedin</string>
|
||||
<string name="settings_subtitle_image_source_path">yollarda topluluk veya kullanıcı tanıtıcısını kullanın</string>
|
||||
</resources>
|
@ -339,4 +339,6 @@
|
||||
<string name="message_unsaved_changes">Є незбережені зміни. Ви впевнені, що бажаєте вийти?</string>
|
||||
<string name="button_no_stay">Ні, залишайся тут</string>
|
||||
<string name="button_yes_quit">Так, вихід</string>
|
||||
<string name="settings_item_image_source_path">Зберігайте зображення в певних підкаталогах</string>
|
||||
<string name="settings_subtitle_image_source_path">використовуйте дескриптор спільноти або користувача в шляхах</string>
|
||||
</resources>
|
@ -340,4 +340,6 @@
|
||||
<string name="message_unsaved_changes">There are unsaved changes, are you sure you want to quit?</string>
|
||||
<string name="button_no_stay">No, stay here</string>
|
||||
<string name="button_yes_quit">Yes, quit</string>
|
||||
<string name="settings_item_image_source_path">Save images in specific sub-directories</string>
|
||||
<string name="settings_subtitle_image_source_path">use community or user handle in paths</string>
|
||||
</resources>
|
@ -53,4 +53,5 @@ data class SettingsModel(
|
||||
val showScores: Boolean = true,
|
||||
val preferUserNicknames: Boolean = true,
|
||||
val commentBarThickness: Int = 1,
|
||||
val imageSourcePath: Boolean = false,
|
||||
)
|
||||
|
@ -56,6 +56,7 @@ private object KeyStoreKeys {
|
||||
const val SHOW_SCORES = "showScores"
|
||||
const val PREFER_USER_NICKNAMES = "preferUserNicknames"
|
||||
const val COMMENT_BAR_THICKNESS = "commentBarThickness"
|
||||
const val IMAGE_SOURCE_PATH = "imageSourcePath"
|
||||
}
|
||||
|
||||
internal class DefaultSettingsRepository(
|
||||
@ -125,7 +126,8 @@ internal class DefaultSettingsRepository(
|
||||
opaqueSystemBars = if (settings.opaqueSystemBars) 1L else 0L,
|
||||
showScores = if (settings.showScores) 1L else 0L,
|
||||
preferUserNicknames = if (settings.preferUserNicknames) 1L else 0L,
|
||||
commentBarThickness = settings.commentBarThickness.toLong()
|
||||
commentBarThickness = settings.commentBarThickness.toLong(),
|
||||
imageSourcePath = if (settings.imageSourcePath) 1L else 0L,
|
||||
)
|
||||
}
|
||||
|
||||
@ -180,6 +182,7 @@ internal class DefaultSettingsRepository(
|
||||
showScores = keyStore[KeyStoreKeys.SHOW_SCORES, true],
|
||||
preferUserNicknames = keyStore[KeyStoreKeys.PREFER_USER_NICKNAMES, true],
|
||||
commentBarThickness = keyStore[KeyStoreKeys.COMMENT_BAR_THICKNESS, 1],
|
||||
imageSourcePath = keyStore[KeyStoreKeys.IMAGE_SOURCE_PATH, false],
|
||||
)
|
||||
} else {
|
||||
val entity = db.settingsQueries.getBy(accountId).executeAsOneOrNull()
|
||||
@ -280,6 +283,7 @@ internal class DefaultSettingsRepository(
|
||||
keyStore.save(KeyStoreKeys.SHOW_SCORES, settings.showScores)
|
||||
keyStore.save(KeyStoreKeys.PREFER_USER_NICKNAMES, settings.preferUserNicknames)
|
||||
keyStore.save(KeyStoreKeys.COMMENT_BAR_THICKNESS, settings.commentBarThickness)
|
||||
keyStore.save(KeyStoreKeys.IMAGE_SOURCE_PATH, settings.imageSourcePath)
|
||||
} else {
|
||||
db.settingsQueries.update(
|
||||
theme = settings.theme?.toLong(),
|
||||
@ -338,6 +342,7 @@ internal class DefaultSettingsRepository(
|
||||
showScores = if (settings.showScores) 1L else 0L,
|
||||
preferUserNicknames = if (settings.preferUserNicknames) 1L else 0L,
|
||||
commentBarThickness = settings.commentBarThickness.toLong(),
|
||||
imageSourcePath = if (settings.imageSourcePath) 1L else 0L,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -412,4 +417,5 @@ private fun GetBy.toModel() = SettingsModel(
|
||||
showScores = showScores == 1L,
|
||||
preferUserNicknames = preferUserNicknames == 1L,
|
||||
commentBarThickness = commentBarThickness.toInt(),
|
||||
imageSourcePath = imageSourcePath == 1L,
|
||||
)
|
||||
|
@ -50,6 +50,7 @@ CREATE TABLE SettingsEntity (
|
||||
showScores INTEGER NOT NULL DEFAULT 1,
|
||||
preferUserNicknames INTEGER NOT NULL DEFAULT 1,
|
||||
commentBarThickness INTEGER NOT NULL DEFAULT 0,
|
||||
imageSourcePath INTEGER NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY (account_id) REFERENCES AccountEntity(id) ON DELETE CASCADE,
|
||||
UNIQUE(account_id)
|
||||
);
|
||||
@ -105,6 +106,7 @@ INSERT OR IGNORE INTO SettingsEntity (
|
||||
showScores,
|
||||
preferUserNicknames,
|
||||
commentBarThickness,
|
||||
imageSourcePath,
|
||||
account_id
|
||||
) VALUES (
|
||||
?,
|
||||
@ -156,6 +158,7 @@ INSERT OR IGNORE INTO SettingsEntity (
|
||||
?,
|
||||
?,
|
||||
?,
|
||||
?,
|
||||
?
|
||||
);
|
||||
|
||||
@ -209,7 +212,8 @@ SET theme = ?,
|
||||
opaqueSystemBars = ?,
|
||||
showScores = ?,
|
||||
preferUserNicknames = ?,
|
||||
commentBarThickness = ?
|
||||
commentBarThickness = ?,
|
||||
imageSourcePath = ?
|
||||
WHERE account_id = ?;
|
||||
|
||||
getBy:
|
||||
@ -263,6 +267,7 @@ SELECT
|
||||
opaqueSystemBars,
|
||||
showScores,
|
||||
preferUserNicknames,
|
||||
commentBarThickness
|
||||
commentBarThickness,
|
||||
imageSourcePath
|
||||
FROM SettingsEntity
|
||||
WHERE account_id = ?;
|
@ -0,0 +1,2 @@
|
||||
ALTER TABLE SettingsEntity
|
||||
ADD COLUMN imageSourcePath INTEGER NOT NULL DEFAULT 0;
|
@ -3,7 +3,7 @@ package com.github.diegoberaldin.raccoonforlemmy.core.utils.gallery
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.provider.MediaStore
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
@ -17,25 +17,32 @@ import kotlinx.coroutines.launch
|
||||
import org.koin.dsl.module
|
||||
import org.koin.java.KoinJavaComponent.inject
|
||||
|
||||
private const val DEFAULT_BASE_PATH = "RaccoonForLemmy"
|
||||
|
||||
class DefaultGalleryHelper(
|
||||
private val context: Context,
|
||||
) : GalleryHelper {
|
||||
|
||||
override fun saveToGallery(bytes: ByteArray, name: String) {
|
||||
val resolver = context.applicationContext.contentResolver
|
||||
override val supportsCustomPath: Boolean = true
|
||||
|
||||
val collection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
|
||||
} else {
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||
override fun saveToGallery(bytes: ByteArray, name: String, additionalPathSegment: String?) {
|
||||
val relativePath = buildString {
|
||||
append(Environment.DIRECTORY_PICTURES)
|
||||
append("/")
|
||||
append(DEFAULT_BASE_PATH)
|
||||
if (!additionalPathSegment.isNullOrEmpty()) {
|
||||
append("/")
|
||||
append(additionalPathSegment)
|
||||
}
|
||||
}
|
||||
|
||||
val resolver = context.applicationContext.contentResolver
|
||||
val details = ContentValues().apply {
|
||||
put(MediaStore.Images.Media.DISPLAY_NAME, name)
|
||||
put(MediaStore.Images.Media.IS_PENDING, 1)
|
||||
put(MediaStore.Images.Media.RELATIVE_PATH, relativePath)
|
||||
}
|
||||
|
||||
val uri = resolver.insert(collection, details)
|
||||
val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, details)
|
||||
if (uri != null) {
|
||||
resolver.openFileDescriptor(uri, "w", null).use { pfd ->
|
||||
ParcelFileDescriptor.AutoCloseOutputStream(pfd).use {
|
||||
|
@ -7,7 +7,10 @@ import org.koin.core.module.Module
|
||||
|
||||
@Stable
|
||||
interface GalleryHelper {
|
||||
fun saveToGallery(bytes: ByteArray, name: String)
|
||||
|
||||
val supportsCustomPath: Boolean
|
||||
|
||||
fun saveToGallery(bytes: ByteArray, name: String, additionalPathSegment: String? = null)
|
||||
|
||||
@Composable
|
||||
fun getImageFromGallery(result: (ByteArray) -> Unit)
|
||||
|
@ -42,8 +42,10 @@ fun ImageBytes.toByteArray(): ByteArray = ByteArray(this@toByteArray.length.toIn
|
||||
|
||||
class DefaultGalleryHelper : GalleryHelper {
|
||||
|
||||
override val supportsCustomPath: Boolean = false
|
||||
|
||||
@OptIn(ExperimentalForeignApi::class)
|
||||
override fun saveToGallery(bytes: ByteArray, name: String) {
|
||||
override fun saveToGallery(bytes: ByteArray, name: String, additionalPathSegment: String?) {
|
||||
val image = UIImage(bytes.toImageBytes())
|
||||
UIImageWriteToSavedPhotosAlbum(image, null, null, null)
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.SearchResult
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.SearchResultType
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toInt
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.zoomableimage.ZoomableImageScreen
|
||||
@ -504,7 +505,10 @@ class ExploreScreen : Screen {
|
||||
},
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(url),
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = result.model.community?.readableHandle.orEmpty(),
|
||||
),
|
||||
)
|
||||
},
|
||||
onOpenPost = rememberCallbackArgs { post, instance ->
|
||||
|
@ -6,8 +6,8 @@ import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
interface AdvancedSettingsMviModel :
|
||||
MviModel<AdvancedSettingsMviModel.Intent, AdvancedSettingsMviModel.UiState, AdvancedSettingsMviModel.Effect>,
|
||||
ScreenModel {
|
||||
ScreenModel,
|
||||
MviModel<AdvancedSettingsMviModel.Intent, AdvancedSettingsMviModel.UiState, AdvancedSettingsMviModel.Effect> {
|
||||
|
||||
sealed interface Intent {
|
||||
data class ChangeEnableDoubleTapAction(val value: Boolean) : Intent
|
||||
@ -19,6 +19,7 @@ interface AdvancedSettingsMviModel :
|
||||
data class ChangeSearchPostTitleOnly(val value: Boolean) : Intent
|
||||
data class ChangeEdgeToEdge(val value: Boolean) : Intent
|
||||
data class ChangeInfiniteScrollDisabled(val value: Boolean) : Intent
|
||||
data class ChangeImageSourcePath(val value: Boolean) : Intent
|
||||
}
|
||||
|
||||
data class UiState(
|
||||
@ -36,6 +37,7 @@ interface AdvancedSettingsMviModel :
|
||||
val edgeToEdge: Boolean = true,
|
||||
val infiniteScrollDisabled: Boolean = false,
|
||||
val opaqueSystemBars: Boolean = false,
|
||||
val imageSourcePath: Boolean = false,
|
||||
)
|
||||
|
||||
sealed interface Effect
|
||||
|
@ -121,13 +121,25 @@ class AdvancedSettingsScreen : Screen {
|
||||
)
|
||||
}
|
||||
|
||||
// image source path
|
||||
SettingsSwitchRow(
|
||||
title = LocalXmlStrings.current.settingsItemImageSourcePath,
|
||||
subtitle = LocalXmlStrings.current.settingsSubtitleImageSourcePath,
|
||||
value = uiState.imageSourcePath,
|
||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||
model.reduce(
|
||||
AdvancedSettingsMviModel.Intent.ChangeImageSourcePath(value),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
// navigation bar titles
|
||||
SettingsSwitchRow(
|
||||
title = LocalXmlStrings.current.settingsNavigationBarTitlesVisible,
|
||||
value = uiState.navBarTitlesVisible,
|
||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||
model.reduce(
|
||||
AdvancedSettingsMviModel.Intent.ChangeNavBarTitlesVisible(value)
|
||||
AdvancedSettingsMviModel.Intent.ChangeNavBarTitlesVisible(value),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
@ -75,8 +75,8 @@ class AdvancedSettingsViewModel(
|
||||
edgeToEdge = settings.edgeToEdge,
|
||||
infiniteScrollDisabled = !settings.infiniteScrollEnabled,
|
||||
opaqueSystemBars = settings.opaqueSystemBars,
|
||||
|
||||
)
|
||||
imageSourcePath = settings.imageSourcePath,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,6 +107,8 @@ class AdvancedSettingsViewModel(
|
||||
is AdvancedSettingsMviModel.Intent.ChangeEdgeToEdge -> changeEdgeToEdge(intent.value)
|
||||
is AdvancedSettingsMviModel.Intent.ChangeInfiniteScrollDisabled ->
|
||||
changeInfiniteScrollDisabled(intent.value)
|
||||
|
||||
is AdvancedSettingsMviModel.Intent.ChangeImageSourcePath -> changeImageSourcePath(intent.value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,6 +247,16 @@ class AdvancedSettingsViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeImageSourcePath(value: Boolean) {
|
||||
updateState { it.copy(imageSourcePath = value) }
|
||||
scope?.launch(Dispatchers.IO) {
|
||||
val settings = settingsRepository.currentSettings.value.copy(
|
||||
imageSourcePath = value
|
||||
)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun saveSettings(settings: SettingsModel) {
|
||||
val accountId = accountRepository.getActive()?.id
|
||||
settingsRepository.updateSettings(settings, accountId)
|
||||
|
@ -68,6 +68,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.gallery.getGalleryHelper
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PrivateMessageModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.chat.components.MessageCard
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.chat.components.MessageCardPlaceholder
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
||||
@ -250,7 +251,12 @@ class InboxChatScreen(
|
||||
content = content,
|
||||
date = date,
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = message.creator?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
onOpenCommunity = rememberCallbackArgs { community, instance ->
|
||||
detailOpener.openCommunityDetail(
|
||||
|
@ -547,7 +547,12 @@ class CommunityDetailScreen(
|
||||
community = uiState.community,
|
||||
autoLoadImages = uiState.autoLoadImages,
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = uiState.community.readableHandle,
|
||||
)
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
@ -757,7 +762,10 @@ class CommunityDetailScreen(
|
||||
)
|
||||
)
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(url),
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = uiState.community.readableHandle,
|
||||
),
|
||||
)
|
||||
},
|
||||
options = buildList {
|
||||
|
@ -219,7 +219,12 @@ class CommunityInfoScreen(
|
||||
navigationCoordinator.hideBottomSheet()
|
||||
scope.launch {
|
||||
delay(100)
|
||||
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = uiState.community.readableHandle,
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
onOpenCommunity = { community, instance ->
|
||||
|
@ -55,6 +55,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigation
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.ActionOnSwipe
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.zoomableimage.ZoomableImageScreen
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@ -242,7 +243,12 @@ class InboxMentionsScreen : Tab {
|
||||
detailOpener.openCommunityDetail(community = community)
|
||||
},
|
||||
onImageClick = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = mention.post.community?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
onUpVote = rememberCallbackArgs(model) { _ ->
|
||||
model.reduce(InboxMentionsMviModel.Intent.UpVoteComment(mention.id))
|
||||
|
@ -67,6 +67,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.ban.BanUserScreen
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.moddedcontents.comments.components.ModdedCommentPlaceholder
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
||||
@ -321,7 +322,10 @@ class ModdedPostsScreen : Screen {
|
||||
},
|
||||
onOpenImage = rememberCallbackArgs(model, post) { url ->
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(url)
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = post.community?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
options = buildList {
|
||||
|
@ -85,6 +85,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.getAdditionalLabel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toInt
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
||||
@ -444,7 +445,12 @@ class MultiCommunityScreen(
|
||||
},
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
model.reduce(MultiCommunityMviModel.Intent.MarkAsRead(post.id))
|
||||
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = post.community?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
options = buildList {
|
||||
add(
|
||||
|
@ -65,6 +65,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.drafts.DraftsScreen
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.managesubscriptions.ManageSubscriptionsScreen
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.moddedcontents.comments.ModdedCommentsScreen
|
||||
@ -178,7 +179,12 @@ object ProfileLoggedScreen : Tab {
|
||||
user = user,
|
||||
autoLoadImages = uiState.autoLoadImages,
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = uiState.user?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
@ -276,7 +282,10 @@ object ProfileLoggedScreen : Tab {
|
||||
},
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(url),
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = post.community?.readableHandle.orEmpty(),
|
||||
),
|
||||
)
|
||||
},
|
||||
onUpVote = rememberCallback(model) {
|
||||
@ -406,7 +415,12 @@ object ProfileLoggedScreen : Tab {
|
||||
hideAuthor = true,
|
||||
hideIndent = true,
|
||||
onImageClick = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = comment.community?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
onOpenCommunity = rememberCallbackArgs { community, instance ->
|
||||
detailOpener.openCommunityDetail(community, instance)
|
||||
|
@ -101,6 +101,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.containsId
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableName
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toInt
|
||||
@ -508,7 +509,10 @@ class PostDetailScreen(
|
||||
},
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(url),
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = uiState.post.community?.readableHandle.orEmpty(),
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
@ -789,7 +793,10 @@ class PostDetailScreen(
|
||||
},
|
||||
onImageClick = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(url)
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = uiState.post.community?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
options = buildList {
|
||||
|
@ -87,6 +87,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.keepscreenon.rememberKeepScreenOn
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableName
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toInt
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
||||
@ -324,7 +325,10 @@ class PostListScreen : Screen {
|
||||
items(
|
||||
items = uiState.posts,
|
||||
// isLogged is added to the key to force swipe action refresh
|
||||
key = { it.id.toString() + (it.updateDate ?: it.publishDate) + uiState.isLogged },
|
||||
key = {
|
||||
it.id.toString() + (it.updateDate
|
||||
?: it.publishDate) + uiState.isLogged
|
||||
},
|
||||
) { post ->
|
||||
LaunchedEffect(post.id) {
|
||||
if (settings.markAsReadWhileScrolling && !post.read) {
|
||||
@ -501,7 +505,10 @@ class PostListScreen : Screen {
|
||||
onOpenImage = rememberCallbackArgs(model, post) { url ->
|
||||
model.reduce(PostListMviModel.Intent.MarkAsRead(post.id))
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(url)
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = post.community?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
options = buildList {
|
||||
|
@ -56,6 +56,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigation
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.ActionOnSwipe
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.zoomableimage.ZoomableImageScreen
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@ -238,7 +239,12 @@ class InboxRepliesScreen : Tab {
|
||||
detailOpener.openCommunityDetail(community = community)
|
||||
},
|
||||
onImageClick = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = reply.post.community?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
onUpVote = rememberCallbackArgs(model) { _ ->
|
||||
model.reduce(InboxRepliesMviModel.Intent.UpVoteComment(reply.id))
|
||||
|
@ -68,6 +68,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toInt
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
||||
@ -264,7 +265,10 @@ class SavedItemsScreen : Screen {
|
||||
},
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
navigatorCoordinator.pushScreen(
|
||||
ZoomableImageScreen(url),
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = post.community?.readableHandle.orEmpty(),
|
||||
),
|
||||
)
|
||||
},
|
||||
options = buildList {
|
||||
@ -355,7 +359,12 @@ class SavedItemsScreen : Screen {
|
||||
)
|
||||
},
|
||||
onImageClick = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = comment.community?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
onUpVote = {
|
||||
model.reduce(
|
||||
|
@ -423,7 +423,8 @@ class UserDetailScreen(
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(
|
||||
url
|
||||
url = url,
|
||||
source = uiState.user?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
@ -655,7 +656,10 @@ class UserDetailScreen(
|
||||
},
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(url),
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = post.community?.readableHandle.orEmpty(),
|
||||
),
|
||||
)
|
||||
},
|
||||
options = buildList {
|
||||
@ -884,7 +888,10 @@ class UserDetailScreen(
|
||||
},
|
||||
onImageClick = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(url)
|
||||
ZoomableImageScreen(
|
||||
url = url,
|
||||
source = comment.community?.readableHandle.orEmpty(),
|
||||
)
|
||||
)
|
||||
},
|
||||
onDoubleClick = if (!uiState.doubleTapActionEnabled) {
|
||||
|
@ -46,6 +46,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigation
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.prettifyDate
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.getPrettyNumber
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.readableName
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.userinfo.components.ModeratedCommunityCell
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
||||
@ -173,7 +174,8 @@ class UserInfoScreen(
|
||||
delay(100)
|
||||
navigationCoordinator.pushScreen(
|
||||
ZoomableImageScreen(
|
||||
url
|
||||
url = url,
|
||||
source = uiState.user.readableHandle,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -6,11 +6,14 @@ import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
|
||||
|
||||
@Stable
|
||||
interface ZoomableImageMviModel :
|
||||
MviModel<ZoomableImageMviModel.Intent, ZoomableImageMviModel.UiState, ZoomableImageMviModel.Effect>,
|
||||
ScreenModel {
|
||||
ScreenModel,
|
||||
MviModel<ZoomableImageMviModel.Intent, ZoomableImageMviModel.UiState, ZoomableImageMviModel.Effect> {
|
||||
sealed interface Intent {
|
||||
data class Share(val url: String) : Intent
|
||||
data class SaveToGallery(val url: String) : Intent
|
||||
data class SaveToGallery(
|
||||
val source: String,
|
||||
val url: String,
|
||||
) : Intent
|
||||
}
|
||||
|
||||
data class UiState(
|
||||
|
@ -43,6 +43,7 @@ import kotlinx.coroutines.flow.onEach
|
||||
|
||||
class ZoomableImageScreen(
|
||||
private val url: String,
|
||||
private val source: String = "",
|
||||
) : Screen {
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@ -95,7 +96,12 @@ class ZoomableImageScreen(
|
||||
Icon(
|
||||
modifier = Modifier.onClick(
|
||||
onClick = rememberCallback {
|
||||
model.reduce(ZoomableImageMviModel.Intent.SaveToGallery(url))
|
||||
model.reduce(
|
||||
ZoomableImageMviModel.Intent.SaveToGallery(
|
||||
url = url,
|
||||
source = source,
|
||||
)
|
||||
)
|
||||
},
|
||||
),
|
||||
imageVector = Icons.Default.Download,
|
||||
|
@ -38,11 +38,15 @@ class ZoomableImageViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
is ZoomableImageMviModel.Intent.SaveToGallery -> downloadAndSave(intent.url)
|
||||
is ZoomableImageMviModel.Intent.SaveToGallery -> downloadAndSave(
|
||||
folder = intent.source,
|
||||
url = intent.url,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun downloadAndSave(url: String) {
|
||||
private fun downloadAndSave(url: String, folder: String) {
|
||||
val imageSourcePath = settingsRepository.currentSettings.value.imageSourcePath
|
||||
scope?.launch(Dispatchers.IO) {
|
||||
updateState { it.copy(loading = true) }
|
||||
try {
|
||||
@ -51,7 +55,11 @@ class ZoomableImageViewModel(
|
||||
val idx = s.lastIndexOf(".").takeIf { it >= 0 } ?: s.length
|
||||
s.substring(idx).takeIf { it.isNotEmpty() } ?: ".jpeg"
|
||||
}
|
||||
galleryHelper.saveToGallery(bytes, "${epochMillis()}.$extension")
|
||||
galleryHelper.saveToGallery(
|
||||
bytes = bytes,
|
||||
name = "${epochMillis()}$extension",
|
||||
additionalPathSegment = folder.takeIf { imageSourcePath },
|
||||
)
|
||||
emitEffect(ZoomableImageMviModel.Effect.ShareSuccess)
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
|
Loading…
x
Reference in New Issue
Block a user