mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-11-04 07:13:28 +01:00 
			
		
		
		
	Added rel. date sort
This commit is contained in:
		@@ -216,6 +216,7 @@
 | 
			
		||||
    "useReleaseDateAsVersion": "Use Release Date as Version",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
 | 
			
		||||
    "changes": "Changes",
 | 
			
		||||
    "releaseDate": "Release Date",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "App entfernen?",
 | 
			
		||||
        "other": "App entfernen?"
 | 
			
		||||
 
 | 
			
		||||
@@ -216,6 +216,7 @@
 | 
			
		||||
    "useReleaseDateAsVersion": "Use Release Date as Version",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
 | 
			
		||||
    "changes": "Changes",
 | 
			
		||||
    "releaseDate": "Release Date",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Remove App?",
 | 
			
		||||
        "other": "Remove Apps?"
 | 
			
		||||
 
 | 
			
		||||
@@ -216,6 +216,7 @@
 | 
			
		||||
    "useReleaseDateAsVersion": "Use Release Date as Version",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
 | 
			
		||||
    "changes": "Changes",
 | 
			
		||||
    "releaseDate": "Release Date",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "برنامه حذف شود؟",
 | 
			
		||||
        "other": "برنامه ها حذف شوند؟"
 | 
			
		||||
 
 | 
			
		||||
@@ -215,6 +215,7 @@
 | 
			
		||||
    "useReleaseDateAsVersion": "Use Release Date as Version",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
 | 
			
		||||
    "changes": "Changes",
 | 
			
		||||
    "releaseDate": "Release Date",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Eltávolítja az alkalmazást?",
 | 
			
		||||
        "other": "Eltávolítja az alkalmazást?"
 | 
			
		||||
 
 | 
			
		||||
@@ -216,6 +216,7 @@
 | 
			
		||||
    "useReleaseDateAsVersion": "Use Release Date as Version",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
 | 
			
		||||
    "changes": "Changes",
 | 
			
		||||
    "releaseDate": "Release Date",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Rimuovere l'App?",
 | 
			
		||||
        "other": "Rimuovere le App?"
 | 
			
		||||
 
 | 
			
		||||
@@ -216,6 +216,7 @@
 | 
			
		||||
    "useReleaseDateAsVersion": "Use Release Date as Version",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
 | 
			
		||||
    "changes": "Changes",
 | 
			
		||||
    "releaseDate": "Release Date",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "アプリを削除しますか?",
 | 
			
		||||
        "other": "アプリを削除しますか?"
 | 
			
		||||
 
 | 
			
		||||
@@ -216,6 +216,7 @@
 | 
			
		||||
    "useReleaseDateAsVersion": "Use Release Date as Version",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
 | 
			
		||||
    "changes": "Changes",
 | 
			
		||||
    "releaseDate": "Release Date",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "删除应用?",
 | 
			
		||||
        "other": "删除应用?"
 | 
			
		||||
 
 | 
			
		||||
