mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-08-19 13:09:30 +02:00
Merge pull request #567 from ImranR98/dev
Add Tags-Only Support for GitHub (and Codeberg) Track-Only Apps (#566), Increase Size of Changelog Touch Target (#565), Make All Sources Accessible in Override Menu (#543), Other Bugfixes
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
import 'package:http/http.dart';
|
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
|
||||||
@@ -85,7 +84,6 @@ class APKCombo extends AppSource {
|
|||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
String appId = tryInferringAppId(standardUrl)!;
|
String appId = tryInferringAppId(standardUrl)!;
|
||||||
String host = Uri.parse(standardUrl).host;
|
|
||||||
var preres = await sourceRequest(standardUrl);
|
var preres = await sourceRequest(standardUrl);
|
||||||
if (preres.statusCode != 200) {
|
if (preres.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(preres);
|
throw getObtainiumHttpError(preres);
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
import 'package:http/http.dart';
|
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
import 'dart:convert';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:http/http.dart';
|
|
||||||
import 'package:obtainium/app_sources/github.dart';
|
import 'package:obtainium/app_sources/github.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';
|
||||||
@@ -9,7 +7,6 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
class Codeberg extends AppSource {
|
class Codeberg extends AppSource {
|
||||||
Codeberg() {
|
Codeberg() {
|
||||||
host = 'codeberg.org';
|
host = 'codeberg.org';
|
||||||
overrideEligible = true;
|
|
||||||
|
|
||||||
additionalSourceSpecificSettingFormItems = [];
|
additionalSourceSpecificSettingFormItems = [];
|
||||||
|
|
||||||
@@ -58,10 +55,10 @@ class Codeberg extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
return gh.getLatestAPKDetailsCommon(
|
return await gh.getLatestAPKDetailsCommon2(standardUrl, additionalSettings,
|
||||||
'https://$host/api/v1/repos${standardUrl.substring('https://$host'.length)}/releases?per_page=100',
|
(bool useTagUrl) async {
|
||||||
standardUrl,
|
return 'https://$host/api/v1/repos${standardUrl.substring('https://$host'.length)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100';
|
||||||
additionalSettings);
|
}, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
AppNames getAppNames(String standardUrl) {
|
AppNames getAppNames(String standardUrl) {
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
import 'package:http/http.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/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
@@ -8,7 +7,6 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
class FDroidRepo extends AppSource {
|
class FDroidRepo extends AppSource {
|
||||||
FDroidRepo() {
|
FDroidRepo() {
|
||||||
name = tr('fdroidThirdPartyRepo');
|
name = tr('fdroidThirdPartyRepo');
|
||||||
overrideEligible = true;
|
|
||||||
|
|
||||||
additionalSourceAppSpecificSettingFormItems = [
|
additionalSourceAppSpecificSettingFormItems = [
|
||||||
[
|
[
|
||||||
|
@@ -13,7 +13,6 @@ import 'package:url_launcher/url_launcher_string.dart';
|
|||||||
class GitHub extends AppSource {
|
class GitHub extends AppSource {
|
||||||
GitHub() {
|
GitHub() {
|
||||||
host = 'github.com';
|
host = 'github.com';
|
||||||
overrideEligible = true;
|
|
||||||
|
|
||||||
additionalSourceSpecificSettingFormItems = [
|
additionalSourceSpecificSettingFormItems = [
|
||||||
GeneratedFormTextField('github-creds',
|
GeneratedFormTextField('github-creds',
|
||||||
@@ -143,15 +142,17 @@ class GitHub extends AppSource {
|
|||||||
} else if (b == null) {
|
} else if (b == null) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
var stdFormats = findStandardFormatsForVersion(a['tag_name'], true)
|
var nameA = a['tag_name'] ?? a['name'];
|
||||||
.intersection(findStandardFormatsForVersion(b['tag_name'], true));
|
var nameB = b['tag_name'] ?? b['name'];
|
||||||
|
var stdFormats = findStandardFormatsForVersion(nameA, true)
|
||||||
|
.intersection(findStandardFormatsForVersion(nameB, true));
|
||||||
if (stdFormats.isNotEmpty) {
|
if (stdFormats.isNotEmpty) {
|
||||||
var reg = RegExp(stdFormats.first);
|
var reg = RegExp(stdFormats.first);
|
||||||
var matchA = reg.firstMatch(a['tag_name']);
|
var matchA = reg.firstMatch(nameA);
|
||||||
var matchB = reg.firstMatch(b['tag_name']);
|
var matchB = reg.firstMatch(nameB);
|
||||||
return compareAlphaNumeric(
|
return compareAlphaNumeric(
|
||||||
(a['tag_name'] as String).substring(matchA!.start, matchA.end),
|
(nameA as String).substring(matchA!.start, matchA.end),
|
||||||
(b['tag_name'] as String).substring(matchB!.start, matchB.end));
|
(nameB as String).substring(matchB!.start, matchB.end));
|
||||||
} else {
|
} else {
|
||||||
return getReleaseDateFromRelease(a)!
|
return getReleaseDateFromRelease(a)!
|
||||||
.compareTo(getReleaseDateFromRelease(b)!);
|
.compareTo(getReleaseDateFromRelease(b)!);
|
||||||
@@ -191,7 +192,7 @@ class GitHub extends AppSource {
|
|||||||
if (targetRelease == null) {
|
if (targetRelease == null) {
|
||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
String? version = targetRelease['tag_name'];
|
String? version = targetRelease['tag_name'] ?? targetRelease['name'];
|
||||||
DateTime? releaseDate = getReleaseDateFromRelease(targetRelease);
|
DateTime? releaseDate = getReleaseDateFromRelease(targetRelease);
|
||||||
if (version == null) {
|
if (version == null) {
|
||||||
throw NoVersionError();
|
throw NoVersionError();
|
||||||
@@ -211,15 +212,35 @@ class GitHub extends AppSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getLatestAPKDetailsCommon2(
|
||||||
|
String standardUrl,
|
||||||
|
Map<String, dynamic> additionalSettings,
|
||||||
|
Future<String> Function(bool) reqUrlGenerator,
|
||||||
|
dynamic Function(Response)? onHttpErrorCode) async {
|
||||||
|
try {
|
||||||
|
return await getLatestAPKDetailsCommon(
|
||||||
|
await reqUrlGenerator(false), standardUrl, additionalSettings,
|
||||||
|
onHttpErrorCode: onHttpErrorCode);
|
||||||
|
} catch (err) {
|
||||||
|
if (err is NoReleasesError && additionalSettings['trackOnly'] == true) {
|
||||||
|
return await getLatestAPKDetailsCommon(
|
||||||
|
await reqUrlGenerator(true), standardUrl, additionalSettings,
|
||||||
|
onHttpErrorCode: onHttpErrorCode);
|
||||||
|
} else {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
return getLatestAPKDetailsCommon(
|
return await getLatestAPKDetailsCommon2(standardUrl, additionalSettings,
|
||||||
'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/releases?per_page=100',
|
(bool useTagUrl) async {
|
||||||
standardUrl,
|
return 'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100';
|
||||||
additionalSettings, onHttpErrorCode: (Response res) {
|
}, (Response res) {
|
||||||
rateLimitErrorCheck(res);
|
rateLimitErrorCheck(res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,6 @@ import 'package:url_launcher/url_launcher_string.dart';
|
|||||||
class GitLab extends AppSource {
|
class GitLab extends AppSource {
|
||||||
GitLab() {
|
GitLab() {
|
||||||
host = 'gitlab.com';
|
host = 'gitlab.com';
|
||||||
overrideEligible = true;
|
|
||||||
canSearch = true;
|
canSearch = true;
|
||||||
|
|
||||||
additionalSourceSpecificSettingFormItems = [
|
additionalSourceSpecificSettingFormItems = [
|
||||||
@@ -83,12 +82,12 @@ class GitLab extends AppSource {
|
|||||||
}
|
}
|
||||||
var json = jsonDecode(res.body) as List<dynamic>;
|
var json = jsonDecode(res.body) as List<dynamic>;
|
||||||
Map<String, List<String>> results = {};
|
Map<String, List<String>> results = {};
|
||||||
json.forEach((element) {
|
for (var element in json) {
|
||||||
results['https://$host/${element['path_with_namespace']}'] = [
|
results['https://$host/${element['path_with_namespace']}'] = [
|
||||||
element['name_with_namespace'],
|
element['name_with_namespace'],
|
||||||
element['description'] ?? tr('noDescription')
|
element['description'] ?? tr('noDescription')
|
||||||
];
|
];
|
||||||
});
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -85,10 +85,6 @@ bool _isNumeric(String s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class HTML extends AppSource {
|
class HTML extends AppSource {
|
||||||
HTML() {
|
|
||||||
overrideEligible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
// TODO: implement requestHeaders choice, hardcoded for now
|
// TODO: implement requestHeaders choice, hardcoded for now
|
||||||
Map<String, String>? get requestHeaders => {
|
Map<String, String>? get requestHeaders => {
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import 'package:http/http.dart';
|
|
||||||
import 'package:obtainium/app_sources/fdroid.dart';
|
import 'package:obtainium/app_sources/fdroid.dart';
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
@@ -6,11 +6,9 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
|
|
||||||
class Jenkins extends AppSource {
|
class Jenkins extends AppSource {
|
||||||
Jenkins() {
|
Jenkins() {
|
||||||
overrideEligible = true;
|
|
||||||
overrideVersionDetectionFormDefault('releaseDateAsVersion', true);
|
overrideVersionDetectionFormDefault('releaseDateAsVersion', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
String trimJobUrl(String url) {
|
String trimJobUrl(String url) {
|
||||||
RegExp standardUrlRegEx = RegExp('.*/job/[^/]+');
|
RegExp standardUrlRegEx = RegExp('.*/job/[^/]+');
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
|
@@ -6,7 +6,6 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
class SourceForge extends AppSource {
|
class SourceForge extends AppSource {
|
||||||
SourceForge() {
|
SourceForge() {
|
||||||
host = 'sourceforge.net';
|
host = 'sourceforge.net';
|
||||||
overrideEligible = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:obtainium/app_sources/github.dart';
|
|
||||||
import 'package:obtainium/app_sources/html.dart';
|
import 'package:obtainium/app_sources/html.dart';
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
@@ -10,7 +9,6 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
class SourceHut extends AppSource {
|
class SourceHut extends AppSource {
|
||||||
SourceHut() {
|
SourceHut() {
|
||||||
host = 'git.sr.ht';
|
host = 'git.sr.ht';
|
||||||
overrideEligible = true;
|
|
||||||
|
|
||||||
additionalSourceAppSpecificSettingFormItems = [
|
additionalSourceAppSpecificSettingFormItems = [
|
||||||
[
|
[
|
||||||
@@ -58,11 +56,19 @@ class SourceHut extends AppSource {
|
|||||||
throw NoVersionError();
|
throw NoVersionError();
|
||||||
}
|
}
|
||||||
String? releaseDateString = entry.querySelector('pubDate')?.innerHtml;
|
String? releaseDateString = entry.querySelector('pubDate')?.innerHtml;
|
||||||
var link = entry.querySelector('link');
|
|
||||||
String releasePage = '$standardUrl/refs/$version';
|
String releasePage = '$standardUrl/refs/$version';
|
||||||
DateTime? releaseDate = releaseDateString != null
|
DateTime? releaseDate;
|
||||||
? DateFormat('EEE, dd MMM yyyy HH:mm:ss Z').parse(releaseDateString)
|
try {
|
||||||
: null;
|
releaseDate = releaseDateString != null
|
||||||
|
? DateFormat('E, dd MMM yyyy HH:mm:ss Z').parse(releaseDateString)
|
||||||
|
: null;
|
||||||
|
releaseDate = releaseDateString != null
|
||||||
|
? DateFormat('EEE, dd MMM yyyy HH:mm:ss Z')
|
||||||
|
.parse(releaseDateString)
|
||||||
|
: null;
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
var res2 = await sourceRequest(releasePage);
|
var res2 = await sourceRequest(releasePage);
|
||||||
List<MapEntry<String, String>> apkUrls = [];
|
List<MapEntry<String, String>> apkUrls = [];
|
||||||
if (res2.statusCode == 200) {
|
if (res2.statusCode == 200) {
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:obtainium/app_sources/html.dart';
|
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
|
||||||
|
@@ -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.13.3';
|
const String currentVersion = '0.13.4';
|
||||||
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
|
||||||
|
|
||||||
|
@@ -321,10 +321,8 @@ class _AddAppPageState extends State<AddAppPage> {
|
|||||||
'overrideSource',
|
'overrideSource',
|
||||||
defaultValue: HTML().runtimeType.toString(),
|
defaultValue: HTML().runtimeType.toString(),
|
||||||
[
|
[
|
||||||
...sourceProvider.sources
|
...sourceProvider.sources.map(
|
||||||
.where((s) => s.overrideEligible)
|
(s) => MapEntry(s.runtimeType.toString(), s.name))
|
||||||
.map((s) =>
|
|
||||||
MapEntry(s.runtimeType.toString(), s.name))
|
|
||||||
],
|
],
|
||||||
label: tr('overrideSource'))
|
label: tr('overrideSource'))
|
||||||
]
|
]
|
||||||
|
@@ -32,6 +32,7 @@ class _AppPageState extends State<AppPage> {
|
|||||||
getUpdate(String id) {
|
getUpdate(String id) {
|
||||||
appsProvider.checkUpdate(id).catchError((e) {
|
appsProvider.checkUpdate(id).catchError((e) {
|
||||||
showError(e, context);
|
showError(e, context);
|
||||||
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -71,6 +71,7 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
});
|
});
|
||||||
return appsProvider.checkUpdates().catchError((e) {
|
return appsProvider.checkUpdates().catchError((e) {
|
||||||
showError(e, context);
|
showError(e, context);
|
||||||
|
return <App>[];
|
||||||
}).whenComplete(() {
|
}).whenComplete(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
refreshingSince = null;
|
refreshingSince = null;
|
||||||
@@ -379,6 +380,7 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
[listedApps[appIndex].app.id],
|
[listedApps[appIndex].app.id],
|
||||||
globalNavigatorKey.currentContext).catchError((e) {
|
globalNavigatorKey.currentContext).catchError((e) {
|
||||||
showError(e, context);
|
showError(e, context);
|
||||||
|
return <String>[];
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
@@ -441,37 +443,35 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
width: 10,
|
width: 10,
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink(),
|
: const SizedBox.shrink(),
|
||||||
Column(
|
GestureDetector(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
onTap: showChangesFn,
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
child: Column(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Row(mainAxisSize: MainAxisSize.min, children: [
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
Container(
|
|
||||||
constraints: BoxConstraints(
|
|
||||||
maxWidth: MediaQuery.of(context).size.width / 4),
|
|
||||||
child: Text(
|
|
||||||
getVersionText(index),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
)),
|
|
||||||
]),
|
|
||||||
Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
onTap: showChangesFn,
|
Container(
|
||||||
child: Text(
|
constraints: BoxConstraints(
|
||||||
|
maxWidth: MediaQuery.of(context).size.width / 4),
|
||||||
|
child: Text(getVersionText(index),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
textAlign: TextAlign.end)),
|
||||||
|
]),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
getChangesButtonString(index, showChangesFn != null),
|
getChangesButtonString(index, showChangesFn != null),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontStyle: FontStyle.italic,
|
fontStyle: FontStyle.italic,
|
||||||
decoration: showChangesFn != null
|
decoration: showChangesFn != null
|
||||||
? TextDecoration.underline
|
? TextDecoration.underline
|
||||||
: TextDecoration.none),
|
: TextDecoration.none),
|
||||||
))
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
))
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -540,15 +540,20 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
: FontWeight.normal)),
|
: FontWeight.normal)),
|
||||||
trailing: listedApps[index].downloadProgress != null
|
trailing: listedApps[index].downloadProgress != null
|
||||||
? SizedBox(
|
? SizedBox(
|
||||||
width: 110,
|
width: 90,
|
||||||
child: Text(tr('percentProgress', args: [
|
child: Text(
|
||||||
listedApps[index].downloadProgress! >= 0
|
listedApps[index].downloadProgress! >= 0
|
||||||
? listedApps[index]
|
? tr('percentProgress', args: [
|
||||||
.downloadProgress!
|
listedApps[index]
|
||||||
.toInt()
|
.downloadProgress!
|
||||||
.toString()
|
.toInt()
|
||||||
: tr('pleaseWait')
|
.toString()
|
||||||
])))
|
])
|
||||||
|
: tr('pleaseWait'),
|
||||||
|
textAlign: (listedApps[index].downloadProgress! >= 0)
|
||||||
|
? TextAlign.start
|
||||||
|
: TextAlign.end,
|
||||||
|
))
|
||||||
: trailingRow,
|
: trailingRow,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (selectedAppIds.isNotEmpty) {
|
if (selectedAppIds.isNotEmpty) {
|
||||||
@@ -681,6 +686,7 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
settingsProvider: settingsProvider)
|
settingsProvider: settingsProvider)
|
||||||
.catchError((e) {
|
.catchError((e) {
|
||||||
showError(e, context);
|
showError(e, context);
|
||||||
|
return <String>[];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -323,8 +323,8 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (importInProgress)
|
if (importInProgress)
|
||||||
Column(
|
const Column(
|
||||||
children: const [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 14,
|
height: 14,
|
||||||
),
|
),
|
||||||
|
@@ -7,7 +7,6 @@ import 'package:device_info_plus/device_info_plus.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:html/dom.dart';
|
import 'package:html/dom.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:obtainium/app_sources/apkcombo.dart';
|
|
||||||
import 'package:obtainium/app_sources/apkmirror.dart';
|
import 'package:obtainium/app_sources/apkmirror.dart';
|
||||||
import 'package:obtainium/app_sources/apkpure.dart';
|
import 'package:obtainium/app_sources/apkpure.dart';
|
||||||
import 'package:obtainium/app_sources/codeberg.dart';
|
import 'package:obtainium/app_sources/codeberg.dart';
|
||||||
@@ -318,7 +317,6 @@ abstract class AppSource {
|
|||||||
late String name;
|
late String name;
|
||||||
bool enforceTrackOnly = false;
|
bool enforceTrackOnly = false;
|
||||||
bool changeLogIfAnyIsMarkDown = true;
|
bool changeLogIfAnyIsMarkDown = true;
|
||||||
bool overrideEligible = false;
|
|
||||||
|
|
||||||
AppSource() {
|
AppSource() {
|
||||||
name = runtimeType.toString();
|
name = runtimeType.toString();
|
||||||
|
@@ -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.13.3+167 # When changing this, update the tag in main() accordingly
|
version: 0.13.4+168 # 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