Compare commits

...

10 Commits

Author SHA1 Message Date
Imran Remtulla
69ccefcf1a Merge pull request #382 from atilluF/main
Update it.json
2023-03-25 00:56:52 -04:00
Imran Remtulla
d3932f317d Merge pull request #384 from ImranR98/dev
Bugfixes: "Return After Delete" (#359) and No Redirect if Navigating During App Addition
2023-03-25 00:56:16 -04:00
Imran Remtulla
895deeead5 Increment version 2023-03-25 00:54:34 -04:00
Imran Remtulla
4c04af3868 Bugfix: App add doesn't redirect if nav away during add 2023-03-25 00:54:12 -04:00
Imran Remtulla
07c490bb0e Fixed "return after delete" bug (#359) 2023-03-25 00:47:26 -04:00
atilluF
a081d553bb Update it.json 2023-03-24 20:11:03 +01:00
Imran Remtulla
3bc5837999 Merge pull request #380 from ImranR98/dev
Bugfix: Infinite load on corrupt App JSON (#378)
2023-03-22 22:41:59 -04:00
Imran Remtulla
9fbe524818 Bugfix: Infinite load on corrupt App JSON (#378) 2023-03-22 22:36:04 -04:00
Imran Remtulla
c21a9d7292 Merge pull request #373 from ImranR98/dev
Rearranged Sources + Added (Non-Activated) WhatsApp Source (Website Currently Provides the Wrong Version)
2023-03-20 15:20:33 -04:00
Imran Remtulla
9c6068b270 Added WhatsApp (not activated) + rearranged sources 2023-03-20 15:18:55 -04:00
7 changed files with 118 additions and 20 deletions

View File

@@ -217,9 +217,9 @@
"releaseDateAsVersionExplanation": "Questa opzione dovrebbe essere usata solo per le App in cui il rilevamento della versione non funziona correttamente, ma è disponibile una data di rilascio.", "releaseDateAsVersionExplanation": "Questa opzione dovrebbe essere usata solo per le App in cui il rilevamento della versione non funziona correttamente, ma è disponibile una data di rilascio.",
"changes": "Novità", "changes": "Novità",
"releaseDate": "Data di rilascio", "releaseDate": "Data di rilascio",
"importFromURLsInFile": "Import from URLs in File (like OPML)", "importFromURLsInFile": "Importa da URL in file (come OPML)",
"versionDetection": "Version Detection", "versionDetection": "Rilevamento di versione",
"standardVersionDetection": "Standard version detection", "standardVersionDetection": "Rilevamento di versione standard",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Rimuovere l'App?", "one": "Rimuovere l'App?",
"other": "Rimuovere le App?" "other": "Rimuovere le App?"

View File

@@ -0,0 +1,75 @@
import 'package:html/parser.dart';
import 'package:http/http.dart';
import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/providers/source_provider.dart';
class WhatsApp extends AppSource {
WhatsApp() {
host = 'whatsapp.com';
}
@override
String standardizeURL(String url) {
return 'https://$host';
}
@override
Future<String> apkUrlPrefetchModifier(String apkUrl) async {
Response res = await get(Uri.parse('https://www.whatsapp.com/android'));
if (res.statusCode == 200) {
var targetLinks = parse(res.body)
.querySelectorAll('a')
.map((e) => e.attributes['href'])
.where((e) => e != null)
.where((e) =>
e!.contains('scontent.whatsapp.net') &&
e.contains('WhatsApp.apk'))
.toList();
if (targetLinks.isEmpty) {
throw NoAPKError();
}
return targetLinks[0]!;
} else {
throw getObtainiumHttpError(res);
}
}
@override
Future<APKDetails> getLatestAPKDetails(
String standardUrl,
Map<String, dynamic> additionalSettings,
) async {
Response res = await get(Uri.parse('https://www.whatsapp.com/android'));
if (res.statusCode == 200) {
var targetElements = parse(res.body)
.querySelectorAll('p')
.where((element) => element.innerHtml.contains('Version '))
.toList();
if (targetElements.isEmpty) {
throw NoVersionError();
}
var vLines = targetElements[0]
.innerHtml
.split('\n')
.where((element) => element.contains('Version '))
.toList();
if (vLines.isEmpty) {
throw NoVersionError();
}
var versionMatch = RegExp('[0-9]+(\\.[0-9]+)+').firstMatch(vLines[0]);
if (versionMatch == null) {
throw NoVersionError();
}
String version =
vLines[0].substring(versionMatch.start, versionMatch.end);
return APKDetails(
version,
[
'https://www.whatsapp.com/android?v=$version&=thisIsaPlaceholder&a=realURLPrefetchedAtDownloadTime'
],
AppNames('Meta', 'WhatsApp'));
} else {
throw getObtainiumHttpError(res);
}
}
}

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.12'; const String currentVersion = '0.11.14';
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
@@ -210,7 +210,7 @@ class _ObtainiumState extends State<Obtainium> {
{'includePrereleases': true}, {'includePrereleases': true},
null, null,
false) false)
]); ], onlyIfExists: false);
} }
if (!supportedLocales if (!supportedLocales
.map((e) => e.languageCode) .map((e) => e.languageCode)

View File

@@ -149,14 +149,14 @@ class _AddAppPageState extends State<AddAppPage> {
app.installedVersion = app.latestVersion; app.installedVersion = app.latestVersion;
} }
app.categories = pickedCategories; app.categories = pickedCategories;
await appsProvider.saveApps([app]); await appsProvider.saveApps([app], onlyIfExists: false);
return app; return app;
} }
}() }()
.then((app) { .then((app) {
if (app != null) { if (app != null) {
Navigator.push(context, Navigator.push(globalNavigatorKey.currentContext ?? context,
MaterialPageRoute(builder: (context) => AppPage(appId: app.id))); MaterialPageRoute(builder: (context) => AppPage(appId: app.id)));
} }
}).catchError((e) { }).catchError((e) {

View File

@@ -571,7 +571,21 @@ class AppsProvider with ChangeNotifier {
List<App> newApps = (await getAppsDir()) List<App> newApps = (await getAppsDir())
.listSync() .listSync()
.where((item) => item.path.toLowerCase().endsWith('.json')) .where((item) => item.path.toLowerCase().endsWith('.json'))
.map((e) => App.fromJson(jsonDecode(File(e.path).readAsStringSync()))) .map((e) {
try {
return App.fromJson(jsonDecode(File(e.path).readAsStringSync()));
} catch (err) {
if (err is FormatException) {
logs.add('Corrupt JSON when loading App (will be ignored): $e');
e.renameSync('${e.path}.corrupt');
return App(
'', '', '', '', '', '', [], 0, {}, DateTime.now(), false);
} else {
rethrow;
}
}
})
.where((element) => element.id.isNotEmpty)
.toList(); .toList();
var idsToDelete = apps.values var idsToDelete = apps.values
.map((e) => e.app.id) .map((e) => e.app.id)
@@ -614,7 +628,8 @@ class AppsProvider with ChangeNotifier {
} }
Future<void> saveApps(List<App> apps, Future<void> saveApps(List<App> apps,
{bool attemptToCorrectInstallStatus = true}) async { {bool attemptToCorrectInstallStatus = true,
bool onlyIfExists = true}) async {
attemptToCorrectInstallStatus = attemptToCorrectInstallStatus =
attemptToCorrectInstallStatus && (await doesInstalledAppsPluginWork()); attemptToCorrectInstallStatus && (await doesInstalledAppsPluginWork());
for (var app in apps) { for (var app in apps) {
@@ -625,9 +640,15 @@ class AppsProvider with ChangeNotifier {
} }
File('${(await getAppsDir()).path}/${app.id}.json') File('${(await getAppsDir()).path}/${app.id}.json')
.writeAsStringSync(jsonEncode(app.toJson())); .writeAsStringSync(jsonEncode(app.toJson()));
this.apps.update( try {
app.id, (value) => AppInMemory(app, value.downloadProgress, info), this.apps.update(
ifAbsent: () => AppInMemory(app, null, info)); app.id, (value) => AppInMemory(app, value.downloadProgress, info),
ifAbsent: onlyIfExists ? null : () => AppInMemory(app, null, info));
} catch (e) {
if (e is! ArgumentError || e.name != 'key') {
rethrow;
}
}
} }
notifyListeners(); notifyListeners();
} }
@@ -810,7 +831,7 @@ class AppsProvider with ChangeNotifier {
a.installedVersion = apps[a.id]?.app.installedVersion; a.installedVersion = apps[a.id]?.app.installedVersion;
} }
} }
await saveApps(importedApps); await saveApps(importedApps, onlyIfExists: false);
notifyListeners(); notifyListeners();
return importedApps.length; return importedApps.length;
} }
@@ -830,7 +851,7 @@ class AppsProvider with ChangeNotifier {
if (apps.containsKey(app.id)) { if (apps.containsKey(app.id)) {
errorsMap.addAll({app.id: tr('appAlreadyAdded')}); errorsMap.addAll({app.id: tr('appAlreadyAdded')});
} else { } else {
await saveApps([app]); await saveApps([app], onlyIfExists: false);
} }
} }
List<List<String>> errors = List<List<String>> errors =

