mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-11-04 07:13:28 +01:00 
			
		
		
		
	Compare commits
	
		
			8 Commits
		
	
	
		
			v0.11.17-b
			...
			v0.11.20-b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					e386b5ab8a | ||
| 
						 | 
					abf7be222d | ||
| 
						 | 
					4c5b9304c0 | ||
| 
						 | 
					4cfe6af044 | ||
| 
						 | 
					3f0c4068dd | ||
| 
						 | 
					7981ca29c5 | ||
| 
						 | 
					187efa8fc5 | ||
| 
						 | 
					cd27ff7f2d | 
@@ -1,7 +1,6 @@
 | 
			
		||||
import 'package:html/parser.dart';
 | 
			
		||||
import 'package:http/http.dart';
 | 
			
		||||
import 'package:obtainium/app_sources/github.dart';
 | 
			
		||||
import 'package:obtainium/app_sources/html.dart';
 | 
			
		||||
import 'package:obtainium/custom_errors.dart';
 | 
			
		||||
import 'package:obtainium/providers/source_provider.dart';
 | 
			
		||||
 | 
			
		||||
@@ -29,24 +28,41 @@ class Mullvad extends AppSource {
 | 
			
		||||
    String standardUrl,
 | 
			
		||||
    Map<String, dynamic> additionalSettings,
 | 
			
		||||
  ) async {
 | 
			
		||||
    var details = await HTML().getLatestAPKDetails(
 | 
			
		||||
        '$standardUrl/en/download/android', additionalSettings);
 | 
			
		||||
    var fileName = details.apkUrls[0].split('/').last;
 | 
			
		||||
    var versionMatch = RegExp('[0-9]+(\\.[0-9]+)+').firstMatch(fileName);
 | 
			
		||||
    if (versionMatch == null) {
 | 
			
		||||
      throw NoVersionError();
 | 
			
		||||
    Response res = await get(Uri.parse('$standardUrl/en/download/android'));
 | 
			
		||||
    if (res.statusCode == 200) {
 | 
			
		||||
      var versions = parse(res.body)
 | 
			
		||||
          .querySelectorAll('p')
 | 
			
		||||
          .map((e) => e.innerHtml)
 | 
			
		||||
          .where((p) => p.contains('Latest version: '))
 | 
			
		||||
          .map((e) {
 | 
			
		||||
            var match = RegExp('[0-9]+(\\.[0-9]+)*').firstMatch(e);
 | 
			
		||||
            if (match == null) {
 | 
			
		||||
              return '';
 | 
			
		||||
            } else {
 | 
			
		||||
              return e.substring(match.start, match.end);
 | 
			
		||||
            }
 | 
			
		||||
          })
 | 
			
		||||
          .where((element) => element.isNotEmpty)
 | 
			
		||||
          .toList();
 | 
			
		||||
      if (versions.isEmpty) {
 | 
			
		||||
        throw NoVersionError();
 | 
			
		||||
      }
 | 
			
		||||
      String? changeLog;
 | 
			
		||||
      try {
 | 
			
		||||
        changeLog = (await GitHub().getLatestAPKDetails(
 | 
			
		||||
                'https://github.com/mullvad/mullvadvpn-app',
 | 
			
		||||
                {'fallbackToOlderReleases': true}))
 | 
			
		||||
            .changeLog;
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        // Ignore
 | 
			
		||||
      }
 | 
			
		||||
      return APKDetails(
 | 
			
		||||
          versions[0],
 | 
			
		||||
          ['https://mullvad.net/download/app/apk/latest'],
 | 
			
		||||
          AppNames(name, 'Mullvad-VPN'),
 | 
			
		||||
          changeLog: changeLog);
 | 
			
		||||
    } else {
 | 
			
		||||
      throw getObtainiumHttpError(res);
 | 
			
		||||
    }
 | 
			
		||||
    details.version = fileName.substring(versionMatch.start, versionMatch.end);
 | 
			
		||||
    details.names = AppNames(name, 'Mullvad-VPN');
 | 
			
		||||
    try {
 | 
			
		||||
      details.changeLog = (await GitHub().getLatestAPKDetails(
 | 
			
		||||
              'https://github.com/mullvad/mullvadvpn-app',
 | 
			
		||||
              {'fallbackToOlderReleases': true}))
 | 
			
		||||
          .changeLog;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      print(e);
 | 
			
		||||
      // Ignore
 | 
			
		||||
    }
 | 
			
		||||
    return details;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart';
 | 
			
		||||
// ignore: implementation_imports
 | 
			
		||||
import 'package:easy_localization/src/localization.dart';
 | 
			
		||||
 | 
			
		||||
const String currentVersion = '0.11.17';
 | 
			
		||||
const String currentVersion = '0.11.20';
 | 
			
		||||
const String currentReleaseTag =
 | 
			
		||||
    'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -448,7 +448,8 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                    .app
 | 
			
		||||
                    .categories
 | 
			
		||||
                    .map((e) =>
 | 
			
		||||
                        Color(settingsProvider.categories[e]!).withAlpha(255))
 | 
			
		||||
                        Color(settingsProvider.categories[e] ?? transparent)
 | 
			
		||||
                            .withAlpha(255))
 | 
			
		||||
                    .toList(),
 | 
			
		||||
                Color(transparent)
 | 
			
		||||
              ])),
 | 
			
		||||
