mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-14 21:56:44 +02:00
Compare commits
14 Commits
v0.6.0-bet
...
v0.6.6-bet
Author | SHA1 | Date | |
---|---|---|---|
bd5f21984e | |||
5037d77b14 | |||
c9711c7734 | |||
76e98feeb7 | |||
03da23f77a | |||
9b99e2b302 | |||
e746ca890a | |||
9c00a7da14 | |||
4df0dd64ad | |||
7cf7ffe0de | |||
b1953435af | |||
fc7d7d11d6 | |||
9ef26b3a4a | |||
27ee6b9e88 |
@ -34,23 +34,39 @@ class FDroid implements AppSource {
|
|||||||
String standardUrl, List<String> additionalData) async {
|
String standardUrl, List<String> additionalData) async {
|
||||||
Response res = await get(Uri.parse(standardUrl));
|
Response res = await get(Uri.parse(standardUrl));
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var latestReleaseDiv =
|
var releases = parse(res.body).querySelectorAll('.package-version');
|
||||||
parse(res.body).querySelector('#latest.package-version');
|
if (releases.isEmpty) {
|
||||||
var apkUrl = latestReleaseDiv
|
throw couldNotFindReleases;
|
||||||
?.querySelector('.package-version-download a')
|
|
||||||
?.attributes['href'];
|
|
||||||
if (apkUrl == null) {
|
|
||||||
throw noAPKFound;
|
|
||||||
}
|
}
|
||||||
var version = latestReleaseDiv
|
String? latestVersion = releases[0]
|
||||||
?.querySelector('.package-version-header b')
|
.querySelector('.package-version-header b')
|
||||||
?.innerHtml
|
?.innerHtml
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.last;
|
.sublist(1)
|
||||||
if (version == null) {
|
.join(' ');
|
||||||
|
if (latestVersion == null) {
|
||||||
throw couldNotFindLatestVersion;
|
throw couldNotFindLatestVersion;
|
||||||
}
|
}
|
||||||
return APKDetails(version, [apkUrl]);
|
List<String> apkUrls = releases
|
||||||
|
.where((element) =>
|
||||||
|
element
|
||||||
|
.querySelector('.package-version-header b')
|
||||||
|
?.innerHtml
|
||||||
|
.split(' ')
|
||||||
|
.sublist(1)
|
||||||
|
.join(' ') ==
|
||||||
|
latestVersion)
|
||||||
|
.map((e) =>
|
||||||
|
e
|
||||||
|
.querySelector('.package-version-download a')
|
||||||
|
?.attributes['href'] ??
|
||||||
|
'')
|
||||||
|
.where((element) => element.isNotEmpty)
|
||||||
|
.toList();
|
||||||
|
if (apkUrls.isEmpty) {
|
||||||
|
throw noAPKFound;
|
||||||
|
}
|
||||||
|
return APKDetails(latestVersion, apkUrls);
|
||||||
} else {
|
} else {
|
||||||
throw couldNotFindReleases;
|
throw couldNotFindReleases;
|
||||||
}
|
}
|
||||||
|
@ -69,9 +69,10 @@ class GitHub implements AppSource {
|
|||||||
if (!includePrereleases && releases[i]['prerelease'] == true) {
|
if (!includePrereleases && releases[i]['prerelease'] == true) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regexFilter != null &&
|
if (regexFilter != null &&
|
||||||
!RegExp(regexFilter)
|
!RegExp(regexFilter)
|
||||||
.hasMatch((releases[i]['name'] as String).trim())) {
|
.hasMatch((releases[i]['tag_name'] as String).trim())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var apkUrls = getReleaseAPKUrls(releases[i]);
|
var apkUrls = getReleaseAPKUrls(releases[i]);
|
||||||
|
@ -28,6 +28,7 @@ class _GeneratedFormModalState extends State<GeneratedFormModal> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
values = widget.defaultValues;
|
||||||
valid = widget.initValid;
|
valid = widget.initValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import 'package:workmanager/workmanager.dart';
|
|||||||
import 'package:dynamic_color/dynamic_color.dart';
|
import 'package:dynamic_color/dynamic_color.dart';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
|
|
||||||
const String currentVersion = '0.6.0';
|
const String currentVersion = '0.6.6';
|
||||||
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
|
||||||
|
|
||||||
|
@ -121,8 +121,10 @@ class _AddAppPageState extends State<AddAppPage> {
|
|||||||
app.preferredApkIndex =
|
app.preferredApkIndex =
|
||||||
app.apkUrls.indexOf(apkUrl);
|
app.apkUrls.indexOf(apkUrl);
|
||||||
var downloadedApk =
|
var downloadedApk =
|
||||||
await appsProvider
|
await appsProvider.downloadApp(
|
||||||
.downloadApp(app);
|
app,
|
||||||
|
showOccasionalProgressToast:
|
||||||
|
true);
|
||||||
app.id = downloadedApk.appId;
|
app.id = downloadedApk.appId;
|
||||||
if (appsProvider.apps
|
if (appsProvider.apps
|
||||||
.containsKey(app.id)) {
|
.containsKey(app.id)) {
|
||||||
@ -154,7 +156,8 @@ class _AddAppPageState extends State<AddAppPage> {
|
|||||||
child: const Text('Add'))
|
child: const Text('Add'))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (pickedSource != null)
|
if (pickedSource != null &&
|
||||||
|
pickedSource!.additionalDataDefaults.isNotEmpty)
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
|
@ -62,10 +62,14 @@ class _AppPageState extends State<AppPage> {
|
|||||||
children: [
|
children: [
|
||||||
Image.memory(
|
Image.memory(
|
||||||
app!.installedInfo!.icon!,
|
app!.installedInfo!.icon!,
|
||||||
scale: 1.5,
|
height: 150,
|
||||||
|
gaplessPlayback: true,
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
: Container(),
|
: Container(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 25,
|
||||||
|
),
|
||||||
Text(
|
Text(
|
||||||
app?.installedInfo?.name ?? app?.app.name ?? 'App',
|
app?.installedInfo?.name ?? app?.app.name ?? 'App',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
|
@ -23,6 +23,7 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
var updatesOnlyFilter =
|
var updatesOnlyFilter =
|
||||||
AppsFilter(includeUptodate: false, includeNonInstalled: false);
|
AppsFilter(includeUptodate: false, includeNonInstalled: false);
|
||||||
Set<String> selectedIds = {};
|
Set<String> selectedIds = {};
|
||||||
|
DateTime? refreshingSince;
|
||||||
|
|
||||||
clearSelected() {
|
clearSelected() {
|
||||||
if (selectedIds.isNotEmpty) {
|
if (selectedIds.isNotEmpty) {
|
||||||
@ -119,8 +120,9 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
sortedApps = sortedApps.reversed.toList();
|
sortedApps = sortedApps.reversed.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
var existingUpdateIdsAllOrSelected = appsProvider
|
var existingUpdates = appsProvider.getExistingUpdates(installedOnly: true);
|
||||||
.getExistingUpdates(installedOnly: true)
|
|
||||||
|
var existingUpdateIdsAllOrSelected = existingUpdates
|
||||||
.where((element) => selectedIds.isEmpty
|
.where((element) => selectedIds.isEmpty
|
||||||
? sortedApps.where((a) => a.app.id == element).isNotEmpty
|
? sortedApps.where((a) => a.app.id == element).isNotEmpty
|
||||||
: selectedIds.contains(element))
|
: selectedIds.contains(element))
|
||||||
@ -132,15 +134,34 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
: selectedIds.contains(element))
|
: selectedIds.contains(element))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
if (settingsProvider.pinUpdates) {
|
||||||
|
var temp = [];
|
||||||
|
sortedApps = sortedApps.where((sa) {
|
||||||
|
if (existingUpdates.contains(sa.app.id)) {
|
||||||
|
temp.add(sa);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}).toList();
|
||||||
|
sortedApps = [...temp, ...sortedApps];
|
||||||
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
onRefresh: () {
|
onRefresh: () {
|
||||||
HapticFeedback.lightImpact();
|
HapticFeedback.lightImpact();
|
||||||
|
setState(() {
|
||||||
|
refreshingSince = DateTime.now();
|
||||||
|
});
|
||||||
return appsProvider.checkUpdates().catchError((e) {
|
return appsProvider.checkUpdates().catchError((e) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text(e.toString())),
|
SnackBar(content: Text(e.toString())),
|
||||||
);
|
);
|
||||||
|
}).whenComplete(() {
|
||||||
|
setState(() {
|
||||||
|
refreshingSince = null;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: CustomScrollView(slivers: <Widget>[
|
child: CustomScrollView(slivers: <Widget>[
|
||||||
@ -157,6 +178,17 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
style: Theme.of(context).textTheme.headlineMedium,
|
style: Theme.of(context).textTheme.headlineMedium,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
))),
|
))),
|
||||||
|
if (refreshingSince != null)
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: LinearProgressIndicator(
|
||||||
|
value: appsProvider.apps.values
|
||||||
|
.where((element) => !(element.app.lastUpdateCheck
|
||||||
|
?.isBefore(refreshingSince!) ??
|
||||||
|
true))
|
||||||
|
.length /
|
||||||
|
appsProvider.apps.length,
|
||||||
|
),
|
||||||
|
),
|
||||||
SliverList(
|
SliverList(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(BuildContext context, int index) {
|
(BuildContext context, int index) {
|
||||||
@ -168,7 +200,10 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
toggleAppSelected(sortedApps[index].app.id);
|
toggleAppSelected(sortedApps[index].app.id);
|
||||||
},
|
},
|
||||||
leading: sortedApps[index].installedInfo != null
|
leading: sortedApps[index].installedInfo != null
|
||||||
? Image.memory(sortedApps[index].installedInfo!.icon!)
|
? Image.memory(
|
||||||
|
sortedApps[index].installedInfo!.icon!,
|
||||||
|
gaplessPlayback: true,
|
||||||
|
)
|
||||||
: null,
|
: null,
|
||||||
title: Text(sortedApps[index].installedInfo?.name ??
|
title: Text(sortedApps[index].installedInfo?.name ??
|
||||||
sortedApps[index].app.name),
|
sortedApps[index].app.name),
|
||||||
@ -212,8 +247,15 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Text(sortedApps[index].app.installedVersion ??
|
: SingleChildScrollView(
|
||||||
'Not Installed')),
|
child: SizedBox(
|
||||||
|
width: 80,
|
||||||
|
child: Text(
|
||||||
|
sortedApps[index].app.installedVersion ??
|
||||||
|
'Not Installed',
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
)))),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (selectedIds.isNotEmpty) {
|
if (selectedIds.isNotEmpty) {
|
||||||
toggleAppSelected(sortedApps[index].app.id);
|
toggleAppSelected(sortedApps[index].app.id);
|
||||||
@ -310,15 +352,18 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
message:
|
message:
|
||||||
'${existingUpdateIdsAllOrSelected.length} update${existingUpdateIdsAllOrSelected.length == 1 ? '' : 's'} and ${newInstallIdsAllOrSelected.length} new install${newInstallIdsAllOrSelected.length == 1 ? '' : 's'}.',
|
'${existingUpdateIdsAllOrSelected.length} update${existingUpdateIdsAllOrSelected.length == 1 ? '' : 's'} and ${newInstallIdsAllOrSelected.length} new install${newInstallIdsAllOrSelected.length == 1 ? '' : 's'}.',
|
||||||
items: formInputs,
|
items: formInputs,
|
||||||
defaultValues: const ['true'],
|
defaultValues: [
|
||||||
|
'true',
|
||||||
|
existingUpdateIdsAllOrSelected.isEmpty
|
||||||
|
? 'true'
|
||||||
|
: ''
|
||||||
|
],
|
||||||
initValid: true,
|
initValid: true,
|
||||||
);
|
);
|
||||||
}).then((values) {
|
}).then((values) {
|
||||||
if (values != null) {
|
if (values != null) {
|
||||||
bool shouldInstallUpdates =
|
bool shouldInstallUpdates = values[0] == 'true';
|
||||||
values.length < 2 || values[0] == 'true';
|
bool shouldInstallNew = values[1] == 'true';
|
||||||
bool shouldInstallNew =
|
|
||||||
values.length >= 2 && values[1] == 'true';
|
|
||||||
settingsProvider
|
settingsProvider
|
||||||
.getInstallPermission()
|
.getInstallPermission()
|
||||||
.then((_) {
|
.then((_) {
|
||||||
|
@ -155,6 +155,20 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
})
|
})
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Text('Pin Updates to Top of Apps View'),
|
||||||
|
Switch(
|
||||||
|
value: settingsProvider.pinUpdates,
|
||||||
|
onChanged: (value) {
|
||||||
|
settingsProvider.pinUpdates = value;
|
||||||
|
})
|
||||||
|
],
|
||||||
|
),
|
||||||
const Divider(
|
const Divider(
|
||||||
height: 16,
|
height: 16,
|
||||||
),
|
),
|
||||||
@ -199,7 +213,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Longer intervals recommended for large App collections',
|
'Longer intervals may result in less reliable behaviour',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.labelMedium!
|
.labelMedium!
|
||||||
|
@ -8,6 +8,7 @@ import 'dart:io';
|
|||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:install_plugin_v2/install_plugin_v2.dart';
|
import 'package:install_plugin_v2/install_plugin_v2.dart';
|
||||||
import 'package:installed_apps/app_info.dart';
|
import 'package:installed_apps/app_info.dart';
|
||||||
import 'package:installed_apps/installed_apps.dart';
|
import 'package:installed_apps/installed_apps.dart';
|
||||||
@ -69,8 +70,9 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
downloadApk(String apkUrl, String fileName, Function? onProgress,
|
downloadApk(String apkUrl, String fileName, Function? onProgress,
|
||||||
Function? urlModifier,
|
Function? urlModifier) async {
|
||||||
{bool useExistingIfExists = true}) async {
|
bool useExistingIfExists =
|
||||||
|
false; // This should be an function argument, but isn't because of the partially downloaded APK issue
|
||||||
var destDir = (await getExternalStorageDirectory())!.path;
|
var destDir = (await getExternalStorageDirectory())!.path;
|
||||||
if (urlModifier != null) {
|
if (urlModifier != null) {
|
||||||
apkUrl = await urlModifier(apkUrl);
|
apkUrl = await urlModifier(apkUrl);
|
||||||
@ -115,7 +117,9 @@ class AppsProvider with ChangeNotifier {
|
|||||||
// Downloads the App (preferred URL) and returns an ApkFile object
|
// Downloads the App (preferred URL) and returns an ApkFile object
|
||||||
// If the app was already saved, updates it's download progress % in memory
|
// If the app was already saved, updates it's download progress % in memory
|
||||||
// But also works for Apps that are not saved
|
// But also works for Apps that are not saved
|
||||||
Future<DownloadedApp> downloadApp(App app) async {
|
Future<DownloadedApp> downloadApp(App app,
|
||||||
|
{bool showOccasionalProgressToast = false}) async {
|
||||||
|
int? prevProg;
|
||||||
var fileName = '${app.id}-${app.latestVersion}-${app.preferredApkIndex}';
|
var fileName = '${app.id}-${app.latestVersion}-${app.preferredApkIndex}';
|
||||||
File downloadFile = await downloadApk(app.apkUrls[app.preferredApkIndex],
|
File downloadFile = await downloadApk(app.apkUrls[app.preferredApkIndex],
|
||||||
'${app.id}-${app.latestVersion}-${app.preferredApkIndex}',
|
'${app.id}-${app.latestVersion}-${app.preferredApkIndex}',
|
||||||
@ -123,6 +127,14 @@ class AppsProvider with ChangeNotifier {
|
|||||||
if (apps[app.id] != null) {
|
if (apps[app.id] != null) {
|
||||||
apps[app.id]!.downloadProgress = progress;
|
apps[app.id]!.downloadProgress = progress;
|
||||||
}
|
}
|
||||||
|
int? prog = progress?.ceil();
|
||||||
|
if (showOccasionalProgressToast &&
|
||||||
|
(prog == 25 || prog == 50 || prog == 75) &&
|
||||||
|
prevProg != prog) {
|
||||||
|
Fluttertoast.showToast(
|
||||||
|
msg: 'Progress: $prog%', toastLength: Toast.LENGTH_SHORT);
|
||||||
|
}
|
||||||
|
prevProg = prog;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}, SourceProvider().getSource(app.url).apkUrlPrefetchModifier);
|
}, SourceProvider().getSource(app.url).apkUrlPrefetchModifier);
|
||||||
// Delete older versions of the APK if any
|
// Delete older versions of the APK if any
|
||||||
@ -291,7 +303,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If Obtainium is being installed, it should be the last one
|
// If Obtainium is being installed, it should be the last one
|
||||||
List<DownloadedApp> moveObtainiumToEnd(List<DownloadedApp> items) {
|
List<DownloadedApp> moveObtainiumToStart(List<DownloadedApp> items) {
|
||||||
String obtainiumId = 'imranr98_obtainium_${GitHub().host}';
|
String obtainiumId = 'imranr98_obtainium_${GitHub().host}';
|
||||||
DownloadedApp? temp;
|
DownloadedApp? temp;
|
||||||
items.removeWhere((element) {
|
items.removeWhere((element) {
|
||||||
@ -302,7 +314,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
if (temp != null) {
|
if (temp != null) {
|
||||||
items.add(temp!);
|
items = [temp!, ...items];
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
@ -310,8 +322,8 @@ class AppsProvider with ChangeNotifier {
|
|||||||
// TODO: Remove below line if silentupdates are ever figured out
|
// TODO: Remove below line if silentupdates are ever figured out
|
||||||
regularInstalls.addAll(silentUpdates);
|
regularInstalls.addAll(silentUpdates);
|
||||||
|
|
||||||
silentUpdates = moveObtainiumToEnd(silentUpdates);
|
silentUpdates = moveObtainiumToStart(silentUpdates);
|
||||||
regularInstalls = moveObtainiumToEnd(regularInstalls);
|
regularInstalls = moveObtainiumToStart(regularInstalls);
|
||||||
|
|
||||||
// TODO: Uncomment below if silentupdates are ever figured out
|
// TODO: Uncomment below if silentupdates are ever figured out
|
||||||
// for (var u in silentUpdates) {
|
// for (var u in silentUpdates) {
|
||||||
|
@ -55,7 +55,7 @@ class SettingsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int get updateInterval {
|
int get updateInterval {
|
||||||
var min = prefs?.getInt('updateInterval') ?? 180;
|
var min = prefs?.getInt('updateInterval') ?? 60;
|
||||||
if (!updateIntervals.contains(min)) {
|
if (!updateIntervals.contains(min)) {
|
||||||
var temp = updateIntervals[0];
|
var temp = updateIntervals[0];
|
||||||
for (var i in updateIntervals) {
|
for (var i in updateIntervals) {
|
||||||
@ -123,6 +123,15 @@ class SettingsProvider with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get pinUpdates {
|
||||||
|
return prefs?.getBool('pinUpdates') ?? true;
|
||||||
|
}
|
||||||
|
|
||||||
|
set pinUpdates(bool show) {
|
||||||
|
prefs?.setBool('pinUpdates', show);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
String? getSettingString(String settingId) {
|
String? getSettingString(String settingId) {
|
||||||
return prefs?.getString(settingId);
|
return prefs?.getString(settingId);
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,11 @@ preStandardizeUrl(String url) {
|
|||||||
if (url.toLowerCase().indexOf('https://www.') == 0) {
|
if (url.toLowerCase().indexOf('https://www.') == 0) {
|
||||||
url = 'https://${url.substring(12)}';
|
url = 'https://${url.substring(12)}';
|
||||||
}
|
}
|
||||||
|
url = url
|
||||||
|
.split('/')
|
||||||
|
.where((e) => e.isNotEmpty)
|
||||||
|
.join('/')
|
||||||
|
.replaceFirst(':/', '://');
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +210,7 @@ class SourceProvider {
|
|||||||
? name
|
? name
|
||||||
: names.name[0].toUpperCase() + names.name.substring(1),
|
: names.name[0].toUpperCase() + names.name.substring(1),
|
||||||
null,
|
null,
|
||||||
apk.version,
|
apk.version.replaceAll('/', '-'),
|
||||||
apk.apkUrls,
|
apk.apkUrls,
|
||||||
apk.apkUrls.length - 1,
|
apk.apkUrls.length - 1,
|
||||||
additionalData,
|
additionalData,
|
||||||
|
@ -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.6.0+44 # When changing this, update the tag in main() accordingly
|
version: 0.6.6+50 # 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