mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-11-03 23:03:29 +01:00 
			
		
		
		
	Merge pull request #402 from ImranR98/dev
Added "Group by Category" setting
This commit is contained in:
		@@ -220,6 +220,7 @@
 | 
				
			|||||||
    "importFromURLsInFile": "Importieren von URLs aus Datei ( z.B. OPML)",
 | 
					    "importFromURLsInFile": "Importieren von URLs aus Datei ( z.B. OPML)",
 | 
				
			||||||
    "versionDetection": "Versionserkennung",
 | 
					    "versionDetection": "Versionserkennung",
 | 
				
			||||||
    "standardVersionDetection": "Standardversionserkennung",
 | 
					    "standardVersionDetection": "Standardversionserkennung",
 | 
				
			||||||
 | 
					    "groupByCategory": "Group by Category",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "App entfernen?",
 | 
					        "one": "App entfernen?",
 | 
				
			||||||
        "other": "App entfernen?"
 | 
					        "other": "App entfernen?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -220,6 +220,7 @@
 | 
				
			|||||||
    "importFromURLsInFile": "Import from URLs in File (like OPML)",
 | 
					    "importFromURLsInFile": "Import from URLs in File (like OPML)",
 | 
				
			||||||
    "versionDetection": "Version Detection",
 | 
					    "versionDetection": "Version Detection",
 | 
				
			||||||
    "standardVersionDetection": "Standard version detection",
 | 
					    "standardVersionDetection": "Standard version detection",
 | 
				
			||||||
 | 
					    "groupByCategory": "Group by Category",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Remove App?",
 | 
					        "one": "Remove App?",
 | 
				
			||||||
        "other": "Remove Apps?"
 | 
					        "other": "Remove Apps?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -220,6 +220,7 @@
 | 
				
			|||||||
    "importFromURLsInFile": "وارد کردن از آدرس های اینترنتی موجود در فایل (مانند OPML)",
 | 
					    "importFromURLsInFile": "وارد کردن از آدرس های اینترنتی موجود در فایل (مانند OPML)",
 | 
				
			||||||
    "versionDetection": "تشخیص نسخه",
 | 
					    "versionDetection": "تشخیص نسخه",
 | 
				
			||||||
    "standardVersionDetection": "تشخیص نسخه استاندارد",
 | 
					    "standardVersionDetection": "تشخیص نسخه استاندارد",
 | 
				
			||||||
 | 
					    "groupByCategory": "Group by Category",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "برنامه حذف شود؟",
 | 
					        "one": "برنامه حذف شود؟",
 | 
				
			||||||
        "other": "برنامه ها حذف شوند؟"
 | 
					        "other": "برنامه ها حذف شوند؟"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -220,6 +220,7 @@
 | 
				
			|||||||
    "importFromURLsInFile": "Importer à partir d'URL dans un fichier (comme OPML)",
 | 
					    "importFromURLsInFile": "Importer à partir d'URL dans un fichier (comme OPML)",
 | 
				
			||||||
    "versionDetection": "Détection des versions",
 | 
					    "versionDetection": "Détection des versions",
 | 
				
			||||||
    "standardVersionDetection": "Détection de version standard",
 | 
					    "standardVersionDetection": "Détection de version standard",
 | 
				
			||||||
 | 
					    "groupByCategory": "Group by Category",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Supprimer l'application ?",
 | 
					        "one": "Supprimer l'application ?",
 | 
				
			||||||
        "other": "Supprimer les applications ?"
 | 
					        "other": "Supprimer les applications ?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -219,6 +219,7 @@
 | 
				
			|||||||
    "importFromURLsInFile": "Importálás fájlban található URL-ből (mint pl. OPML)",
 | 
					    "importFromURLsInFile": "Importálás fájlban található URL-ből (mint pl. OPML)",
 | 
				
			||||||
    "versionDetection": "Verzió érzékelés",
 | 
					    "versionDetection": "Verzió érzékelés",
 | 
				
			||||||
    "standardVersionDetection": "Alapért. verzió érzékelés",
 | 
					    "standardVersionDetection": "Alapért. verzió érzékelés",
 | 
				
			||||||
 | 
					    "groupByCategory": "Group by Category",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Eltávolítja az alkalmazást?",
 | 
					        "one": "Eltávolítja az alkalmazást?",
 | 
				
			||||||
        "other": "Eltávolítja az alkalmazást?"
 | 
					        "other": "Eltávolítja az alkalmazást?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -220,6 +220,7 @@
 | 
				
			|||||||
    "importFromURLsInFile": "Importa da URL in file (come OPML)",
 | 
					    "importFromURLsInFile": "Importa da URL in file (come OPML)",
 | 
				
			||||||
    "versionDetection": "Rilevamento di versione",
 | 
					    "versionDetection": "Rilevamento di versione",
 | 
				
			||||||
    "standardVersionDetection": "Rilevamento di versione standard",
 | 
					    "standardVersionDetection": "Rilevamento di versione standard",
 | 
				
			||||||
 | 
					    "groupByCategory": "Group by Category",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Rimuovere l'App?",
 | 
					        "one": "Rimuovere l'App?",
 | 
				
			||||||
        "other": "Rimuovere le App?"
 | 
					        "other": "Rimuovere le App?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -220,6 +220,7 @@
 | 
				
			|||||||
    "importFromURLsInFile": "ファイル(OPMLなど)内のURLからインポート",
 | 
					    "importFromURLsInFile": "ファイル(OPMLなど)内のURLからインポート",
 | 
				
			||||||
    "versionDetection": "バージョン検出",
 | 
					    "versionDetection": "バージョン検出",
 | 
				
			||||||
    "standardVersionDetection": "標準のバージョン検出",
 | 
					    "standardVersionDetection": "標準のバージョン検出",
 | 
				
			||||||
 | 
					    "groupByCategory": "Group by Category",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "アプリを削除しますか?",
 | 
					        "one": "アプリを削除しますか?",
 | 
				
			||||||
        "other": "アプリを削除しますか?"
 | 
					        "other": "アプリを削除しますか?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -220,6 +220,7 @@
 | 
				
			|||||||
    "importFromURLsInFile": "Import from URLs in File (like OPML)",
 | 
					    "importFromURLsInFile": "Import from URLs in File (like OPML)",
 | 
				
			||||||
    "versionDetection": "Version Detection",
 | 
					    "versionDetection": "Version Detection",
 | 
				
			||||||
    "standardVersionDetection": "Standard version detection",
 | 
					    "standardVersionDetection": "Standard version detection",
 | 
				
			||||||
 | 
					    "groupByCategory": "Group by Category",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "删除应用?",
 | 
					        "one": "删除应用?",
 | 
				
			||||||
        "other": "删除应用?"
 | 
					        "other": "删除应用?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart';
 | 
				
			|||||||
