v1.4.1+62
All checks were successful
Flutter Schmutter / build (push) Successful in 3m48s

This commit is contained in:
2025-06-21 13:40:44 +02:00
parent 2b5aaad331
commit 73a44bb269
15 changed files with 608 additions and 515 deletions

View File

@ -6,6 +6,13 @@ import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:encrypt_shared_preferences/provider.dart';
const Map<String, Locale> supportedLocales = {
'en_US': Locale('en', 'US'),
'de_DE': Locale('de', 'DE'),
'fr_FR': Locale('fr', 'FR'),
'nl_NL': Locale('nl', 'NL'),
};
class MyTranslations extends Translations {
static final MyTranslations instance = MyTranslations._internal();
MyTranslations._internal();
@ -13,15 +20,18 @@ class MyTranslations extends Translations {
static final Map<String, Map<String, String>> _translations = {};
static Future<void> loadTranslations() async {
final locales = ['en_US', 'de_DE', 'fr_FR', 'nl_NL'];
for (final locale in locales) {
final String jsonString = await rootBundle.loadString(
'assets/i18n/$locale.json',
);
final Map<String, dynamic> jsonMap = json.decode(jsonString);
_translations[locale] = jsonMap.map(
(key, value) => MapEntry(key, value.toString()),
);
for (final localeKey in supportedLocales.keys) {
try {
final String jsonString = await rootBundle.loadString(
'assets/i18n/$localeKey.json',
);
final Map<String, dynamic> jsonMap = json.decode(jsonString);
_translations[localeKey] = jsonMap.map(
(key, value) => MapEntry(key, value.toString()),
);
} catch (e) {
debugPrint('Konnte Übersetzung für $localeKey nicht laden: $e');
}
}
}
@ -32,7 +42,7 @@ class MyTranslations extends Translations {
class LocalizationController extends GetxController {
final EncryptedSharedPreferencesAsync storage =
EncryptedSharedPreferencesAsync.getInstance();
Rx<Locale> currentLocale = const Locale('en', 'US').obs;
Rx<Locale> currentLocale = supportedLocales['en_US']!.obs;
@override
void onInit() {
@ -41,25 +51,29 @@ class LocalizationController extends GetxController {
}
Future<void> loadLocale() async {
String? savedLocale = await storage.getString(
String? savedLocaleKey = await storage.getString(
'locale',
defaultValue: 'en_US',
);
if (savedLocale != null && savedLocale.isNotEmpty) {
final List<String> parts = savedLocale.split('_');
currentLocale.value = parts.length == 2
? Locale(parts[0], parts[1])
: Locale(parts[0]);
Get.locale = currentLocale.value;
}
final Locale locale =
supportedLocales[savedLocaleKey ?? 'en_US'] ??
supportedLocales['en_US']!;
currentLocale.value = locale;
Get.locale = locale;
}
Future<void> changeLocale(Locale newLocale) async {
final String localeKey = supportedLocales.entries
.firstWhere(
(entry) => entry.value == newLocale,
orElse: () => supportedLocales.entries.first,
)
.key;
currentLocale.value = newLocale;
Get.updateLocale(newLocale);
await storage.setString(
'locale',
'${newLocale.languageCode}_${newLocale.countryCode}',
);
await storage.setString('locale', localeKey);
}
}

View File

@ -10,7 +10,7 @@ const List<String> mediaTypes = ["alles", "image", "video", "audio"];
const List<String> mediaModes = ["sfw", "nsfw", "untagged", "all"];
class MediaController extends GetxController {
final ApiService _api = ApiService();
final ApiService _api = Get.find<ApiService>();
final EncryptedSharedPreferencesAsync storage =
EncryptedSharedPreferencesAsync.getInstance();
@ -22,7 +22,7 @@ class MediaController extends GetxController {
RxInt typeIndex = 0.obs;
RxInt modeIndex = 0.obs;
RxInt random = 0.obs;
Rxn<String> tag = Rxn<String>();
Rxn<String> tag = Rxn<String>(null);
RxBool muted = false.obs;
Rx<PageTransition> transitionType = PageTransition.opacity.obs;
RxBool drawerSwipeEnabled = true.obs;
@ -45,14 +45,6 @@ class MediaController extends GetxController {
}
}
List<MediaItem> get filteredItems {
final String typeStr = mediaTypes[typeIndex.value];
return items.where((item) {
final bool typeOk = typeStr == "alles" || item.mime.startsWith(typeStr);
return typeOk;
}).toList();
}
Future<List<Favorite>?> toggleFavorite(
MediaItem item,
bool isFavorite,
@ -64,68 +56,82 @@ class MediaController extends GetxController {
}
}
Future<void> fetchInitial({int? id}) async {
Future<Feed?> _fetchItems({int? older, int? newer}) async {
if (loading.value) return null;
loading.value = true;
try {
final Feed result = await _api.fetchItems(
return await _api.fetchItems(
older: older,
newer: newer,
type: typeIndex.value,
mode: modeIndex.value,
random: random.value,
tag: tag.value,
older: id,
);
} catch (e) {
Get.snackbar(
'Fehler beim Laden',
'Die Daten konnten nicht abgerufen werden. Wo Internet?',
snackPosition: SnackPosition.BOTTOM,
);
return null;
} finally {
loading.value = false;
}
}
Future<void> fetchInitial({int? id}) async {
final result = await _fetchItems(older: id);
if (result != null) {
items.assignAll(result.items);
atEnd.value = result.atEnd;
atStart.value = result.atStart;
} finally {
loading.value = false;
}
}
Future<void> fetchMore() async {
if (items.isEmpty || atEnd.value) return;
loading.value = true;
try {
final Feed result = await _api.fetchItems(
older: items.last.id,
type: typeIndex.value,
mode: modeIndex.value,
random: random.value,
tag: tag.value,
);
final result = await _fetchItems(older: items.last.id);
if (result != null) {
final Set<int> existingIds = items.map((e) => e.id).toSet();
final List<MediaItem> newItems = result.items
.where((item) => !items.any((existing) => existing.id == item.id))
.where((item) => !existingIds.contains(item.id))
.toList();
items.addAll(newItems);
items.refresh();
atEnd.value = result.atEnd;
} finally {
loading.value = false;
}
}
Future<int> fetchNewer() async {
if (items.isEmpty || atStart.value) return 0;
loading.value = true;
try {
final Feed result = await _api.fetchItems(
newer: items.first.id,
type: typeIndex.value,
mode: modeIndex.value,
random: random.value,
tag: tag.value,
);
int oldLength = filteredItems.length;
final oldLength = items.length;
final result = await _fetchItems(newer: items.first.id);
if (result != null) {
final Set<int> existingIds = items.map((e) => e.id).toSet();
final List<MediaItem> newItems = result.items
.where((item) => !items.any((existing) => existing.id == item.id))
.where((item) => !existingIds.contains(item.id))
.toList();
items.insertAll(0, newItems);
items.refresh();
atStart.value = result.atStart;
int newLength = filteredItems.length;
return newLength - oldLength;
} finally {
loading.value = false;
return items.length - oldLength;
}
return 0;
}
Future<void> handleRefresh() async {
if (loading.value) return;
if (!atStart.value) {
await fetchNewer();
} else {
await fetchInitial();
}
}
Future<void> handleLoading() async {
if (!loading.value && !atEnd.value) {
await fetchMore();
}
}
@ -178,4 +184,6 @@ class MediaController extends GetxController {
await storage.setBoolean('drawerSwipeEnabled', drawerSwipeEnabled.value);
await storage.setInt('transitionType', transitionType.value.index);
}
bool get isRandomEnabled => random.value == 1;
}