@@ -734,14 +735,12 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pinSelectedApps() {
 | 
			
		||||
      () {
 | 
			
		||||
        var pinStatus = selectedApps.where((element) => element.pinned).isEmpty;
 | 
			
		||||
        appsProvider.saveApps(selectedApps.map((e) {
 | 
			
		||||
          e.pinned = pinStatus;
 | 
			
		||||
          return e;
 | 
			
		||||
        }).toList());
 | 
			
		||||
        Navigator.of(context).pop();
 | 
			
		||||
      };
 | 
			
		||||
      var pinStatus = selectedApps.where((element) => element.pinned).isEmpty;
 | 
			
		||||
      appsProvider.saveApps(selectedApps.map((e) {
 | 
			
		||||
        e.pinned = pinStatus;
 | 
			
		||||
        return e;
 | 
			
		||||
      }).toList());
 | 
			
		||||
      Navigator.of(context).pop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    resetSelectedAppsInstallStatuses() {
 | 
			
		||||
 
 | 
			
		||||
@@ -133,7 +133,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
            settingsProvider.categories = cats;
 | 
			
		||||
            appsProvider.addMissingCategories(settingsProvider);
 | 
			
		||||
            showError(tr('importedX', args: [plural('apps', value)]), context);
 | 
			
		||||
          });
 | 
			
		||||
        } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ import 'package:obtainium/components/custom_app_bar.dart';
 | 
			
		||||
import 'package:obtainium/components/generated_form.dart';
 | 
			
		||||
import 'package:obtainium/custom_errors.dart';
 | 
			
		||||
import 'package:obtainium/main.dart';
 | 
			
		||||
import 'package:obtainium/providers/apps_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/logs_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/settings_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/source_provider.dart';
 | 
			
		||||
