From 76f8cd4102adef7926dcb636bbd7c3e76d2c4001 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 29 Jul 2023 22:06:42 -0400 Subject: [PATCH] Source configuration settings changes - "Source config" refers to source-specific, app-agnostic settings - Don't use saved config for overridden sources - For overridden sources, use app-specific source config - Allow sources to show notes on add-app page (#720) --- assets/translations/bs.json | 4 ++++ assets/translations/de.json | 4 ++++ assets/translations/en.json | 4 ++++ assets/translations/es.json | 4 ++++ assets/translations/fa.json | 4 ++++ assets/translations/fr.json | 4 ++++ assets/translations/hu.json | 4 ++++ assets/translations/it.json | 4 ++++ assets/translations/ja.json | 4 ++++ assets/translations/pl.json | 4 ++++ assets/translations/ru.json | 4 ++++ assets/translations/zh.json | 4 ++++ lib/app_sources/codeberg.dart | 2 -- lib/app_sources/github.dart | 33 ++++++++++++++++++--------- lib/app_sources/gitlab.dart | 21 ++++++++++++----- lib/mass_app_sources/githubstars.dart | 2 +- lib/pages/add_app.dart | 28 ++++++++++++++++++----- lib/pages/settings.dart | 4 ++-- lib/providers/source_provider.dart | 22 +++++++++++++++++- 19 files changed, 131 insertions(+), 29 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index b0296f6..dd9c8be 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Ugasite animaciju prijelaza stranice", "reversePageTransitions": "Reverzne animacije prijelaza stranice", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 78911ce..f58b4ba 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index d6afd88..e86bf32 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index ad5789e..2708bce 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index eaa94a6..781b45b 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 6869452..1619faf 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 21c11e1..399686d 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -239,6 +239,10 @@ "disablePageTransitions": "Lap áttűnési animációk tiltása", "reversePageTransitions": "Fordított lap áttűnési animációk", "minStarCount": "Minimális csillag szám", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" diff --git a/assets/translations/it.json b/assets/translations/it.json index 064382e..e905551 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index bf70542..58129b4 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -240,6 +240,10 @@ "disablePageTransitions": "ページ遷移アニメーションを無効化する", "reversePageTransitions": "ページ遷移アニメーションを反転する", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 755db7e..360b928 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -244,6 +244,10 @@ "disablePageTransitions": "Wyłącz animacje przejścia między stronami", "reversePageTransitions": "Odwróć animacje przejścia pomiędzy stronami", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 8ce8341..68f8e6c 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Отключить анимацию перехода между страницами", "reversePageTransitions": "Реверс анимации перехода между страницами", "minStarCount": "Минимальное количество звёзд", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index c622c70..8bed1fa 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -240,6 +240,10 @@ "disablePageTransitions": "禁用页面过渡动画效果", "reversePageTransitions": "反转页面过渡动画效果", "minStarCount": "最小星标数", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index 669e0d9..8e9ef04 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -9,8 +9,6 @@ class Codeberg extends AppSource { Codeberg() { host = 'codeberg.org'; - additionalSourceSpecificSettingFormItems = []; - additionalSourceAppSpecificSettingFormItems = [ [ GeneratedFormSwitch('includePrereleases', diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 0f74c47..b6a5e2d 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -16,7 +16,7 @@ class GitHub extends AppSource { host = 'github.com'; appIdInferIsOptional = true; - additionalSourceSpecificSettingFormItems = [ + sourceConfigSettingFormItems = [ GeneratedFormTextField('github-creds', label: tr('githubPATLabel'), password: true, @@ -107,7 +107,7 @@ class GitHub extends AppSource { for (var path in possibleBuildGradleLocations) { try { var res = await sourceRequest( - '${await convertStandardUrlToAPIUrl(standardUrl)}/contents/$path'); + '${await convertStandardUrlToAPIUrl(standardUrl, additionalSettings)}/contents/$path'); if (res.statusCode == 200) { try { var body = jsonDecode(res.body); @@ -155,19 +155,30 @@ class GitHub extends AppSource { return url.substring(0, match.end); } - Future getCredentialPrefixIfAny() async { + Future getCredentialPrefixIfAny( + Map additionalSettings) async { SettingsProvider settingsProvider = SettingsProvider(); await settingsProvider.initializeSettings(); - String? creds = settingsProvider - .getSettingString(additionalSourceSpecificSettingFormItems[0].key); + var sourceConfig = + await getSourceConfigValues(additionalSettings, settingsProvider); + String? creds = sourceConfig['github-creds']; return creds != null && creds.isNotEmpty ? '$creds@' : ''; } - Future getAPIHost() async => - 'https://${await getCredentialPrefixIfAny()}api.$host'; + @override + Future getSourceNote() async { + if (!hostChanged && (await getCredentialPrefixIfAny({})).isEmpty) { + return '${tr('githubSourceNote')} ${hostChanged ? tr('addInfoBelow') : tr('addInfoInSettings')}'; + } + return null; + } - Future convertStandardUrlToAPIUrl(String standardUrl) async => - '${await getAPIHost()}/repos${standardUrl.substring('https://$host'.length)}'; + Future getAPIHost(Map additionalSettings) async => + 'https://${await getCredentialPrefixIfAny(additionalSettings)}api.$host'; + + Future convertStandardUrlToAPIUrl( + String standardUrl, Map additionalSettings) async => + '${await getAPIHost(additionalSettings)}/repos${standardUrl.substring('https://$host'.length)}'; @override String? changeLogPageFromStandardUrl(String standardUrl) => @@ -311,7 +322,7 @@ class GitHub extends AppSource { ) async { return await getLatestAPKDetailsCommon2(standardUrl, additionalSettings, (bool useTagUrl) async { - return '${await convertStandardUrlToAPIUrl(standardUrl)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100'; + return '${await convertStandardUrlToAPIUrl(standardUrl, additionalSettings)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100'; }, (Response res) { rateLimitErrorCheck(res); }); @@ -360,7 +371,7 @@ class GitHub extends AppSource { {Map querySettings = const {}}) async { return searchCommon( query, - '${await getAPIHost()}/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100', + '${await getAPIHost({})}/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100', 'items', onHttpErrorCode: (Response res) { rateLimitErrorCheck(res); }, querySettings: querySettings); diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index ec2fd94..bea24eb 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -16,7 +16,7 @@ class GitLab extends AppSource { host = 'gitlab.com'; canSearch = true; - additionalSourceSpecificSettingFormItems = [ + sourceConfigSettingFormItems = [ GeneratedFormTextField('gitlab-creds', label: tr('gitlabPATLabel'), password: true, @@ -60,18 +60,27 @@ class GitLab extends AppSource { return url.substring(0, match.end); } - Future getPATIfAny() async { + Future getPATIfAny(Map additionalSettings) async { SettingsProvider settingsProvider = SettingsProvider(); await settingsProvider.initializeSettings(); - String? creds = settingsProvider - .getSettingString(additionalSourceSpecificSettingFormItems[0].key); + var sourceConfig = + await getSourceConfigValues(additionalSettings, settingsProvider); + String? creds = sourceConfig['gitlab-creds']; return creds != null && creds.isNotEmpty ? creds : null; } + @override + Future getSourceNote() async { + if ((await getPATIfAny({})) == null) { + return '${tr('gitlabSourceNote')} ${hostChanged ? tr('addInfoBelow') : tr('addInfoInSettings')}'; + } + return null; + } + @override Future>> search(String query, {Map querySettings = const {}}) async { - String? PAT = await getPATIfAny(); + String? PAT = await getPATIfAny({}); if (PAT == null) { throw CredsNeededError(name); } @@ -103,7 +112,7 @@ class GitLab extends AppSource { ) async { bool fallbackToOlderReleases = additionalSettings['fallbackToOlderReleases'] == true; - String? PAT = await getPATIfAny(); + String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {}); Iterable apkDetailsList = []; if (PAT != null) { var names = GitHub().getAppNames(standardUrl); diff --git a/lib/mass_app_sources/githubstars.dart b/lib/mass_app_sources/githubstars.dart index 5a086f1..db8495b 100644 --- a/lib/mass_app_sources/githubstars.dart +++ b/lib/mass_app_sources/githubstars.dart @@ -16,7 +16,7 @@ class GitHubStars implements MassAppUrlSource { Future>> getOnePageOfUserStarredUrlsWithDescriptions( String username, int page) async { Response res = await get(Uri.parse( - 'https://${await GitHub().getCredentialPrefixIfAny()}api.github.com/users/$username/starred?per_page=100&page=$page')); + 'https://${await GitHub().getCredentialPrefixIfAny({})}api.github.com/users/$username/starred?per_page=100&page=$page')); if (res.statusCode == 200) { Map> urlsWithDescriptions = {}; for (var e in (jsonDecode(res.body) as List)) { diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index b31dc4d..0f8095c 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -41,6 +41,7 @@ class _AddAppPageState extends State { @override Widget build(BuildContext context) { AppsProvider appsProvider = context.read(); + SettingsProvider settingsProvider = context.watch(); bool doingSomething = gettingAppInfo || searching; @@ -85,8 +86,7 @@ class _AddAppPageState extends State { } } - Future getTrackOnlyConfirmationIfNeeded( - bool userPickedTrackOnly, SettingsProvider settingsProvider, + Future getTrackOnlyConfirmationIfNeeded(bool userPickedTrackOnly, {bool ignoreHideSetting = false}) async { var useTrackOnly = userPickedTrackOnly || pickedSource!.enforceTrackOnly; if (useTrackOnly && @@ -138,11 +138,9 @@ class _AddAppPageState extends State { gettingAppInfo = true; }); try { - var settingsProvider = context.read(); var userPickedTrackOnly = additionalSettings['trackOnly'] == true; App? app; - if ((await getTrackOnlyConfirmationIfNeeded( - userPickedTrackOnly, settingsProvider)) && + if ((await getTrackOnlyConfirmationIfNeeded(userPickedTrackOnly)) && (await getReleaseDateAsVersionConfirmationIfNeeded( userPickedTrackOnly))) { var trackOnly = pickedSource!.enforceTrackOnly || userPickedTrackOnly; @@ -410,7 +408,13 @@ class _AddAppPageState extends State { ), GeneratedForm( key: Key(pickedSource.runtimeType.toString()), - items: pickedSource!.combinedAppSpecificSettingFormItems, + items: [ + ...pickedSource!.combinedAppSpecificSettingFormItems, + ...(pickedSourceOverride != null + ? pickedSource!.sourceConfigSettingFormItems + .map((e) => [e]) + : []) + ], onValueChanges: (values, valid, isBuilding) { if (!isBuilding) { setState(() { @@ -504,6 +508,18 @@ class _AddAppPageState extends State { HTML().runtimeType.toString())) getHTMLSourceOverrideDropdown(), if (shouldShowSearchBar()) getSearchBarRow(), + if (pickedSource != null) + FutureBuilder( + builder: (ctx, val) { + return val.data != null && val.data!.isNotEmpty + ? Text( + val.data!, + style: + Theme.of(context).textTheme.bodySmall, + ) + : const SizedBox(); + }, + future: pickedSource?.getSourceNote()), const SizedBox( height: 16, ), diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 2a42376..c96c72d 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -166,9 +166,9 @@ class _SettingsPageState extends State { }); var sourceSpecificFields = sourceProvider.sources.map((e) { - if (e.additionalSourceSpecificSettingFormItems.isNotEmpty) { + if (e.sourceConfigSettingFormItems.isNotEmpty) { return GeneratedForm( - items: e.additionalSourceSpecificSettingFormItems.map((e) { + items: e.sourceConfigSettingFormItems.map((e) { e.defaultValue = settingsProvider.getSettingString(e.key); return [e]; }).toList(), diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 8ddea20..ca2c969 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -28,6 +28,7 @@ import 'package:obtainium/app_sources/vlc.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart'; +import 'package:obtainium/providers/settings_provider.dart'; class AppNames { late String author; @@ -424,12 +425,31 @@ abstract class AppSource { } // Some Sources may have additional settings at the Source level (not specific to Apps) - these use SettingsProvider - List additionalSourceSpecificSettingFormItems = []; + // If the source has been overridden, we expect the user to define one-time values as additional settings - don't use the stored values + List sourceConfigSettingFormItems = []; + Future> getSourceConfigValues( + Map additionalSettings, + SettingsProvider settingsProvider) async { + Map results = {}; + sourceConfigSettingFormItems.forEach((e) { + var val = hostChanged + ? additionalSettings[e.key] + : settingsProvider.getSettingString(e.key); + if (val != null) { + results[e.key] = val; + } + }); + return results; + } String? changeLogPageFromStandardUrl(String standardUrl) { return null; } + Future getSourceNote() async { + return null; + } + Future apkUrlPrefetchModifier( String apkUrl, String standardUrl) async { return apkUrl;