View File

@@ -21,6 +21,7 @@ import 'package:obtainium/app_sources/sourceforge.dart';
import 'package:obtainium/app_sources/steammobile.dart'; import 'package:obtainium/app_sources/steammobile.dart';
import 'package:obtainium/app_sources/telegramapp.dart'; import 'package:obtainium/app_sources/telegramapp.dart';
import 'package:obtainium/app_sources/vlc.dart'; import 'package:obtainium/app_sources/vlc.dart';
import 'package:obtainium/app_sources/whatsapp.dart';
import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/components/generated_form.dart';
import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/mass_app_sources/githubstars.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart';
@@ -342,14 +343,15 @@ class SourceProvider {
Codeberg(), Codeberg(),
FDroid(), FDroid(),
IzzyOnDroid(), IzzyOnDroid(),
Mullvad(), FDroidRepo(),
Signal(),
SourceForge(), SourceForge(),
APKMirror(), APKMirror(),
FDroidRepo(), Mullvad(),
SteamMobile(), Signal(),
TelegramApp(),
VLC(), VLC(),
// WhatsApp(), // As of 2023-03-20 this is unusable as the version on the webpage is months out of date
TelegramApp(),
SteamMobile(),
NeutronCode(), NeutronCode(),
HTML() // This should ALWAYS be the last option as they are tried in order HTML() // This should ALWAYS be the last option as they are tried in order
]; ];

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.12+133 # When changing this, update the tag in main() accordingly version: 0.11.14+135 # 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'