// ignore: implementation_imports
 | 
					// ignore: implementation_imports
 | 
				
			||||||
import 'package:easy_localization/src/localization.dart';
 | 
					import 'package:easy_localization/src/localization.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const String currentVersion = '0.11.16';
 | 
					const String currentVersion = '0.11.17';
 | 
				
			||||||
const String currentReleaseTag =
 | 
					const String currentReleaseTag =
 | 
				
			||||||
    'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
 | 
					    'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -187,6 +187,25 @@ class AppsPageState extends State<AppsPage> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    listedApps = [...tempPinned, ...tempNotPinned];
 | 
					    listedApps = [...tempPinned, ...tempNotPinned];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    List<String?> getListedCategories() {
 | 
				
			||||||
 | 
					      var temp = listedApps
 | 
				
			||||||
 | 
					          .map((e) => e.app.categories.isNotEmpty ? e.app.categories : [null]);
 | 
				
			||||||
 | 
					      return temp.isNotEmpty
 | 
				
			||||||
 | 
					          ? {
 | 
				
			||||||
 | 
					              ...temp.reduce((v, e) => [...v, ...e])
 | 
				
			||||||
 | 
					            }.toList()
 | 
				
			||||||
 | 
					          : [];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var listedCategories = getListedCategories();
 | 
				
			||||||
 | 
					    listedCategories.sort((a, b) {
 | 
				
			||||||
 | 
					      return a != null && b != null
 | 
				
			||||||
 | 
					          ? a.compareTo(b)
 | 
				
			||||||
 | 
					          : a == null
 | 
				
			||||||
 | 
					              ? 1
 | 
				
			||||||
 | 
					              : -1;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    showChangeLogDialog(
 | 
					    showChangeLogDialog(
 | 
				
			||||||
        String? changesUrl, AppSource appSource, String changeLog, int index) {
 | 
					        String? changesUrl, AppSource appSource, String changeLog, int index) {
 | 
				
			||||||
      showDialog(
 | 
					      showDialog(
 | 
				
			||||||
@@ -402,17 +421,37 @@ class AppsPageState extends State<AppsPage> {
 | 
				
			|||||||
        ],
 | 
					        ],
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      var transparent = const Color.fromARGB(0, 0, 0, 0).value;
 | 
					      var transparent =
 | 
				
			||||||
 | 
					          Theme.of(context).colorScheme.background.withAlpha(0).value;
 | 
				
			||||||
 | 
					      List<double> stops = [
 | 
				
			||||||
 | 
					        ...listedApps[index]
 | 
				
			||||||
 | 
					            .app
 | 
				
			||||||
 | 
					            .categories
 | 
				
			||||||
 | 
					            .asMap()
 | 
				
			||||||
 | 
					            .entries
 | 
				
			||||||
 | 
					            .map((e) =>
 | 
				
			||||||
 | 
					                ((e.key / (listedApps[index].app.categories.length - 1))))
 | 
				
			||||||
 | 
					            .toList(),
 | 
				
			||||||
 | 
					        1
 | 
				
			||||||
 | 
					      ];
 | 
				
			||||||
 | 
					      if (stops.length == 2) {
 | 
				
			||||||
 | 
					        stops[0] = 1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      return Container(
 | 
					      return Container(
 | 
				
			||||||
          decoration: BoxDecoration(
 | 
					          decoration: BoxDecoration(
 | 
				
			||||||
              border: Border.symmetric(
 | 
					              gradient: LinearGradient(
 | 
				
			||||||
                  vertical: BorderSide(
 | 
					                  stops: stops,
 | 
				
			||||||
                      width: 4,
 | 
					                  begin: const Alignment(-1, 0),
 | 
				
			||||||
                      color: Color(listedApps[index].app.categories.isNotEmpty
 | 
					                  end: const Alignment(-0.97, 0),
 | 
				
			||||||
                          ? settingsProvider.categories[
 | 
					                  colors: [
 | 
				
			||||||
                                  listedApps[index].app.categories.first] ??
 | 
					                ...listedApps[index]
 | 
				
			||||||
                              transparent
 | 
					                    .app
 | 
				
			||||||
                          : transparent)))),
 | 
					                    .categories
 | 
				
			||||||
 | 
					                    .map((e) =>
 | 
				
			||||||
 | 
					                        Color(settingsProvider.categories[e]!).withAlpha(255))
 | 
				
			||||||
 | 
					                    .toList(),
 | 
				
			||||||
 | 
					                Color(transparent)
 | 
				
			||||||
 | 
					              ])),
 | 
				
			||||||
          child: ListTile(
 | 
					          child: ListTile(
 | 
				
			||||||
            tileColor: listedApps[index].app.pinned
 | 
					            tileColor: listedApps[index].app.pinned
 | 
				
			||||||
                ? Colors.grey.withOpacity(0.1)
 | 
					                ? Colors.grey.withOpacity(0.1)
 | 
				
			||||||
@@ -465,6 +504,28 @@ class AppsPageState extends State<AppsPage> {
 | 
				
			|||||||
          ));
 | 
					          ));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getCategoryCollapsibleTile(int index) {
 | 
				
			||||||
 | 
					      var tiles = listedApps
 | 
				
			||||||
 | 
					          .asMap()
 | 
				
			||||||
 | 
					          .entries
 | 
				
			||||||
 | 
					          .where((e) =>
 | 
				
			||||||
 | 
					              e.value.app.categories.contains(listedCategories[index]) ||
 | 
				
			||||||
 | 
					              e.value.app.categories.isEmpty && listedCategories[index] == null)
 | 
				
			||||||
 | 
					          .map((e) => getSingleAppHorizTile(e.key))
 | 
				
			||||||
 | 
					          .toList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      capFirstChar(String str) => str[0].toUpperCase() + str.substring(1);
 | 
				
			||||||
 | 
					      return ExpansionTile(
 | 
				
			||||||
 | 
					          initiallyExpanded: true,
 | 
				
			||||||
 | 
					          title: Text(
 | 
				
			||||||
 | 
					            capFirstChar(listedCategories[index] ?? tr('noCategory')),
 | 
				
			||||||
 | 
					            style: const TextStyle(fontWeight: FontWeight.bold),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          controlAffinity: ListTileControlAffinity.leading,
 | 
				
			||||||
 | 
					          trailing: Text(tiles.length.toString()),
 | 
				
			||||||
 | 
					          children: tiles);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getSelectAllButton() {
 | 
					    getSelectAllButton() {
 | 
				
			||||||
      return selectedApps.isEmpty
 | 
					      return selectedApps.isEmpty
 | 
				
			||||||
          ? TextButton.icon(
 | 
					          ? TextButton.icon(
 | 
				
			||||||
@@ -903,6 +964,22 @@ class AppsPageState extends State<AppsPage> {
 | 
				
			|||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getDisplayedList() {
 | 
				
			||||||
 | 
					      return settingsProvider.groupByCategory &&
 | 
				
			||||||
 | 
					              !(listedCategories.isEmpty ||
 | 
				
			||||||
 | 
					                  (listedCategories.length == 1 && listedCategories[0] == null))
 | 
				
			||||||
 | 
					          ? SliverList(
 | 
				
			||||||
 | 
					              delegate:
 | 
				
			||||||
 | 
					                  SliverChildBuilderDelegate((BuildContext context, int index) {
 | 
				
			||||||
 | 
					              return getCategoryCollapsibleTile(index);
 | 
				
			||||||
 | 
					            }, childCount: listedCategories.length))
 | 
				
			||||||
 | 
					          : SliverList(
 | 
				
			||||||
 | 
					              delegate:
 | 
				
			||||||
 | 
					                  SliverChildBuilderDelegate((BuildContext context, int index) {
 | 
				
			||||||
 | 
					              return getSingleAppHorizTile(index);
 | 
				
			||||||
 | 
					            }, childCount: listedApps.length));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Scaffold(
 | 
					    return Scaffold(
 | 
				
			||||||
      backgroundColor: Theme.of(context).colorScheme.surface,
 | 
					      backgroundColor: Theme.of(context).colorScheme.surface,
 | 
				
			||||||
      body: RefreshIndicator(
 | 
					      body: RefreshIndicator(
 | 
				
			||||||
@@ -922,11 +999,7 @@ class AppsPageState extends State<AppsPage> {
 | 
				
			|||||||
          child: CustomScrollView(slivers: <Widget>[
 | 
					          child: CustomScrollView(slivers: <Widget>[
 | 
				
			||||||
            CustomAppBar(title: tr('appsString')),
 | 
					            CustomAppBar(title: tr('appsString')),
 | 
				
			||||||
            ...getLoadingWidgets(),
 | 
					            ...getLoadingWidgets(),
 | 
				
			||||||
            SliverList(
 | 
					            getDisplayedList()
 | 
				
			||||||
                delegate: SliverChildBuilderDelegate(
 | 
					 | 
				
			||||||
                    (BuildContext context, int index) {
 | 
					 | 
				
			||||||
              return getSingleAppHorizTile(index);
 | 
					 | 
				
			||||||
            }, childCount: listedApps.length))
 | 
					 | 
				
			||||||
          ])),
 | 
					          ])),
 | 
				
			||||||
      persistentFooterButtons: appsProvider.apps.isEmpty
 | 
					      persistentFooterButtons: appsProvider.apps.isEmpty
 | 
				
			||||||
          ? null
 | 
					          ? null
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -262,6 +262,18 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
				
			|||||||
                                    })
 | 
					                                    })
 | 
				
			||||||
                              ],
 | 
					                              ],
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
 | 
					                            height16,
 | 
				
			||||||
 | 
					                            Row(
 | 
				
			||||||
 | 
					                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
				
			||||||
 | 
					                              children: [
 | 
				
			||||||
 | 
					                                Text(tr('groupByCategory')),
 | 
				
			||||||
 | 
					                                Switch(
 | 
				
			||||||
 | 
					                                    value: settingsProvider.groupByCategory,
 | 
				
			||||||
 | 
					                                    onChanged: (value) {
 | 
				
			||||||
 | 
					                                      settingsProvider.groupByCategory = value;
 | 
				
			||||||
 | 
					                                    })
 | 
				
			||||||
 | 
					                              ],
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
                            const Divider(
 | 
					                            const Divider(
 | 
				
			||||||
                              height: 16,
 | 
					                              height: 16,
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -139,6 +139,15 @@ class SettingsProvider with ChangeNotifier {
 | 
				
			|||||||
    notifyListeners();
 | 
					    notifyListeners();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get groupByCategory {
 | 
				
			||||||
 | 
					    return prefs?.getBool('groupByCategory') ?? false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  set groupByCategory(bool show) {
 | 
				
			||||||
 | 
					    prefs?.setBool('groupByCategory', show);
 | 
				
			||||||
 | 
					    notifyListeners();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  String? getSettingString(String settingId) {
 | 
					  String? getSettingString(String settingId) {
 | 
				
			||||||
    return prefs?.getString(settingId);
 | 
					    return prefs?.getString(settingId);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 | 
				
			|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
					# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
				
			||||||
# In Windows, build-name is used as the major, minor, and patch parts
 | 
					# In Windows, build-name is used as the major, minor, and patch parts
 | 
				
			||||||
# of the product and file versions while build-number is used as the build suffix.
 | 
					# of the product and file versions while build-number is used as the build suffix.
 | 
				
			||||||
version: 0.11.16+138 # When changing this, update the tag in main() accordingly
 | 
					version: 0.11.17+139 # When changing this, update the tag in main() accordingly
 | 
				
			||||||
 | 
					
 | 
				
			||||||
environment:
 | 
					environment:
 | 
				
			||||||
  sdk: '>=2.18.2 <3.0.0'
 | 
					  sdk: '>=2.18.2 <3.0.0'
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user