@@ -444,6 +445,7 @@ class _CategoryEditorSelectorState extends State<CategoryEditorSelector> {
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var settingsProvider = context.watch<SettingsProvider>();
 | 
			
		||||
    var appsProvider = context.watch<AppsProvider>();
 | 
			
		||||
    storedValues = settingsProvider.categories.map((key, value) => MapEntry(
 | 
			
		||||
        key,
 | 
			
		||||
        MapEntry(value,
 | 
			
		||||
@@ -467,8 +469,9 @@ class _CategoryEditorSelectorState extends State<CategoryEditorSelector> {
 | 
			
		||||
          if (!isBuilding) {
 | 
			
		||||
            storedValues =
 | 
			
		||||
                values['categories'] as Map<String, MapEntry<int, bool>>;
 | 
			
		||||
            settingsProvider.categories =
 | 
			
		||||
                storedValues.map((key, value) => MapEntry(key, value.key));
 | 
			
		||||
            settingsProvider.setCategories(
 | 
			
		||||
                storedValues.map((key, value) => MapEntry(key, value.key)),
 | 
			
		||||
                appsProvider: appsProvider);
 | 
			
		||||
            if (widget.onSelected != null) {
 | 
			
		||||
              widget.onSelected!(storedValues.keys
 | 
			
		||||
                  .where((k) => storedValues[k]!.value)
 | 
			
		||||
 
 | 
			
		||||
@@ -757,6 +757,18 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
    await intent.launch();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  addMissingCategories(SettingsProvider settingsProvider) {
 | 
			
		||||
    var cats = settingsProvider.categories;
 | 
			
		||||
    apps.forEach((key, value) {
 | 
			
		||||
      for (var c in value.app.categories) {
 | 
			
		||||
        if (!cats.containsKey(c)) {
 | 
			
		||||
          cats[c] = generateRandomLightColor().value;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    settingsProvider.setCategories(cats, appsProvider: this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<App?> checkUpdate(String appId) async {
 | 
			
		||||
    App? currentApp = apps[appId]!.app;
 | 
			
		||||
    SourceProvider sourceProvider = SourceProvider();
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,8 @@ import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:fluttertoast/fluttertoast.dart';
 | 
			
		||||
import 'package:obtainium/app_sources/github.dart';
 | 
			
		||||
import 'package:obtainium/main.dart';
 | 
			
		||||
import 'package:obtainium/providers/apps_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/source_provider.dart';
 | 
			
		||||
import 'package:permission_handler/permission_handler.dart';
 | 
			
		||||
import 'package:shared_preferences/shared_preferences.dart';
 | 
			
		||||
 | 
			
		||||
@@ -160,7 +162,22 @@ class SettingsProvider with ChangeNotifier {
 | 
			
		||||
  Map<String, int> get categories =>
 | 
			
		||||
      Map<String, int>.from(jsonDecode(prefs?.getString('categories') ?? '{}'));
 | 
			
		||||
 | 
			
		||||
  set categories(Map<String, int> cats) {
 | 
			
		||||
  void setCategories(Map<String, int> cats, {AppsProvider? appsProvider}) {
 | 
			
		||||
    if (appsProvider != null) {
 | 
			
		||||
      List<App> changedApps = appsProvider.apps.values
 | 
			
		||||
          .map((a) {
 | 
			
		||||
            var n1 = a.app.categories.length;
 | 
			
		||||
            a.app.categories.removeWhere((c) => !cats.keys.contains(c));
 | 
			
		||||
            return n1 > a.app.categories.length ? a.app : null;
 | 
			
		||||
          })
 | 
			
		||||
          .where((element) => element != null)
 | 
			
		||||
          .map((e) => e as App)
 | 
			
		||||
          .toList();
 | 
			
		||||
      if (changedApps.isNotEmpty) {
 | 
			
		||||
        appsProvider.saveApps(changedApps,
 | 
			
		||||
            attemptToCorrectInstallStatus: false);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    prefs?.setString('categories', jsonEncode(cats));
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								pubspec.lock
									
									
									
									
									
								
							@@ -337,10 +337,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: markdown
 | 
			
		||||
      sha256: b3c60dee8c2af50ad0e6e90cceba98e47718a6ee0a7a6772c77846a0cc21f78b
 | 
			
		||||
      sha256: d95a9d12954aafc97f984ca29baaa7690ed4d9ec4140a23ad40580bcdb6c87f5
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "7.0.1"
 | 
			
		||||
    version: "7.0.2"
 | 
			
		||||
  matcher:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -553,34 +553,34 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: shared_preferences
 | 
			
		||||
      sha256: "78528fd87d0d08ffd3e69551173c026e8eacc7b7079c82eb6a77413957b7e394"
 | 
			
		||||
      sha256: "858aaa72d8f61637d64e776aca82e1c67e6d9ee07979123c5d17115031c1b13b"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.20"
 | 
			
		||||
    version: "2.1.0"
 | 
			
		||||
  shared_preferences_android:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: shared_preferences_android
 | 
			
		||||
      sha256: ad423a80fe7b4e48b50d6111b3ea1027af0e959e49d485712e134863d9c1c521
 | 
			
		||||
      sha256: "8304d8a1f7d21a429f91dee552792249362b68a331ac5c3c1caf370f658873f6"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.17"
 | 
			
		||||
    version: "2.1.0"
 | 
			
		||||
  shared_preferences_foundation:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: shared_preferences_foundation
 | 
			
		||||
      sha256: "1e755f8583229f185cfca61b1d80fb2344c9d660e1c69ede5450d8f478fa5310"
 | 
			
		||||
      sha256: cf2a42fb20148502022861f71698db12d937c7459345a1bdaa88fc91a91b3603
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.1.5"
 | 
			
		||||
    version: "2.2.0"
 | 
			
		||||
  shared_preferences_linux:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: shared_preferences_linux
 | 
			
		||||
      sha256: "3a59ed10890a8409ad0faad7bb2957dab4b92b8fbe553257b05d30ed8af2c707"
 | 
			
		||||
      sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.1.5"
 | 
			
		||||
    version: "2.2.0"
 | 
			
		||||
  shared_preferences_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -593,18 +593,18 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: shared_preferences_web
 | 
			
		||||
      sha256: "0dc2633f215a3d4aa3184c9b2c5766f4711e4e5a6b256e62aafee41f89f1bfb8"
 | 
			
		||||
      sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.6"
 | 
			
		||||
    version: "2.1.0"
 | 
			
		||||
  shared_preferences_windows:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: shared_preferences_windows
 | 
			
		||||
      sha256: "71bcd669bb9cdb6b39f22c4a7728b6d49e934f6cba73157ffa5a54f1eed67436"
 | 
			
		||||
      sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.1.5"
 | 
			
		||||
    version: "2.2.0"
 | 
			
		||||
  sky_engine:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description: flutter
 | 
			
		||||
@@ -790,10 +790,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: webview_flutter_android
 | 
			
		||||
      sha256: "34f83c2f0f64c75ad75c77a2ccfc8d2e531afbe8ad41af1fd787d6d33336aa90"
 | 
			
		||||
      sha256: "9e223788e1954087dac30d813dc151f8e12f09f1139f116ce20b5658893f3627"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.4.3"
 | 
			
		||||
    version: "3.4.4"
 | 
			
		||||
  webview_flutter_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -835,5 +835,5 @@ packages:
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.2.2"
 | 
			
		||||
sdks:
 | 
			
		||||
  dart: ">=2.18.2 <3.0.0"
 | 
			
		||||
  dart: ">=2.19.0 <3.0.0"
 | 
			
		||||
  flutter: ">=3.4.0-17.0.pre"
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
# 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.
 | 
			
		||||
version: 0.11.17+139 # When changing this, update the tag in main() accordingly
 | 
			
		||||
version: 0.11.20+142 # When changing this, update the tag in main() accordingly
 | 
			
		||||
 | 
			
		||||
environment:
 | 
			
		||||
  sdk: '>=2.18.2 <3.0.0'
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user