[imp]: Refactor localization & convert screens to slivers
This commit is contained in:
+321
-194
@@ -1,306 +1,433 @@
|
||||
import 'dart:convert';
|
||||
import 'package:crowdin_sdk/crowdin_sdk.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
|
||||
import 'app_localizations.dart';
|
||||
|
||||
import 'package:crowdin_sdk/crowdin_sdk.dart';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
|
||||
class CrowdinLocalization extends AppLocalizations {
|
||||
final AppLocalizations _fallbackTexts;
|
||||
|
||||
CrowdinLocalization(String locale, AppLocalizations fallbackTexts) : _fallbackTexts = fallbackTexts, super(locale);
|
||||
|
||||
static const LocalizationsDelegate<AppLocalizations> delegate = _CrowdinLocalizationsDelegate();
|
||||
CrowdinLocalization(super.locale, AppLocalizations fallbackTexts)
|
||||
: _fallbackTexts = fallbackTexts;
|
||||
|
||||
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <
|
||||
LocalizationsDelegate<dynamic>>[
|
||||
delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
];
|
||||
static const LocalizationsDelegate<AppLocalizations> delegate =
|
||||
_CrowdinLocalizationsDelegate();
|
||||
|
||||
static const List<Locale> supportedLocales = AppLocalizations.supportedLocales;
|
||||
|
||||
@override
|
||||
String get app_name => Crowdin.getText(localeName, 'app_name') ?? _fallbackTexts.app_name;
|
||||
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
|
||||
<LocalizationsDelegate<dynamic>>[
|
||||
delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
];
|
||||
|
||||
@override
|
||||
String get welcome => Crowdin.getText(localeName, 'welcome') ?? _fallbackTexts.welcome;
|
||||
static const List<Locale> supportedLocales =
|
||||
AppLocalizations.supportedLocales;
|
||||
|
||||
@override
|
||||
String get search => Crowdin.getText(localeName, 'search') ?? _fallbackTexts.search;
|
||||
@override
|
||||
String get app_name =>
|
||||
Crowdin.getText(localeName, 'app_name') ?? _fallbackTexts.app_name;
|
||||
|
||||
@override
|
||||
String get settings => Crowdin.getText(localeName, 'settings') ?? _fallbackTexts.settings;
|
||||
@override
|
||||
String get welcome =>
|
||||
Crowdin.getText(localeName, 'welcome') ?? _fallbackTexts.welcome;
|
||||
|
||||
@override
|
||||
@override
|
||||
String get search =>
|
||||
Crowdin.getText(localeName, 'search') ?? _fallbackTexts.search;
|
||||
|
||||
@override
|
||||
String get settings =>
|
||||
Crowdin.getText(localeName, 'settings') ?? _fallbackTexts.settings;
|
||||
|
||||
@override
|
||||
String get home => Crowdin.getText(localeName, 'home') ?? _fallbackTexts.home;
|
||||
|
||||
@override
|
||||
String get categories => Crowdin.getText(localeName, 'categories') ?? _fallbackTexts.categories;
|
||||
@override
|
||||
String get categories =>
|
||||
Crowdin.getText(localeName, 'categories') ?? _fallbackTexts.categories;
|
||||
|
||||
@override
|
||||
String get updates => Crowdin.getText(localeName, 'updates') ?? _fallbackTexts.updates;
|
||||
@override
|
||||
String get updates =>
|
||||
Crowdin.getText(localeName, 'updates') ?? _fallbackTexts.updates;
|
||||
|
||||
@override
|
||||
String get installed => Crowdin.getText(localeName, 'installed') ?? _fallbackTexts.installed;
|
||||
@override
|
||||
String get installed =>
|
||||
Crowdin.getText(localeName, 'installed') ?? _fallbackTexts.installed;
|
||||
|
||||
@override
|
||||
String get download => Crowdin.getText(localeName, 'download') ?? _fallbackTexts.download;
|
||||
@override
|
||||
String get download =>
|
||||
Crowdin.getText(localeName, 'download') ?? _fallbackTexts.download;
|
||||
|
||||
@override
|
||||
String get install => Crowdin.getText(localeName, 'install') ?? _fallbackTexts.install;
|
||||
@override
|
||||
String get install =>
|
||||
Crowdin.getText(localeName, 'install') ?? _fallbackTexts.install;
|
||||
|
||||
@override
|
||||
String get uninstall => Crowdin.getText(localeName, 'uninstall') ?? _fallbackTexts.uninstall;
|
||||
@override
|
||||
String get uninstall =>
|
||||
Crowdin.getText(localeName, 'uninstall') ?? _fallbackTexts.uninstall;
|
||||
|
||||
@override
|
||||
@override
|
||||
String get open => Crowdin.getText(localeName, 'open') ?? _fallbackTexts.open;
|
||||
|
||||
@override
|
||||
String get cancel => Crowdin.getText(localeName, 'cancel') ?? _fallbackTexts.cancel;
|
||||
@override
|
||||
String get cancel =>
|
||||
Crowdin.getText(localeName, 'cancel') ?? _fallbackTexts.cancel;
|
||||
|
||||
@override
|
||||
String get update_available => Crowdin.getText(localeName, 'update_available') ?? _fallbackTexts.update_available;
|
||||
@override
|
||||
String get update_available =>
|
||||
Crowdin.getText(localeName, 'update_available') ??
|
||||
_fallbackTexts.update_available;
|
||||
|
||||
@override
|
||||
String get downloading => Crowdin.getText(localeName, 'downloading') ?? _fallbackTexts.downloading;
|
||||
@override
|
||||
String get downloading =>
|
||||
Crowdin.getText(localeName, 'downloading') ?? _fallbackTexts.downloading;
|
||||
|
||||
@override
|
||||
String get install_permission_required => Crowdin.getText(localeName, 'install_permission_required') ?? _fallbackTexts.install_permission_required;
|
||||
@override
|
||||
String get install_permission_required =>
|
||||
Crowdin.getText(localeName, 'install_permission_required') ??
|
||||
_fallbackTexts.install_permission_required;
|
||||
|
||||
@override
|
||||
String get storage_permission_required => Crowdin.getText(localeName, 'storage_permission_required') ?? _fallbackTexts.storage_permission_required;
|
||||
@override
|
||||
String get storage_permission_required =>
|
||||
Crowdin.getText(localeName, 'storage_permission_required') ??
|
||||
_fallbackTexts.storage_permission_required;
|
||||
|
||||
@override
|
||||
String get cancel_download => Crowdin.getText(localeName, 'cancel_download') ?? _fallbackTexts.cancel_download;
|
||||
@override
|
||||
String get cancel_download =>
|
||||
Crowdin.getText(localeName, 'cancel_download') ??
|
||||
_fallbackTexts.cancel_download;
|
||||
|
||||
@override
|
||||
String get version => Crowdin.getText(localeName, 'version') ?? _fallbackTexts.version;
|
||||
@override
|
||||
String get version =>
|
||||
Crowdin.getText(localeName, 'version') ?? _fallbackTexts.version;
|
||||
|
||||
@override
|
||||
@override
|
||||
String get size => Crowdin.getText(localeName, 'size') ?? _fallbackTexts.size;
|
||||
|
||||
@override
|
||||
String get description => Crowdin.getText(localeName, 'description') ?? _fallbackTexts.description;
|
||||
@override
|
||||
String get description =>
|
||||
Crowdin.getText(localeName, 'description') ?? _fallbackTexts.description;
|
||||
|
||||
@override
|
||||
String get permissions => Crowdin.getText(localeName, 'permissions') ?? _fallbackTexts.permissions;
|
||||
@override
|
||||
String get permissions =>
|
||||
Crowdin.getText(localeName, 'permissions') ?? _fallbackTexts.permissions;
|
||||
|
||||
@override
|
||||
String get screenshots => Crowdin.getText(localeName, 'screenshots') ?? _fallbackTexts.screenshots;
|
||||
@override
|
||||
String get screenshots =>
|
||||
Crowdin.getText(localeName, 'screenshots') ?? _fallbackTexts.screenshots;
|
||||
|
||||
@override
|
||||
String get no_version_available => Crowdin.getText(localeName, 'no_version_available') ?? _fallbackTexts.no_version_available;
|
||||
@override
|
||||
String get no_version_available =>
|
||||
Crowdin.getText(localeName, 'no_version_available') ??
|
||||
_fallbackTexts.no_version_available;
|
||||
|
||||
@override
|
||||
String get app_information => Crowdin.getText(localeName, 'app_information') ?? _fallbackTexts.app_information;
|
||||
@override
|
||||
String get app_information =>
|
||||
Crowdin.getText(localeName, 'app_information') ??
|
||||
_fallbackTexts.app_information;
|
||||
|
||||
@override
|
||||
String get package_name => Crowdin.getText(localeName, 'package_name') ?? _fallbackTexts.package_name;
|
||||
@override
|
||||
String get package_name =>
|
||||
Crowdin.getText(localeName, 'package_name') ??
|
||||
_fallbackTexts.package_name;
|
||||
|
||||
@override
|
||||
String get license => Crowdin.getText(localeName, 'license') ?? _fallbackTexts.license;
|
||||
@override
|
||||
String get license =>
|
||||
Crowdin.getText(localeName, 'license') ?? _fallbackTexts.license;
|
||||
|
||||
@override
|
||||
String get added => Crowdin.getText(localeName, 'added') ?? _fallbackTexts.added;
|
||||
@override
|
||||
String get added =>
|
||||
Crowdin.getText(localeName, 'added') ?? _fallbackTexts.added;
|
||||
|
||||
@override
|
||||
String get last_updated => Crowdin.getText(localeName, 'last_updated') ?? _fallbackTexts.last_updated;
|
||||
@override
|
||||
String get last_updated =>
|
||||
Crowdin.getText(localeName, 'last_updated') ??
|
||||
_fallbackTexts.last_updated;
|
||||
|
||||
@override
|
||||
String get version_information => Crowdin.getText(localeName, 'version_information') ?? _fallbackTexts.version_information;
|
||||
@override
|
||||
String get version_information =>
|
||||
Crowdin.getText(localeName, 'version_information') ??
|
||||
_fallbackTexts.version_information;
|
||||
|
||||
@override
|
||||
String get version_name => Crowdin.getText(localeName, 'version_name') ?? _fallbackTexts.version_name;
|
||||
@override
|
||||
String get version_name =>
|
||||
Crowdin.getText(localeName, 'version_name') ??
|
||||
_fallbackTexts.version_name;
|
||||
|
||||
@override
|
||||
String get version_code => Crowdin.getText(localeName, 'version_code') ?? _fallbackTexts.version_code;
|
||||
@override
|
||||
String get version_code =>
|
||||
Crowdin.getText(localeName, 'version_code') ??
|
||||
_fallbackTexts.version_code;
|
||||
|
||||
@override
|
||||
String get min_sdk => Crowdin.getText(localeName, 'min_sdk') ?? _fallbackTexts.min_sdk;
|
||||
@override
|
||||
String get min_sdk =>
|
||||
Crowdin.getText(localeName, 'min_sdk') ?? _fallbackTexts.min_sdk;
|
||||
|
||||
@override
|
||||
String get target_sdk => Crowdin.getText(localeName, 'target_sdk') ?? _fallbackTexts.target_sdk;
|
||||
@override
|
||||
String get target_sdk =>
|
||||
Crowdin.getText(localeName, 'target_sdk') ?? _fallbackTexts.target_sdk;
|
||||
|
||||
@override
|
||||
String get all_versions => Crowdin.getText(localeName, 'all_versions') ?? _fallbackTexts.all_versions;
|
||||
@override
|
||||
String get all_versions =>
|
||||
Crowdin.getText(localeName, 'all_versions') ??
|
||||
_fallbackTexts.all_versions;
|
||||
|
||||
@override
|
||||
String get latest => Crowdin.getText(localeName, 'latest') ?? _fallbackTexts.latest;
|
||||
@override
|
||||
String get latest =>
|
||||
Crowdin.getText(localeName, 'latest') ?? _fallbackTexts.latest;
|
||||
|
||||
@override
|
||||
String get released => Crowdin.getText(localeName, 'released') ?? _fallbackTexts.released;
|
||||
@override
|
||||
String get released =>
|
||||
Crowdin.getText(localeName, 'released') ?? _fallbackTexts.released;
|
||||
|
||||
@override
|
||||
String get loading => Crowdin.getText(localeName, 'loading') ?? _fallbackTexts.loading;
|
||||
@override
|
||||
String get loading =>
|
||||
Crowdin.getText(localeName, 'loading') ?? _fallbackTexts.loading;
|
||||
|
||||
@override
|
||||
String get error => Crowdin.getText(localeName, 'error') ?? _fallbackTexts.error;
|
||||
@override
|
||||
String get error =>
|
||||
Crowdin.getText(localeName, 'error') ?? _fallbackTexts.error;
|
||||
|
||||
@override
|
||||
String get retry => Crowdin.getText(localeName, 'retry') ?? _fallbackTexts.retry;
|
||||
@override
|
||||
String get retry =>
|
||||
Crowdin.getText(localeName, 'retry') ?? _fallbackTexts.retry;
|
||||
|
||||
@override
|
||||
String get share => Crowdin.getText(localeName, 'share') ?? _fallbackTexts.share;
|
||||
@override
|
||||
String get share =>
|
||||
Crowdin.getText(localeName, 'share') ?? _fallbackTexts.share;
|
||||
|
||||
@override
|
||||
String get website => Crowdin.getText(localeName, 'website') ?? _fallbackTexts.website;
|
||||
@override
|
||||
String get website =>
|
||||
Crowdin.getText(localeName, 'website') ?? _fallbackTexts.website;
|
||||
|
||||
@override
|
||||
String get source_code => Crowdin.getText(localeName, 'source_code') ?? _fallbackTexts.source_code;
|
||||
@override
|
||||
String get source_code =>
|
||||
Crowdin.getText(localeName, 'source_code') ?? _fallbackTexts.source_code;
|
||||
|
||||
@override
|
||||
String get issue_tracker => Crowdin.getText(localeName, 'issue_tracker') ?? _fallbackTexts.issue_tracker;
|
||||
@override
|
||||
String get issue_tracker =>
|
||||
Crowdin.getText(localeName, 'issue_tracker') ??
|
||||
_fallbackTexts.issue_tracker;
|
||||
|
||||
@override
|
||||
String get whats_new => Crowdin.getText(localeName, 'whats_new') ?? _fallbackTexts.whats_new;
|
||||
@override
|
||||
String get whats_new =>
|
||||
Crowdin.getText(localeName, 'whats_new') ?? _fallbackTexts.whats_new;
|
||||
|
||||
@override
|
||||
String get show_more => Crowdin.getText(localeName, 'show_more') ?? _fallbackTexts.show_more;
|
||||
@override
|
||||
String get show_more =>
|
||||
Crowdin.getText(localeName, 'show_more') ?? _fallbackTexts.show_more;
|
||||
|
||||
@override
|
||||
String get show_less => Crowdin.getText(localeName, 'show_less') ?? _fallbackTexts.show_less;
|
||||
@override
|
||||
String get show_less =>
|
||||
Crowdin.getText(localeName, 'show_less') ?? _fallbackTexts.show_less;
|
||||
|
||||
@override
|
||||
String get downloads_stats => Crowdin.getText(localeName, 'downloads_stats') ?? _fallbackTexts.downloads_stats;
|
||||
@override
|
||||
String get downloads_stats =>
|
||||
Crowdin.getText(localeName, 'downloads_stats') ??
|
||||
_fallbackTexts.downloads_stats;
|
||||
|
||||
@override
|
||||
String get last_day => Crowdin.getText(localeName, 'last_day') ?? _fallbackTexts.last_day;
|
||||
@override
|
||||
String get last_day =>
|
||||
Crowdin.getText(localeName, 'last_day') ?? _fallbackTexts.last_day;
|
||||
|
||||
@override
|
||||
String get last_30_days => Crowdin.getText(localeName, 'last_30_days') ?? _fallbackTexts.last_30_days;
|
||||
@override
|
||||
String get last_30_days =>
|
||||
Crowdin.getText(localeName, 'last_30_days') ??
|
||||
_fallbackTexts.last_30_days;
|
||||
|
||||
@override
|
||||
String get last_365_days => Crowdin.getText(localeName, 'last_365_days') ?? _fallbackTexts.last_365_days;
|
||||
@override
|
||||
String get last_365_days =>
|
||||
Crowdin.getText(localeName, 'last_365_days') ??
|
||||
_fallbackTexts.last_365_days;
|
||||
|
||||
@override
|
||||
String get not_available => Crowdin.getText(localeName, 'not_available') ?? _fallbackTexts.not_available;
|
||||
@override
|
||||
String get not_available =>
|
||||
Crowdin.getText(localeName, 'not_available') ??
|
||||
_fallbackTexts.not_available;
|
||||
|
||||
@override
|
||||
String get download_failed => Crowdin.getText(localeName, 'download_failed') ?? _fallbackTexts.download_failed;
|
||||
@override
|
||||
String get download_failed =>
|
||||
Crowdin.getText(localeName, 'download_failed') ??
|
||||
_fallbackTexts.download_failed;
|
||||
|
||||
@override
|
||||
String get installation_failed => Crowdin.getText(localeName, 'installation_failed') ?? _fallbackTexts.installation_failed;
|
||||
@override
|
||||
String get installation_failed =>
|
||||
Crowdin.getText(localeName, 'installation_failed') ??
|
||||
_fallbackTexts.installation_failed;
|
||||
|
||||
@override
|
||||
String get uninstall_failed => Crowdin.getText(localeName, 'uninstall_failed') ?? _fallbackTexts.uninstall_failed;
|
||||
@override
|
||||
String get uninstall_failed =>
|
||||
Crowdin.getText(localeName, 'uninstall_failed') ??
|
||||
_fallbackTexts.uninstall_failed;
|
||||
|
||||
@override
|
||||
String get open_failed => Crowdin.getText(localeName, 'open_failed') ?? _fallbackTexts.open_failed;
|
||||
@override
|
||||
String get open_failed =>
|
||||
Crowdin.getText(localeName, 'open_failed') ?? _fallbackTexts.open_failed;
|
||||
|
||||
@override
|
||||
String get device => Crowdin.getText(localeName, 'device') ?? _fallbackTexts.device;
|
||||
@override
|
||||
String get device =>
|
||||
Crowdin.getText(localeName, 'device') ?? _fallbackTexts.device;
|
||||
|
||||
@override
|
||||
String get recently_updated => Crowdin.getText(localeName, 'recently_updated') ?? _fallbackTexts.recently_updated;
|
||||
@override
|
||||
String get recently_updated =>
|
||||
Crowdin.getText(localeName, 'recently_updated') ??
|
||||
_fallbackTexts.recently_updated;
|
||||
|
||||
@override
|
||||
String get refresh => Crowdin.getText(localeName, 'refresh') ?? _fallbackTexts.refresh;
|
||||
@override
|
||||
String get refresh =>
|
||||
Crowdin.getText(localeName, 'refresh') ?? _fallbackTexts.refresh;
|
||||
|
||||
@override
|
||||
String get about => Crowdin.getText(localeName, 'about') ?? _fallbackTexts.about;
|
||||
@override
|
||||
String get about =>
|
||||
Crowdin.getText(localeName, 'about') ?? _fallbackTexts.about;
|
||||
|
||||
@override
|
||||
String get refreshing_data => Crowdin.getText(localeName, 'refreshing_data') ?? _fallbackTexts.refreshing_data;
|
||||
@override
|
||||
String get refreshing_data =>
|
||||
Crowdin.getText(localeName, 'refreshing_data') ??
|
||||
_fallbackTexts.refreshing_data;
|
||||
|
||||
@override
|
||||
String get data_refreshed => Crowdin.getText(localeName, 'data_refreshed') ?? _fallbackTexts.data_refreshed;
|
||||
@override
|
||||
String get data_refreshed =>
|
||||
Crowdin.getText(localeName, 'data_refreshed') ??
|
||||
_fallbackTexts.data_refreshed;
|
||||
|
||||
@override
|
||||
String get refresh_failed => Crowdin.getText(localeName, 'refresh_failed') ?? _fallbackTexts.refresh_failed;
|
||||
@override
|
||||
String get refresh_failed =>
|
||||
Crowdin.getText(localeName, 'refresh_failed') ??
|
||||
_fallbackTexts.refresh_failed;
|
||||
|
||||
@override
|
||||
String get loading_latest_apps => Crowdin.getText(localeName, 'loading_latest_apps') ?? _fallbackTexts.loading_latest_apps;
|
||||
@override
|
||||
String get loading_latest_apps =>
|
||||
Crowdin.getText(localeName, 'loading_latest_apps') ??
|
||||
_fallbackTexts.loading_latest_apps;
|
||||
|
||||
@override
|
||||
String get latest_apps => Crowdin.getText(localeName, 'latest_apps') ?? _fallbackTexts.latest_apps;
|
||||
@override
|
||||
String get latest_apps =>
|
||||
Crowdin.getText(localeName, 'latest_apps') ?? _fallbackTexts.latest_apps;
|
||||
|
||||
@override
|
||||
String get no_apps_found => Crowdin.getText(localeName, 'no_apps_found') ?? _fallbackTexts.no_apps_found;
|
||||
@override
|
||||
String get no_apps_found =>
|
||||
Crowdin.getText(localeName, 'no_apps_found') ??
|
||||
_fallbackTexts.no_apps_found;
|
||||
|
||||
@override
|
||||
String get searching => Crowdin.getText(localeName, 'searching') ?? _fallbackTexts.searching;
|
||||
@override
|
||||
String get searching =>
|
||||
Crowdin.getText(localeName, 'searching') ?? _fallbackTexts.searching;
|
||||
|
||||
@override
|
||||
String get setup_failed => Crowdin.getText(localeName, 'setup_failed') ?? _fallbackTexts.setup_failed;
|
||||
@override
|
||||
String get setup_failed =>
|
||||
Crowdin.getText(localeName, 'setup_failed') ??
|
||||
_fallbackTexts.setup_failed;
|
||||
|
||||
@override
|
||||
@override
|
||||
String get back => Crowdin.getText(localeName, 'back') ?? _fallbackTexts.back;
|
||||
|
||||
@override
|
||||
String get allow => Crowdin.getText(localeName, 'allow') ?? _fallbackTexts.allow;
|
||||
@override
|
||||
String get allow =>
|
||||
Crowdin.getText(localeName, 'allow') ?? _fallbackTexts.allow;
|
||||
|
||||
@override
|
||||
String get manage_repositories => Crowdin.getText(localeName, 'manage_repositories') ?? _fallbackTexts.manage_repositories;
|
||||
@override
|
||||
String get manage_repositories =>
|
||||
Crowdin.getText(localeName, 'manage_repositories') ??
|
||||
_fallbackTexts.manage_repositories;
|
||||
|
||||
@override
|
||||
String get enable_disable => Crowdin.getText(localeName, 'enable_disable') ?? _fallbackTexts.enable_disable;
|
||||
@override
|
||||
String get enable_disable =>
|
||||
Crowdin.getText(localeName, 'enable_disable') ??
|
||||
_fallbackTexts.enable_disable;
|
||||
|
||||
@override
|
||||
@override
|
||||
String get edit => Crowdin.getText(localeName, 'edit') ?? _fallbackTexts.edit;
|
||||
|
||||
@override
|
||||
String get delete => Crowdin.getText(localeName, 'delete') ?? _fallbackTexts.delete;
|
||||
@override
|
||||
String get delete =>
|
||||
Crowdin.getText(localeName, 'delete') ?? _fallbackTexts.delete;
|
||||
|
||||
@override
|
||||
String get delete_repository => Crowdin.getText(localeName, 'delete_repository') ?? _fallbackTexts.delete_repository;
|
||||
@override
|
||||
String get delete_repository =>
|
||||
Crowdin.getText(localeName, 'delete_repository') ??
|
||||
_fallbackTexts.delete_repository;
|
||||
|
||||
@override
|
||||
String delete_repository_confirm(Object name, Object repo) => Crowdin.getText(localeName, 'delete_repository_confirm', {'name': name, 'repo': repo}) ?? _fallbackTexts.delete_repository_confirm(name, repo);
|
||||
@override
|
||||
String delete_repository_confirm(Object name, Object repo) =>
|
||||
Crowdin.getText(localeName, 'delete_repository_confirm', {
|
||||
'name': name,
|
||||
'repo': repo,
|
||||
}) ??
|
||||
_fallbackTexts.delete_repository_confirm(name, repo);
|
||||
|
||||
@override
|
||||
String get updating_repository => Crowdin.getText(localeName, 'updating_repository') ?? _fallbackTexts.updating_repository;
|
||||
@override
|
||||
String get updating_repository =>
|
||||
Crowdin.getText(localeName, 'updating_repository') ??
|
||||
_fallbackTexts.updating_repository;
|
||||
|
||||
@override
|
||||
String get touch_grass_message => Crowdin.getText(localeName, 'touch_grass_message') ?? _fallbackTexts.touch_grass_message;
|
||||
@override
|
||||
String get touch_grass_message =>
|
||||
Crowdin.getText(localeName, 'touch_grass_message') ??
|
||||
_fallbackTexts.touch_grass_message;
|
||||
|
||||
@override
|
||||
String get add_repository => Crowdin.getText(localeName, 'add_repository') ?? _fallbackTexts.add_repository;
|
||||
@override
|
||||
String get add_repository =>
|
||||
Crowdin.getText(localeName, 'add_repository') ??
|
||||
_fallbackTexts.add_repository;
|
||||
|
||||
@override
|
||||
@override
|
||||
String get add => Crowdin.getText(localeName, 'add') ?? _fallbackTexts.add;
|
||||
|
||||
@override
|
||||
@override
|
||||
String get save => Crowdin.getText(localeName, 'save') ?? _fallbackTexts.save;
|
||||
|
||||
@override
|
||||
String get enter_repository_name => Crowdin.getText(localeName, 'enter_repository_name') ?? _fallbackTexts.enter_repository_name;
|
||||
@override
|
||||
String get enter_repository_name =>
|
||||
Crowdin.getText(localeName, 'enter_repository_name') ??
|
||||
_fallbackTexts.enter_repository_name;
|
||||
|
||||
@override
|
||||
String get enter_repository_url => Crowdin.getText(localeName, 'enter_repository_url') ?? _fallbackTexts.enter_repository_url;
|
||||
@override
|
||||
String get enter_repository_url =>
|
||||
Crowdin.getText(localeName, 'enter_repository_url') ??
|
||||
_fallbackTexts.enter_repository_url;
|
||||
|
||||
@override
|
||||
String get edit_repository => Crowdin.getText(localeName, 'edit_repository') ?? _fallbackTexts.edit_repository;
|
||||
@override
|
||||
String get edit_repository =>
|
||||
Crowdin.getText(localeName, 'edit_repository') ??
|
||||
_fallbackTexts.edit_repository;
|
||||
|
||||
@override
|
||||
String get loading_apps => Crowdin.getText(localeName, 'loading_apps') ?? _fallbackTexts.loading_apps;
|
||||
@override
|
||||
String get loading_apps =>
|
||||
Crowdin.getText(localeName, 'loading_apps') ??
|
||||
_fallbackTexts.loading_apps;
|
||||
|
||||
@override
|
||||
String no_apps_in_category(Object category) => Crowdin.getText(localeName, 'no_apps_in_category', {'category':category}) ?? _fallbackTexts.no_apps_in_category(category);
|
||||
@override
|
||||
String no_apps_in_category(Object category) =>
|
||||
Crowdin.getText(localeName, 'no_apps_in_category', {
|
||||
'category': category,
|
||||
}) ??
|
||||
_fallbackTexts.no_apps_in_category(category);
|
||||
|
||||
@override
|
||||
String get loading_categories => Crowdin.getText(localeName, 'loading_categories') ?? _fallbackTexts.loading_categories;
|
||||
|
||||
@override
|
||||
String get no_categories_found => Crowdin.getText(localeName, 'no_categories_found') ?? _fallbackTexts.no_categories_found;
|
||||
@override
|
||||
String get loading_categories =>
|
||||
Crowdin.getText(localeName, 'loading_categories') ??
|
||||
_fallbackTexts.loading_categories;
|
||||
|
||||
@override
|
||||
String get no_categories_found =>
|
||||
Crowdin.getText(localeName, 'no_categories_found') ??
|
||||
_fallbackTexts.no_categories_found;
|
||||
}
|
||||
|
||||
class _CrowdinLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||
class _CrowdinLocalizationsDelegate
|
||||
extends LocalizationsDelegate<AppLocalizations> {
|
||||
const _CrowdinLocalizationsDelegate();
|
||||
|
||||
@override
|
||||
Future<AppLocalizations> load(Locale locale) =>
|
||||
AppLocalizations.delegate.load(locale)
|
||||
.then((fallback) => CrowdinLocalization(locale.toString(), fallback));
|
||||
Future<AppLocalizations> load(Locale locale) => AppLocalizations.delegate
|
||||
.load(locale)
|
||||
.then((fallback) => CrowdinLocalization(locale.toString(), fallback));
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => AppLocalizations.supportedLocales.contains(locale);
|
||||
bool isSupported(Locale locale) =>
|
||||
AppLocalizations.supportedLocales.contains(locale);
|
||||
|
||||
@override
|
||||
bool shouldReload(_CrowdinLocalizationsDelegate old) => false;
|
||||
|
||||
@@ -269,7 +269,7 @@ class _AppDetailsScreenState extends State<AppDetailsScreen> {
|
||||
if (availableRepos == null || availableRepos.isEmpty) return;
|
||||
|
||||
// Capture the mounted context before showing dialog
|
||||
final scaffoldMessenger = ScaffoldMessenger.of(context);
|
||||
// final scaffoldMessenger = ScaffoldMessenger.of(context);
|
||||
|
||||
await showModalBottomSheet(
|
||||
context: context,
|
||||
@@ -370,7 +370,7 @@ class _AppDetailsScreenState extends State<AppDetailsScreen> {
|
||||
return Scaffold(
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar.large(
|
||||
SliverAppBar(
|
||||
pinned: true,
|
||||
centerTitle: false,
|
||||
title: Row(
|
||||
@@ -428,6 +428,7 @@ class _AppDetailsScreenState extends State<AppDetailsScreen> {
|
||||
},
|
||||
),
|
||||
PopupMenuButton<String>(
|
||||
icon: const Icon(Symbols.more_vert),
|
||||
onSelected: (value) async {
|
||||
switch (value) {
|
||||
case 'website':
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:florid/l10n/app_localizations.dart';
|
||||
import 'package:florid/providers/app_provider.dart';
|
||||
import 'package:florid/providers/repositories_provider.dart';
|
||||
@@ -7,7 +6,7 @@ import 'package:florid/screens/home_screen.dart';
|
||||
import 'package:florid/utils/menu_actions.dart';
|
||||
import 'package:florid/widgets/f_tabbar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class LibraryScreen extends StatefulWidget {
|
||||
@@ -37,67 +36,73 @@ class _LibraryScreenState extends State<LibraryScreen>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(AppLocalizations.of(context)!.app_name),
|
||||
backgroundColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||
surfaceTintColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||
actions: [
|
||||
PopupMenuButton<String>(
|
||||
onSelected: (value) {
|
||||
switch (value) {
|
||||
case 'refresh':
|
||||
_refreshData();
|
||||
break;
|
||||
case 'settings':
|
||||
MenuActions.showSettings(context);
|
||||
break;
|
||||
case 'about':
|
||||
MenuActions.showAbout(context);
|
||||
break;
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
value: 'refresh',
|
||||
child: ListTile(
|
||||
leading: const Icon(Symbols.refresh),
|
||||
title: Text(AppLocalizations.of(context)!.refresh),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'settings',
|
||||
child: ListTile(
|
||||
leading: const Icon(Symbols.settings),
|
||||
title: Text(AppLocalizations.of(context)!.settings),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'about',
|
||||
child: ListTile(
|
||||
leading: Icon(Symbols.info),
|
||||
title: Text(AppLocalizations.of(context)!.about),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
title: Text(AppLocalizations.of(context)!.app_name),
|
||||
backgroundColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||
surfaceTintColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||
actions: [
|
||||
PopupMenuButton<String>(
|
||||
onSelected: (value) {
|
||||
switch (value) {
|
||||
case 'refresh':
|
||||
_refreshData();
|
||||
break;
|
||||
case 'settings':
|
||||
MenuActions.showSettings(context);
|
||||
break;
|
||||
case 'about':
|
||||
MenuActions.showAbout(context);
|
||||
break;
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
value: 'refresh',
|
||||
child: ListTile(
|
||||
leading: const Icon(Symbols.refresh),
|
||||
title: Text(AppLocalizations.of(context)!.refresh),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'settings',
|
||||
child: ListTile(
|
||||
leading: const Icon(Symbols.settings),
|
||||
title: Text(AppLocalizations.of(context)!.settings),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'about',
|
||||
child: ListTile(
|
||||
leading: Icon(Symbols.info),
|
||||
title: Text(AppLocalizations.of(context)!.about),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
bottom: FTabBar(
|
||||
controller: _tabController,
|
||||
onTabChanged: (index) {
|
||||
_tabController.animateTo(index);
|
||||
},
|
||||
items: [
|
||||
FloridTabBarItem(
|
||||
icon: Symbols.home,
|
||||
label: AppLocalizations.of(context)!.home,
|
||||
),
|
||||
FloridTabBarItem(
|
||||
icon: Symbols.category,
|
||||
label: AppLocalizations.of(context)!.categories,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
bottom: FTabBar(
|
||||
controller: _tabController,
|
||||
onTabChanged: (index) {
|
||||
_tabController.animateTo(index);
|
||||
},
|
||||
items: [
|
||||
FloridTabBarItem(icon: Symbols.home, label: AppLocalizations.of(context)!.home),
|
||||
FloridTabBarItem(icon: Symbols.category, label: AppLocalizations.of(context)!.categories),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
SliverFillRemaining(
|
||||
child: TabBarView(controller: _tabController, children: tabs),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:florid/l10n/app_localizations.dart';
|
||||
import 'package:florid/widgets/m_list.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
@@ -56,279 +57,308 @@ class _RepositoriesScreenState extends State<RepositoriesScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Manage Repositories')),
|
||||
body: Consumer<RepositoriesProvider>(
|
||||
builder: (context, provider, _) {
|
||||
if (provider.isLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar.medium(
|
||||
leading: BackButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateColor.resolveWith(
|
||||
(states) => Theme.of(context).colorScheme.surfaceContainer,
|
||||
),
|
||||
),
|
||||
),
|
||||
title: Text(AppLocalizations.of(context)!.manage_repositories),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Consumer<RepositoriesProvider>(
|
||||
builder: (context, provider, _) {
|
||||
if (provider.isLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 24.0),
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
// Error message if any
|
||||
if (provider.error != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Material(
|
||||
color: Colors.red.shade100,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Symbols.error, color: Colors.red.shade700),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
provider.error ?? 'Unknown error',
|
||||
style: TextStyle(color: Colors.red.shade700),
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 24.0),
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
// Error message if any
|
||||
if (provider.error != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Material(
|
||||
color: Colors.red.shade100,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Symbols.error,
|
||||
color: Colors.red.shade700,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
provider.error ?? 'Unknown error',
|
||||
style: TextStyle(
|
||||
color: Colors.red.shade700,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.close),
|
||||
onPressed: provider.clearError,
|
||||
color: Colors.red.shade700,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.close),
|
||||
onPressed: provider.clearError,
|
||||
color: Colors.red.shade700,
|
||||
),
|
||||
),
|
||||
// Presets section
|
||||
if (_presets.isNotEmpty)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 4.0,
|
||||
children: [
|
||||
MListHeader(title: 'Preset'),
|
||||
MListViewBuilder(
|
||||
itemCount: _presets.length,
|
||||
itemBuilder: (index) {
|
||||
final preset = _presets[index];
|
||||
final isAdded = provider.repositories.any(
|
||||
(repo) => repo.url == preset['url'],
|
||||
);
|
||||
|
||||
return MListItemData(
|
||||
title: preset['name']!,
|
||||
subtitle: preset['description']!,
|
||||
onTap: () {},
|
||||
suffix: Switch(
|
||||
value: isAdded,
|
||||
onChanged: (newValue) async {
|
||||
if (newValue) {
|
||||
// Add the preset
|
||||
final repoProvider = context
|
||||
.read<RepositoriesProvider>();
|
||||
await repoProvider.addRepository(
|
||||
preset['name']!,
|
||||
preset['url']!,
|
||||
);
|
||||
// Only proceed with modal and refresh if addition succeeded (no error)
|
||||
if (repoProvider.error == null &&
|
||||
context.mounted) {
|
||||
await _runRepositoryActionWithDialog(
|
||||
context,
|
||||
() async {
|
||||
final apiService = context
|
||||
.read<FDroidApiService>();
|
||||
final appProvider = context
|
||||
.read<AppProvider>();
|
||||
|
||||
await apiService
|
||||
.clearRepositoryCache();
|
||||
await appProvider.refreshAll(
|
||||
repositoriesProvider:
|
||||
repoProvider,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Remove the preset
|
||||
Repository? addedRepo;
|
||||
try {
|
||||
addedRepo = provider.repositories
|
||||
.firstWhere(
|
||||
(repo) =>
|
||||
repo.url == preset['url'],
|
||||
);
|
||||
} catch (e) {
|
||||
addedRepo = null;
|
||||
}
|
||||
if (addedRepo != null) {
|
||||
final repoProvider = context
|
||||
.read<RepositoriesProvider>();
|
||||
repoProvider.deleteRepository(
|
||||
addedRepo.id,
|
||||
);
|
||||
// Only proceed with modal and refresh if deletion succeeded (no error)
|
||||
if (repoProvider.error == null &&
|
||||
context.mounted) {
|
||||
await _runRepositoryActionWithDialog(
|
||||
context,
|
||||
() async {
|
||||
final apiService = context
|
||||
.read<FDroidApiService>();
|
||||
final appProvider = context
|
||||
.read<AppProvider>();
|
||||
|
||||
await apiService
|
||||
.clearRepositoryCache();
|
||||
await appProvider.refreshAll(
|
||||
repositoriesProvider:
|
||||
repoProvider,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Presets section
|
||||
if (_presets.isNotEmpty)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 4.0,
|
||||
children: [
|
||||
MListHeader(title: 'Preset'),
|
||||
MListViewBuilder(
|
||||
itemCount: _presets.length,
|
||||
itemBuilder: (index) {
|
||||
final preset = _presets[index];
|
||||
final isAdded = provider.repositories.any(
|
||||
(repo) => repo.url == preset['url'],
|
||||
);
|
||||
|
||||
return MListItemData(
|
||||
title: preset['name']!,
|
||||
subtitle: preset['description']!,
|
||||
onTap: () {},
|
||||
suffix: Switch(
|
||||
value: isAdded,
|
||||
onChanged: (newValue) async {
|
||||
if (newValue) {
|
||||
// Add the preset
|
||||
final repoProvider = context
|
||||
.read<RepositoriesProvider>();
|
||||
await repoProvider.addRepository(
|
||||
preset['name']!,
|
||||
preset['url']!,
|
||||
);
|
||||
// Only proceed with modal and refresh if addition succeeded (no error)
|
||||
if (repoProvider.error == null &&
|
||||
context.mounted) {
|
||||
await _runRepositoryActionWithDialog(
|
||||
context,
|
||||
() async {
|
||||
final apiService = context
|
||||
.read<FDroidApiService>();
|
||||
final appProvider = context
|
||||
.read<AppProvider>();
|
||||
|
||||
await apiService.clearRepositoryCache();
|
||||
await appProvider.refreshAll(
|
||||
repositoriesProvider: repoProvider,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Remove the preset
|
||||
Repository? addedRepo;
|
||||
try {
|
||||
addedRepo = provider.repositories
|
||||
.firstWhere(
|
||||
(repo) => repo.url == preset['url'],
|
||||
);
|
||||
} catch (e) {
|
||||
addedRepo = null;
|
||||
}
|
||||
if (addedRepo != null) {
|
||||
final repoProvider = context
|
||||
.read<RepositoriesProvider>();
|
||||
repoProvider.deleteRepository(addedRepo.id);
|
||||
// Only proceed with modal and refresh if deletion succeeded (no error)
|
||||
if (repoProvider.error == null &&
|
||||
context.mounted) {
|
||||
await _runRepositoryActionWithDialog(
|
||||
context,
|
||||
() async {
|
||||
final apiService = context
|
||||
.read<FDroidApiService>();
|
||||
final appProvider = context
|
||||
.read<AppProvider>();
|
||||
|
||||
await apiService
|
||||
.clearRepositoryCache();
|
||||
await appProvider.refreshAll(
|
||||
repositoriesProvider: repoProvider,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
// Custom Repositories list
|
||||
Column(
|
||||
spacing: 4.0,
|
||||
children: [
|
||||
MListHeader(title: 'Your Repositories'),
|
||||
provider.repositories
|
||||
.where(
|
||||
(repo) => !_presets.any(
|
||||
(preset) => preset['url'] == repo.url,
|
||||
),
|
||||
)
|
||||
.toList()
|
||||
.isEmpty
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Symbols.inbox,
|
||||
size: 64,
|
||||
color: Colors.grey.shade400,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'No custom repositories added',
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Add a custom F-Droid repository to get started',
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: MListViewBuilder(
|
||||
itemCount: provider.repositories
|
||||
.where(
|
||||
(repo) => !_presets.any(
|
||||
(preset) => preset['url'] == repo.url,
|
||||
),
|
||||
)
|
||||
.length,
|
||||
itemBuilder: (index) {
|
||||
final customRepos = provider.repositories
|
||||
// Custom Repositories list
|
||||
Column(
|
||||
spacing: 4.0,
|
||||
children: [
|
||||
MListHeader(title: 'Your Repositories'),
|
||||
provider.repositories
|
||||
.where(
|
||||
(repo) => !_presets.any(
|
||||
(preset) => preset['url'] == repo.url,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
final repo = customRepos[index];
|
||||
return MListItemData(
|
||||
title: repo.name,
|
||||
subtitle: repo.url,
|
||||
suffix: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Switch(
|
||||
value: repo.isEnabled,
|
||||
onChanged: (_) async {
|
||||
await _toggleRepositoryWithDialog(
|
||||
.toList()
|
||||
.isEmpty
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Symbols.inbox,
|
||||
size: 64,
|
||||
color: Colors.grey.shade400,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'No custom repositories added',
|
||||
style: Theme.of(
|
||||
context,
|
||||
provider,
|
||||
repo.id,
|
||||
);
|
||||
},
|
||||
),
|
||||
PopupMenuButton<String>(
|
||||
onSelected: (value) async {
|
||||
switch (value) {
|
||||
case 'edit':
|
||||
_RepositoryListItem(
|
||||
repository: repo,
|
||||
)._showEditRepositoryDialog(
|
||||
context,
|
||||
repo,
|
||||
);
|
||||
break;
|
||||
case 'delete':
|
||||
_RepositoryListItem(
|
||||
repository: repo,
|
||||
)._showDeleteConfirmation(
|
||||
context,
|
||||
repo,
|
||||
provider,
|
||||
);
|
||||
break;
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
value: 'edit',
|
||||
child: Row(
|
||||
spacing: 16.0,
|
||||
children: [
|
||||
Icon(Symbols.edit_rounded),
|
||||
Text('Edit'),
|
||||
],
|
||||
),
|
||||
).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Add a custom F-Droid repository to get started',
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.bodySmall,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: MListViewBuilder(
|
||||
itemCount: provider.repositories
|
||||
.where(
|
||||
(repo) => !_presets.any(
|
||||
(preset) => preset['url'] == repo.url,
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: Row(
|
||||
spacing: 16.0,
|
||||
children: [
|
||||
Icon(
|
||||
Symbols.delete_rounded,
|
||||
fill: 1,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.error,
|
||||
),
|
||||
Text(
|
||||
'Delete',
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
)
|
||||
.length,
|
||||
itemBuilder: (index) {
|
||||
final customRepos = provider.repositories
|
||||
.where(
|
||||
(repo) => !_presets.any(
|
||||
(preset) =>
|
||||
preset['url'] == repo.url,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
final repo = customRepos[index];
|
||||
return MListItemData(
|
||||
title: repo.name,
|
||||
subtitle: repo.url,
|
||||
suffix: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Switch(
|
||||
value: repo.isEnabled,
|
||||
onChanged: (_) async {
|
||||
await _toggleRepositoryWithDialog(
|
||||
context,
|
||||
provider,
|
||||
repo.id,
|
||||
);
|
||||
},
|
||||
),
|
||||
PopupMenuButton<String>(
|
||||
onSelected: (value) async {
|
||||
switch (value) {
|
||||
case 'edit':
|
||||
_RepositoryListItem(
|
||||
repository: repo,
|
||||
)._showEditRepositoryDialog(
|
||||
context,
|
||||
).colorScheme.error,
|
||||
repo,
|
||||
);
|
||||
break;
|
||||
case 'delete':
|
||||
_RepositoryListItem(
|
||||
repository: repo,
|
||||
)._showDeleteConfirmation(
|
||||
context,
|
||||
repo,
|
||||
provider,
|
||||
);
|
||||
break;
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
value: 'edit',
|
||||
child: Row(
|
||||
spacing: 16.0,
|
||||
children: [
|
||||
Icon(Symbols.edit_rounded),
|
||||
Text('Edit'),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: Row(
|
||||
spacing: 16.0,
|
||||
children: [
|
||||
Icon(
|
||||
Symbols.delete_rounded,
|
||||
fill: 1,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.error,
|
||||
),
|
||||
Text(
|
||||
'Delete',
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.error,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
onTap: () {},
|
||||
);
|
||||
},
|
||||
),
|
||||
onTap: () {},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () => _showAddRepositoryDialog(context),
|
||||
|
||||
+259
-255
@@ -75,267 +75,271 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
return Consumer<SettingsProvider>(
|
||||
builder: (context, settings, _) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(AppLocalizations.of(context)!.settings)),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 16,
|
||||
children: [
|
||||
Column(
|
||||
spacing: 4,
|
||||
children: [
|
||||
MListHeader(title: 'Theme Mode'),
|
||||
MRadioListView(
|
||||
items: [
|
||||
MRadioListItemData<ThemeMode>(
|
||||
title: 'Follow system theme',
|
||||
subtitle: '',
|
||||
value: ThemeMode.system,
|
||||
),
|
||||
MRadioListItemData<ThemeMode>(
|
||||
title: 'Light theme',
|
||||
subtitle: '',
|
||||
value: ThemeMode.light,
|
||||
),
|
||||
MRadioListItemData<ThemeMode>(
|
||||
title: 'Dark theme',
|
||||
subtitle: '',
|
||||
value: ThemeMode.dark,
|
||||
),
|
||||
],
|
||||
groupValue: settings.themeMode,
|
||||
onChanged: (mode) {
|
||||
settings.setThemeMode(mode);
|
||||
},
|
||||
),
|
||||
MListHeader(title: 'Theme Style'),
|
||||
MRadioListView(
|
||||
items: [
|
||||
MRadioListItemData<ThemeStyle>(
|
||||
title: 'Material style',
|
||||
subtitle: '',
|
||||
value: ThemeStyle.material,
|
||||
),
|
||||
MRadioListItemData<ThemeStyle>(
|
||||
title: 'Florid style',
|
||||
subtitle: '',
|
||||
suffix: Container(
|
||||
margin: const EdgeInsets.only(right: 8.0),
|
||||
child: Material(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
borderRadius: BorderRadius.circular(99.0),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 2.0,
|
||||
),
|
||||
child: Text(
|
||||
'Beta',
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSecondary,
|
||||
),
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar.medium(
|
||||
title: Text(AppLocalizations.of(context)!.settings),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Column(
|
||||
spacing: 4,
|
||||
children: [
|
||||
MListHeader(title: 'Theme Mode'),
|
||||
MRadioListView(
|
||||
items: [
|
||||
MRadioListItemData<ThemeMode>(
|
||||
title: 'Follow system theme',
|
||||
subtitle: '',
|
||||
value: ThemeMode.system,
|
||||
),
|
||||
MRadioListItemData<ThemeMode>(
|
||||
title: 'Light theme',
|
||||
subtitle: '',
|
||||
value: ThemeMode.light,
|
||||
),
|
||||
MRadioListItemData<ThemeMode>(
|
||||
title: 'Dark theme',
|
||||
subtitle: '',
|
||||
value: ThemeMode.dark,
|
||||
),
|
||||
],
|
||||
groupValue: settings.themeMode,
|
||||
onChanged: (mode) {
|
||||
settings.setThemeMode(mode);
|
||||
},
|
||||
),
|
||||
MListHeader(title: 'Theme Style'),
|
||||
MRadioListView(
|
||||
items: [
|
||||
MRadioListItemData<ThemeStyle>(
|
||||
title: 'Material style',
|
||||
subtitle: '',
|
||||
value: ThemeStyle.material,
|
||||
),
|
||||
MRadioListItemData<ThemeStyle>(
|
||||
title: 'Florid style',
|
||||
subtitle: '',
|
||||
suffix: Container(
|
||||
margin: const EdgeInsets.only(right: 8.0),
|
||||
child: Material(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
borderRadius: BorderRadius.circular(99.0),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 2.0,
|
||||
),
|
||||
child: Text(
|
||||
'Beta',
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSecondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
value: ThemeStyle.florid,
|
||||
),
|
||||
],
|
||||
groupValue: settings.themeStyle,
|
||||
onChanged: (style) {
|
||||
settings.setThemeStyle(style);
|
||||
},
|
||||
),
|
||||
MListView(
|
||||
items: [
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.feedback),
|
||||
title: 'Fedback on Florid theme',
|
||||
subtitle:
|
||||
'Help improve the Florid theme by providing feedback',
|
||||
onTap: () {
|
||||
launchUrl(
|
||||
Uri.parse(
|
||||
'https://github.com/Nandanrmenon/florid/discussions/5',
|
||||
),
|
||||
);
|
||||
},
|
||||
suffix: Icon(Symbols.open_in_new),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 4,
|
||||
children: [
|
||||
MListHeader(title: 'General Settings'),
|
||||
MListView(
|
||||
items: [
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.language),
|
||||
title: 'App content language',
|
||||
onTap: () => _showLanguageDialog(context, settings),
|
||||
subtitle: SettingsProvider.getLocaleDisplayName(
|
||||
settings.locale,
|
||||
),
|
||||
suffix: Icon(Symbols.chevron_right),
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.cloud),
|
||||
title: 'Manage repositories',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
const RepositoriesScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
subtitle: 'Add or remove F-Droid repositories',
|
||||
suffix: Icon(Symbols.chevron_right),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Column(
|
||||
spacing: 4,
|
||||
children: [
|
||||
MListHeader(title: 'Downloads & Storage'),
|
||||
MListView(
|
||||
items: [
|
||||
MListItemData(
|
||||
title: 'Auto-install after download',
|
||||
onTap: () {
|
||||
settings.setAutoInstallApk(
|
||||
!settings.autoInstallApk,
|
||||
);
|
||||
},
|
||||
subtitle:
|
||||
'Install APKs automatically once download finishes',
|
||||
suffix: Switch(
|
||||
value: settings.autoInstallApk,
|
||||
onChanged: (value) {
|
||||
settings.setAutoInstallApk(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
MListItemData(
|
||||
title: 'Delete APK after install',
|
||||
onTap: () {
|
||||
settings.setAutoInstallApk(
|
||||
!settings.autoInstallApk,
|
||||
);
|
||||
},
|
||||
subtitle:
|
||||
'Remove installer files after successful installation',
|
||||
suffix: Switch(
|
||||
value: settings.autoDeleteApk,
|
||||
onChanged: (value) {
|
||||
settings.setAutoDeleteApk(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
MListView(
|
||||
items: [
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.cleaning_services),
|
||||
title: 'Clear repository cache',
|
||||
onTap: () {
|
||||
_clearRepoCache(context);
|
||||
},
|
||||
subtitle:
|
||||
'Refresh app list and metadata on next load',
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.delete_sweep),
|
||||
title: 'Clear APK downloads',
|
||||
onTap: () {
|
||||
_clearRepoCache(context);
|
||||
},
|
||||
subtitle:
|
||||
'Remove downloaded installer files from storage',
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.image_not_supported),
|
||||
title: 'Clear image cache',
|
||||
onTap: () {
|
||||
_clearRepoCache(context);
|
||||
},
|
||||
subtitle: 'Remove cached icons and screenshots',
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Column(
|
||||
spacing: 4,
|
||||
children: [
|
||||
MListHeader(title: 'About'),
|
||||
MListView(
|
||||
items: [
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.info),
|
||||
title: 'Version',
|
||||
subtitle: _appVersion.isEmpty
|
||||
? 'Loading…'
|
||||
: _appVersion,
|
||||
onTap: () {},
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.code_rounded),
|
||||
title: 'Source code',
|
||||
onTap: () async {
|
||||
final url = Uri.parse(
|
||||
'https://github.com/Nandanrmenon/florid',
|
||||
);
|
||||
if (await canLaunchUrl(url)) {
|
||||
await launchUrl(url);
|
||||
}
|
||||
},
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.bug_report_rounded),
|
||||
title: 'Report an issue',
|
||||
onTap: () async {
|
||||
final url = Uri.parse(
|
||||
'https://github.com/Nandanrmenon/florid/issues/new?template=bug_report.md',
|
||||
);
|
||||
if (await canLaunchUrl(url)) {
|
||||
await launchUrl(url);
|
||||
}
|
||||
},
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.share),
|
||||
title: 'Share Florid',
|
||||
onTap: () {
|
||||
SharePlus.instance.share(
|
||||
ShareParams(
|
||||
title: 'Check out Florid!',
|
||||
text:
|
||||
'A modern F-Droid client! https://github.com/Nandanrmenon/florid',
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
value: ThemeStyle.florid,
|
||||
),
|
||||
],
|
||||
groupValue: settings.themeStyle,
|
||||
onChanged: (style) {
|
||||
settings.setThemeStyle(style);
|
||||
},
|
||||
),
|
||||
MListView(
|
||||
items: [
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.feedback),
|
||||
title: 'Fedback on Florid theme',
|
||||
subtitle:
|
||||
'Help improve the Florid theme by providing feedback',
|
||||
onTap: () {
|
||||
launchUrl(
|
||||
Uri.parse(
|
||||
'https://github.com/Nandanrmenon/florid/discussions/5',
|
||||
),
|
||||
);
|
||||
},
|
||||
suffix: Icon(Symbols.open_in_new),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Column(
|
||||
spacing: 4,
|
||||
children: [
|
||||
MListHeader(title: 'General Settings'),
|
||||
MListView(
|
||||
items: [
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.language),
|
||||
title: 'App content language',
|
||||
onTap: () => _showLanguageDialog(context, settings),
|
||||
subtitle: SettingsProvider.getLocaleDisplayName(
|
||||
settings.locale,
|
||||
),
|
||||
suffix: Icon(Symbols.chevron_right),
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.cloud),
|
||||
title: 'Manage repositories',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
const RepositoriesScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
subtitle: 'Add or remove F-Droid repositories',
|
||||
suffix: Icon(Symbols.chevron_right),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SliverToBoxAdapter(
|
||||
child: Column(
|
||||
spacing: 4,
|
||||
children: [
|
||||
MListHeader(title: 'Downloads & Storage'),
|
||||
MListView(
|
||||
items: [
|
||||
MListItemData(
|
||||
title: 'Auto-install after download',
|
||||
onTap: () {
|
||||
settings.setAutoInstallApk(
|
||||
!settings.autoInstallApk,
|
||||
);
|
||||
},
|
||||
subtitle:
|
||||
'Install APKs automatically once download finishes',
|
||||
suffix: Switch(
|
||||
value: settings.autoInstallApk,
|
||||
onChanged: (value) {
|
||||
settings.setAutoInstallApk(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
MListItemData(
|
||||
title: 'Delete APK after install',
|
||||
onTap: () {
|
||||
settings.setAutoInstallApk(
|
||||
!settings.autoInstallApk,
|
||||
);
|
||||
},
|
||||
subtitle:
|
||||
'Remove installer files after successful installation',
|
||||
suffix: Switch(
|
||||
value: settings.autoDeleteApk,
|
||||
onChanged: (value) {
|
||||
settings.setAutoDeleteApk(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
MListView(
|
||||
items: [
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.cleaning_services),
|
||||
title: 'Clear repository cache',
|
||||
onTap: () {
|
||||
_clearRepoCache(context);
|
||||
},
|
||||
subtitle:
|
||||
'Refresh app list and metadata on next load',
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.delete_sweep),
|
||||
title: 'Clear APK downloads',
|
||||
onTap: () {
|
||||
_clearRepoCache(context);
|
||||
},
|
||||
subtitle:
|
||||
'Remove downloaded installer files from storage',
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.image_not_supported),
|
||||
title: 'Clear image cache',
|
||||
onTap: () {
|
||||
_clearRepoCache(context);
|
||||
},
|
||||
subtitle: 'Remove cached icons and screenshots',
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SliverToBoxAdapter(
|
||||
child: Column(
|
||||
spacing: 4,
|
||||
children: [
|
||||
MListHeader(title: 'About'),
|
||||
MListView(
|
||||
items: [
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.info),
|
||||
title: 'Version',
|
||||
subtitle: _appVersion.isEmpty
|
||||
? 'Loading…'
|
||||
: _appVersion,
|
||||
onTap: () {},
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.code_rounded),
|
||||
title: 'Source code',
|
||||
onTap: () async {
|
||||
final url = Uri.parse(
|
||||
'https://github.com/Nandanrmenon/florid',
|
||||
);
|
||||
if (await canLaunchUrl(url)) {
|
||||
await launchUrl(url);
|
||||
}
|
||||
},
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.bug_report_rounded),
|
||||
title: 'Report an issue',
|
||||
onTap: () async {
|
||||
final url = Uri.parse(
|
||||
'https://github.com/Nandanrmenon/florid/issues/new?template=bug_report.md',
|
||||
);
|
||||
if (await canLaunchUrl(url)) {
|
||||
await launchUrl(url);
|
||||
}
|
||||
},
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(Symbols.share),
|
||||
title: 'Share Florid',
|
||||
onTap: () {
|
||||
SharePlus.instance.share(
|
||||
ShareParams(
|
||||
title: 'Check out Florid!',
|
||||
text:
|
||||
'A modern F-Droid client! https://github.com/Nandanrmenon/florid',
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(child: const SizedBox(height: 32)),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:florid/constants.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
class AppThemes {
|
||||
// Material Theme (Original)
|
||||
@@ -91,6 +92,15 @@ class AppThemes {
|
||||
brightness: Brightness.light,
|
||||
).onSurface,
|
||||
),
|
||||
backgroundColor: ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.light,
|
||||
).surface,
|
||||
surfaceTintColor: ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.light,
|
||||
).surfaceContainerHigh,
|
||||
elevation: 0,
|
||||
),
|
||||
floatingActionButtonTheme: FloatingActionButtonThemeData(
|
||||
elevation: 0,
|
||||
@@ -140,7 +150,29 @@ class AppThemes {
|
||||
),
|
||||
),
|
||||
),
|
||||
iconButtonTheme: IconButtonThemeData(
|
||||
style: IconButton.styleFrom(
|
||||
backgroundColor: ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.light,
|
||||
).surfaceContainerLow,
|
||||
),
|
||||
),
|
||||
switchTheme: SwitchThemeData(
|
||||
thumbIcon: WidgetStateProperty.resolveWith<Icon?>((
|
||||
Set<WidgetState> states,
|
||||
) {
|
||||
if (states.contains(WidgetState.selected)) {
|
||||
return Icon(
|
||||
Symbols.check,
|
||||
color: ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.light,
|
||||
).onPrimary,
|
||||
);
|
||||
}
|
||||
return const Icon(Symbols.close);
|
||||
}),
|
||||
thumbColor: WidgetStateProperty.resolveWith<Color?>((
|
||||
Set<WidgetState> states,
|
||||
) {
|
||||
@@ -148,7 +180,7 @@ class AppThemes {
|
||||
return ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.light,
|
||||
).primaryContainer;
|
||||
).primary;
|
||||
}
|
||||
return null; // Use the default thumb color
|
||||
}),
|
||||
@@ -159,14 +191,26 @@ class AppThemes {
|
||||
return ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.light,
|
||||
).secondary;
|
||||
).surface;
|
||||
}
|
||||
return null; // Use the default track color
|
||||
// Change the default track color to a custom color
|
||||
return ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.light,
|
||||
).surfaceContainerLowest;
|
||||
}),
|
||||
trackOutlineWidth: WidgetStateProperty.resolveWith<double?>((
|
||||
Set<WidgetState> states,
|
||||
) {
|
||||
return 1;
|
||||
return 2;
|
||||
}),
|
||||
trackOutlineColor: WidgetStateProperty.resolveWith<Color?>((
|
||||
Set<WidgetState> states,
|
||||
) {
|
||||
return ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.light,
|
||||
).surfaceContainerHighest;
|
||||
}),
|
||||
),
|
||||
navigationBarTheme: NavigationBarThemeData(
|
||||
@@ -283,6 +327,14 @@ class AppThemes {
|
||||
brightness: Brightness.dark,
|
||||
).onSurface,
|
||||
),
|
||||
backgroundColor: ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.dark,
|
||||
).surface,
|
||||
surfaceTintColor: ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.dark,
|
||||
).surfaceContainerHigh,
|
||||
),
|
||||
floatingActionButtonTheme: FloatingActionButtonThemeData(
|
||||
elevation: 0,
|
||||
@@ -336,6 +388,14 @@ class AppThemes {
|
||||
),
|
||||
),
|
||||
switchTheme: SwitchThemeData(
|
||||
thumbIcon: WidgetStateProperty.resolveWith<Icon?>((
|
||||
Set<WidgetState> states,
|
||||
) {
|
||||
if (states.contains(WidgetState.selected)) {
|
||||
return const Icon(Symbols.check);
|
||||
}
|
||||
return const Icon(Symbols.close);
|
||||
}),
|
||||
thumbColor: WidgetStateProperty.resolveWith<Color?>((
|
||||
Set<WidgetState> states,
|
||||
) {
|
||||
@@ -354,14 +414,25 @@ class AppThemes {
|
||||
return ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.dark,
|
||||
).secondary;
|
||||
).surface;
|
||||
}
|
||||
return null; // Use the default track color
|
||||
return ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.dark,
|
||||
).surfaceContainerLowest;
|
||||
}),
|
||||
trackOutlineWidth: WidgetStateProperty.resolveWith<double?>((
|
||||
Set<WidgetState> states,
|
||||
) {
|
||||
return 1;
|
||||
return 2;
|
||||
}),
|
||||
trackOutlineColor: WidgetStateProperty.resolveWith<Color?>((
|
||||
Set<WidgetState> states,
|
||||
) {
|
||||
return ColorScheme.fromSeed(
|
||||
seedColor: kAppColor,
|
||||
brightness: Brightness.dark,
|
||||
).surfaceContainerHighest;
|
||||
}),
|
||||
),
|
||||
navigationBarTheme: NavigationBarThemeData(
|
||||
|
||||
Reference in New Issue
Block a user