@@ -54,12 +54,12 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var appsProvider = context.watch<AppsProvider>();
 | 
			
		||||
    var settingsProvider = context.watch<SettingsProvider>();
 | 
			
		||||
    var sortedApps = appsProvider.apps.values.toList();
 | 
			
		||||
    var listedApps = appsProvider.apps.values.toList();
 | 
			
		||||
    var currentFilterIsUpdatesOnly =
 | 
			
		||||
        filter.isIdenticalTo(updatesOnlyFilter, settingsProvider);
 | 
			
		||||
 | 
			
		||||
    selectedApps = selectedApps
 | 
			
		||||
        .where((element) => sortedApps.map((e) => e.app).contains(element))
 | 
			
		||||
        .where((element) => listedApps.map((e) => e.app).contains(element))
 | 
			
		||||
        .toSet();
 | 
			
		||||
 | 
			
		||||
    toggleAppSelected(App app) {
 | 
			
		||||
@@ -72,7 +72,7 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sortedApps = sortedApps.where((app) {
 | 
			
		||||
    listedApps = listedApps.where((app) {
 | 
			
		||||
      if (app.app.installedVersion == app.app.latestVersion &&
 | 
			
		||||
          !(filter.includeUptodate)) {
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -111,7 +111,7 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
      return true;
 | 
			
		||||
    }).toList();
 | 
			
		||||
 | 
			
		||||
    sortedApps.sort((a, b) {
 | 
			
		||||
    listedApps.sort((a, b) {
 | 
			
		||||
      var nameA = a.installedInfo?.name ?? a.app.name;
 | 
			
		||||
      var nameB = b.installedInfo?.name ?? b.app.name;
 | 
			
		||||
      int result = 0;
 | 
			
		||||
@@ -119,25 +119,30 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
        result = (a.app.author + nameA).compareTo(b.app.author + nameB);
 | 
			
		||||
      } else if (settingsProvider.sortColumn == SortColumnSettings.nameAuthor) {
 | 
			
		||||
        result = (nameA + a.app.author).compareTo(nameB + b.app.author);
 | 
			
		||||
      } else if (settingsProvider.sortColumn ==
 | 
			
		||||
          SortColumnSettings.releaseDate) {
 | 
			
		||||
        result = (a.app.releaseDate)
 | 
			
		||||
                ?.compareTo(b.app.releaseDate ?? DateTime.now()) ??
 | 
			
		||||
            0;
 | 
			
		||||
      }
 | 
			
		||||
      return result;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (settingsProvider.sortOrder == SortOrderSettings.descending) {
 | 
			
		||||
      sortedApps = sortedApps.reversed.toList();
 | 
			
		||||
      listedApps = listedApps.reversed.toList();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var existingUpdates = appsProvider.findExistingUpdates(installedOnly: true);
 | 
			
		||||
 | 
			
		||||
    var existingUpdateIdsAllOrSelected = existingUpdates
 | 
			
		||||
        .where((element) => selectedApps.isEmpty
 | 
			
		||||
            ? sortedApps.where((a) => a.app.id == element).isNotEmpty
 | 
			
		||||
            ? listedApps.where((a) => a.app.id == element).isNotEmpty
 | 
			
		||||
            : selectedApps.map((e) => e.id).contains(element))
 | 
			
		||||
        .toList();
 | 
			
		||||
    var newInstallIdsAllOrSelected = appsProvider
 | 
			
		||||
        .findExistingUpdates(nonInstalledOnly: true)
 | 
			
		||||
        .where((element) => selectedApps.isEmpty
 | 
			
		||||
            ? sortedApps.where((a) => a.app.id == element).isNotEmpty
 | 
			
		||||
            ? listedApps.where((a) => a.app.id == element).isNotEmpty
 | 
			
		||||
            : selectedApps.map((e) => e.id).contains(element))
 | 
			
		||||
        .toList();
 | 
			
		||||
 | 
			
		||||
@@ -159,26 +164,26 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
 | 
			
		||||
    if (settingsProvider.pinUpdates) {
 | 
			
		||||
      var temp = [];
 | 
			
		||||
      sortedApps = sortedApps.where((sa) {
 | 
			
		||||
      listedApps = listedApps.where((sa) {
 | 
			
		||||
        if (existingUpdates.contains(sa.app.id)) {
 | 
			
		||||
          temp.add(sa);
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
      }).toList();
 | 
			
		||||
      sortedApps = [...temp, ...sortedApps];
 | 
			
		||||
      listedApps = [...temp, ...listedApps];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var tempPinned = [];
 | 
			
		||||
    var tempNotPinned = [];
 | 
			
		||||
    for (var a in sortedApps) {
 | 
			
		||||
    for (var a in listedApps) {
 | 
			
		||||
      if (a.app.pinned) {
 | 
			
		||||
        tempPinned.add(a);
 | 
			
		||||
      } else {
 | 
			
		||||
        tempNotPinned.add(a);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    sortedApps = [...tempPinned, ...tempNotPinned];
 | 
			
		||||
    listedApps = [...tempPinned, ...tempNotPinned];
 | 
			
		||||
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      backgroundColor: Theme.of(context).colorScheme.surface,
 | 
			
		||||
@@ -198,7 +203,7 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
          },
 | 
			
		||||
          child: CustomScrollView(slivers: <Widget>[
 | 
			
		||||
            CustomAppBar(title: tr('appsString')),
 | 
			
		||||
            if (appsProvider.loadingApps || sortedApps.isEmpty)
 | 
			
		||||
            if (appsProvider.loadingApps || listedApps.isEmpty)
 | 
			
		||||
              SliverFillRemaining(
 | 
			
		||||
                  child: Center(
 | 
			
		||||
                      child: appsProvider.loadingApps
 | 
			
		||||
@@ -225,8 +230,8 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                delegate: SliverChildBuilderDelegate(
 | 
			
		||||
                    (BuildContext context, int index) {
 | 
			
		||||
              String? changesUrl = SourceProvider()
 | 
			
		||||
                  .getSource(sortedApps[index].app.url)
 | 
			
		||||
                  .changeLogPageFromStandardUrl(sortedApps[index].app.url);
 | 
			
		||||
                  .getSource(listedApps[index].app.url)
 | 
			
		||||
                  .changeLogPageFromStandardUrl(listedApps[index].app.url);
 | 
			
		||||
              var transparent = const Color.fromARGB(0, 0, 0, 0).value;
 | 
			
		||||
              return Container(
 | 
			
		||||
                  decoration: BoxDecoration(
 | 
			
		||||
@@ -234,53 +239,53 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                          vertical: BorderSide(
 | 
			
		||||
                              width: 4,
 | 
			
		||||
                              color: Color(
 | 
			
		||||
                                  sortedApps[index].app.categories.isNotEmpty
 | 
			
		||||
                                  listedApps[index].app.categories.isNotEmpty
 | 
			
		||||
                                      ? settingsProvider.categories[
 | 
			
		||||
                                              sortedApps[index]
 | 
			
		||||
                                              listedApps[index]
 | 
			
		||||
                                                  .app
 | 
			
		||||
                                                  .categories
 | 
			
		||||
                                                  .first] ??
 | 
			
		||||
                                          transparent
 | 
			
		||||
                                      : transparent)))),
 | 
			
		||||
                  child: ListTile(
 | 
			
		||||
                    tileColor: sortedApps[index].app.pinned
 | 
			
		||||
                    tileColor: listedApps[index].app.pinned
 | 
			
		||||
                        ? Colors.grey.withOpacity(0.1)
 | 
			
		||||
                        : Colors.transparent,
 | 
			
		||||
                    selectedTileColor: Theme.of(context)
 | 
			
		||||
                        .colorScheme
 | 
			
		||||
                        .primary
 | 
			
		||||
                        .withOpacity(sortedApps[index].app.pinned ? 0.2 : 0.1),
 | 
			
		||||
                    selected: selectedApps.contains(sortedApps[index].app),
 | 
			
		||||
                        .withOpacity(listedApps[index].app.pinned ? 0.2 : 0.1),
 | 
			
		||||
                    selected: selectedApps.contains(listedApps[index].app),
 | 
			
		||||
                    onLongPress: () {
 | 
			
		||||
                      toggleAppSelected(sortedApps[index].app);
 | 
			
		||||
                      toggleAppSelected(listedApps[index].app);
 | 
			
		||||
                    },
 | 
			
		||||
                    leading: sortedApps[index].installedInfo != null
 | 
			
		||||
                    leading: listedApps[index].installedInfo != null
 | 
			
		||||
                        ? Image.memory(
 | 
			
		||||
                            sortedApps[index].installedInfo!.icon!,
 | 
			
		||||
                            listedApps[index].installedInfo!.icon!,
 | 
			
		||||
                            gaplessPlayback: true,
 | 
			
		||||
                          )
 | 
			
		||||
                        : null,
 | 
			
		||||
                    title: Text(
 | 
			
		||||
                      sortedApps[index].installedInfo?.name ??
 | 
			
		||||
                          sortedApps[index].app.name,
 | 
			
		||||
                      listedApps[index].installedInfo?.name ??
 | 
			
		||||
                          listedApps[index].app.name,
 | 
			
		||||
                      style: TextStyle(
 | 
			
		||||
                        overflow: TextOverflow.ellipsis,
 | 
			
		||||
                        fontWeight: sortedApps[index].app.pinned
 | 
			
		||||
                        fontWeight: listedApps[index].app.pinned
 | 
			
		||||
                            ? FontWeight.bold
 | 
			
		||||
                            : FontWeight.normal,
 | 
			
		||||
                      ),
 | 
			
		||||
                    ),
 | 
			
		||||
                    subtitle: Text(
 | 
			
		||||
                        tr('byX', args: [sortedApps[index].app.author]),
 | 
			
		||||
                        tr('byX', args: [listedApps[index].app.author]),
 | 
			
		||||
                        style: TextStyle(
 | 
			
		||||
                            fontWeight: sortedApps[index].app.pinned
 | 
			
		||||
                            fontWeight: listedApps[index].app.pinned
 | 
			
		||||
                                ? FontWeight.bold
 | 
			
		||||
                                : FontWeight.normal)),
 | 
			
		||||
                    trailing: SingleChildScrollView(
 | 
			
		||||
                        reverse: true,
 | 
			
		||||
                        child: sortedApps[index].downloadProgress != null
 | 
			
		||||
                        child: listedApps[index].downloadProgress != null
 | 
			
		||||
                            ? Text(tr('percentProgress', args: [
 | 
			
		||||
                                sortedApps[index]
 | 
			
		||||
                                listedApps[index]
 | 
			
		||||
                                        .downloadProgress
 | 
			
		||||
                                        ?.toInt()
 | 
			
		||||
                                        .toString() ??
 | 
			
		||||
@@ -294,7 +299,7 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                                      mainAxisSize: MainAxisSize.min,
 | 
			
		||||
                                      children: [
 | 
			
		||||
                                        Text(
 | 
			
		||||
                                          '${sortedApps[index].app.installedVersion ?? tr('notInstalled')}${sortedApps[index].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}',
 | 
			
		||||
                                          '${listedApps[index].app.installedVersion ?? tr('notInstalled')}${listedApps[index].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}',
 | 
			
		||||
                                          overflow: TextOverflow.ellipsis,
 | 
			
		||||
                                          textAlign: TextAlign.end,
 | 
			
		||||
                                        )
 | 
			
		||||
@@ -308,11 +313,11 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                                                      .externalApplication);
 | 
			
		||||
                                            },
 | 
			
		||||
                                      child: Text(
 | 
			
		||||
                                        sortedApps[index].app.releaseDate ==
 | 
			
		||||
                                        listedApps[index].app.releaseDate ==
 | 
			
		||||
                                                null
 | 
			
		||||
                                            ? tr('changes')
 | 
			
		||||
                                            : DateFormat('yyyy-MM-dd').format(
 | 
			
		||||
                                                sortedApps[index]
 | 
			
		||||
                                                listedApps[index]
 | 
			
		||||
                                                    .app
 | 
			
		||||
                                                    .releaseDate!),
 | 
			
		||||
                                        style: const TextStyle(
 | 
			
		||||
@@ -320,12 +325,12 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                                            decoration:
 | 
			
		||||
                                                TextDecoration.underline),
 | 
			
		||||
                                      )),
 | 
			
		||||
                                  sortedApps[index].app.installedVersion !=
 | 
			
		||||
                                  listedApps[index].app.installedVersion !=
 | 
			
		||||
                                              null &&
 | 
			
		||||
                                          sortedApps[index]
 | 
			
		||||
                                          listedApps[index]
 | 
			
		||||
                                                  .app
 | 
			
		||||
                                                  .installedVersion !=
 | 
			
		||||
                                              sortedApps[index]
 | 
			
		||||
                                              listedApps[index]
 | 
			
		||||
                                                  .app
 | 
			
		||||
                                                  .latestVersion
 | 
			
		||||
                                      ? appsProvider.areDownloadsRunning()
 | 
			
		||||
@@ -340,7 +345,7 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                                                      appsProvider
 | 
			
		||||
                                                          .downloadAndInstallLatestApps(
 | 
			
		||||
                                                              [
 | 
			
		||||
                                                            sortedApps[index]
 | 
			
		||||
                                                            listedApps[index]
 | 
			
		||||
                                                                .app
 | 
			
		||||
                                                                .id
 | 
			
		||||
                                                          ],
 | 
			
		||||
@@ -351,7 +356,7 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                                                      });
 | 
			
		||||
                                                    },
 | 
			
		||||
                                                    child: Text(
 | 
			
		||||
                                                      sortedApps[index]
 | 
			
		||||
                                                      listedApps[index]
 | 
			
		||||
                                                                      .app
 | 
			
		||||
                                                                      .additionalSettings[
 | 
			
		||||
                                                                  'trackOnly'] ==
 | 
			
		||||
@@ -373,18 +378,18 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                              ))),
 | 
			
		||||
                    onTap: () {
 | 
			
		||||
                      if (selectedApps.isNotEmpty) {
 | 
			
		||||
                        toggleAppSelected(sortedApps[index].app);
 | 
			
		||||
                        toggleAppSelected(listedApps[index].app);
 | 
			
		||||
                      } else {
 | 
			
		||||
                        Navigator.push(
 | 
			
		||||
                          context,
 | 
			
		||||
                          MaterialPageRoute(
 | 
			
		||||
                              builder: (context) =>
 | 
			
		||||
                                  AppPage(appId: sortedApps[index].app.id)),
 | 
			
		||||
                                  AppPage(appId: listedApps[index].app.id)),
 | 
			
		||||
                        );
 | 
			
		||||
                      }
 | 
			
		||||
                    },
 | 
			
		||||
                  ));
 | 
			
		||||
            }, childCount: sortedApps.length))
 | 
			
		||||
            }, childCount: listedApps.length))
 | 
			
		||||
          ])),
 | 
			
		||||
      persistentFooterButtons: appsProvider.apps.isEmpty
 | 
			
		||||
          ? null
 | 
			
		||||
@@ -396,20 +401,20 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                          style: const ButtonStyle(
 | 
			
		||||
                              visualDensity: VisualDensity.compact),
 | 
			
		||||
                          onPressed: () {
 | 
			
		||||
                            selectThese(sortedApps.map((e) => e.app).toList());
 | 
			
		||||
                            selectThese(listedApps.map((e) => e.app).toList());
 | 
			
		||||
                          },
 | 
			
		||||
                          icon: Icon(
 | 
			
		||||
                            Icons.select_all_outlined,
 | 
			
		||||
                            color: Theme.of(context).colorScheme.primary,
 | 
			
		||||
                          ),
 | 
			
		||||
                          label: Text(sortedApps.length.toString()))
 | 
			
		||||
                          label: Text(listedApps.length.toString()))
 | 
			
		||||
                      : TextButton.icon(
 | 
			
		||||
                          style: const ButtonStyle(
 | 
			
		||||
                              visualDensity: VisualDensity.compact),
 | 
			
		||||
                          onPressed: () {
 | 
			
		||||
                            selectedApps.isEmpty
 | 
			
		||||
                                ? selectThese(
 | 
			
		||||
                                    sortedApps.map((e) => e.app).toList())
 | 
			
		||||
                                    listedApps.map((e) => e.app).toList())
 | 
			
		||||
                                : clearSelected();
 | 
			
		||||
                          },
 | 
			
		||||
                          icon: Icon(
 | 
			
		||||
 
 | 
			
		||||
@@ -101,6 +101,10 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
          DropdownMenuItem(
 | 
			
		||||
            value: SortColumnSettings.added,
 | 
			
		||||
            child: Text(tr('asAdded')),
 | 
			
		||||
          ),
 | 
			
		||||
          DropdownMenuItem(
 | 
			
		||||
            value: SortColumnSettings.releaseDate,
 | 
			
		||||
            child: Text(tr('releaseDate')),
 | 
			
		||||
          )
 | 
			
		||||
        ],
 | 
			
		||||
        onChanged: (value) {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,6 @@ import 'package:easy_localization/easy_localization.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:fluttertoast/fluttertoast.dart';
 | 
			
		||||
import 'package:obtainium/app_sources/github.dart';
 | 
			
		||||
import 'package:obtainium/components/generated_form.dart';
 | 
			
		||||
import 'package:obtainium/main.dart';
 | 
			
		||||
import 'package:permission_handler/permission_handler.dart';
 | 
			
		||||
import 'package:shared_preferences/shared_preferences.dart';
 | 
			
		||||
@@ -18,7 +17,7 @@ enum ThemeSettings { system, light, dark }
 | 
			
		||||
 | 
			
		||||
enum ColourSettings { basic, materialYou }
 | 
			
		||||
 | 
			
		||||
enum SortColumnSettings { added, nameAuthor, authorName }
 | 
			
		||||
enum SortColumnSettings { added, nameAuthor, authorName, releaseDate }
 | 
			
		||||
 | 
			
		||||
enum SortOrderSettings { ascending, descending }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user