Added "Group by Category" setting

This commit is contained in:
Imran Remtulla
2023-03-30 23:40:32 -04:00
parent 814e269d1d
commit 4e17bbcfd1
13 changed files with 118 additions and 16 deletions

View File

@@ -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?"

View File

@@ -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?"

View File

@@ -220,6 +220,7 @@
"importFromURLsInFile": "وارد کردن از آدرس های اینترنتی موجود در فایل (مانند OPML)", "importFromURLsInFile": "وارد کردن از آدرس های اینترنتی موجود در فایل (مانند OPML)",
"versionDetection": "تشخیص نسخه", "versionDetection": "تشخیص نسخه",
"standardVersionDetection": "تشخیص نسخه استاندارد", "standardVersionDetection": "تشخیص نسخه استاندارد",
"groupByCategory": "Group by Category",
"removeAppQuestion": { "removeAppQuestion": {
"one": "برنامه حذف شود؟", "one": "برنامه حذف شود؟",
"other": "برنامه ها حذف شوند؟" "other": "برنامه ها حذف شوند؟"

View File

@@ -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 ?"

View File

@@ -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?"

View File

@@ -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?"

View File

@@ -220,6 +220,7 @@
"importFromURLsInFile": "ファイルOPMLなど内のURLからインポート", "importFromURLsInFile": "ファイルOPMLなど内のURLからインポート",
"versionDetection": "バージョン検出", "versionDetection": "バージョン検出",
"standardVersionDetection": "標準のバージョン検出", "standardVersionDetection": "標準のバージョン検出",
"groupByCategory": "Group by Category",
"removeAppQuestion": { "removeAppQuestion": {
"one": "アプリを削除しますか?", "one": "アプリを削除しますか?",
"other": "アプリを削除しますか?" "other": "アプリを削除しますか?"

View File

@@ -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": "删除应用?"

View File

@@ -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

View File

@@ -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

View File

@@ -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,
), ),

View File

@@ -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);
} }

View File

@@ -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'