diff --git a/assets/i18n/en_US.json b/assets/i18n/en_US.json old mode 100755 new mode 100644 diff --git a/assets/i18n/strings.i18n.json b/assets/i18n/strings.i18n.json index 667a8bf7..fa08eb02 100755 --- a/assets/i18n/strings.i18n.json +++ b/assets/i18n/strings.i18n.json @@ -164,6 +164,7 @@ "debugSectionTitle": "Debugging", "advancedSectionTitle": "Advanced", "exportSectionTitle": "Import & export", + "dataSectionTitle": "Data sources", "themeModeLabel": "App theme", "systemThemeLabel": "System", "lightThemeLabel": "Light", @@ -173,17 +174,18 @@ "languageLabel": "Language", "languageUpdated": "Language updated", "englishOption": "English", - "sourcesLabel": "Sources", - "sourcesLabelHint": "Configure the source of patches and integrations", + "sourcesLabel": "Alternative sources", + "sourcesLabelHint": "Configure the alternative sources for ReVanced Patches and ReVanced Integrations", "sourcesIntegrationsLabel": "Integrations source", + "useAlternativeSources": "Use alternative sources", + "useAlternativeSourcesHint": "Use alternative sources for ReVanced Patches and ReVanced Integrations instead of the API", "sourcesResetDialogTitle": "Reset", "sourcesResetDialogText": "Are you sure you want to reset your sources to their default values?", "apiURLResetDialogText": "Are you sure you want to reset your API URL to its default value?", - "sourcesUpdateNote": "Note: Patches will be updated to the latest version automatically.\n\nThis will reveal your IP address to the server.", + "sourcesUpdateNote": "Note: This will automatically download ReVanced Patches and ReVanced Integrations from the alternative sources.\n\nThis will connect you to the alternative source.", "apiURLLabel": "API URL", - "apiURLHint": "Configure the URL of the API to use", + "apiURLHint": "Configure the API URL of ReVanced Manager", "selectApiURL": "API URL", - "hostRepositoryLabel": "Repository API", "orgPatchesLabel": "Patches organization", "sourcesPatchesLabel": "Patches source", "orgIntegrationsLabel": "Integrations organization", diff --git a/lib/services/manager_api.dart b/lib/services/manager_api.dart index 091ddf22..a1edc3a3 100644 --- a/lib/services/manager_api.dart +++ b/lib/services/manager_api.dart @@ -53,14 +53,6 @@ class ManagerAPI { String? patchesVersion = ''; String? integrationsVersion = ''; - bool isDefaultPatchesRepo() { - return getPatchesRepo().toLowerCase() == defaultPatchesRepo; - } - - bool isDefaultIntegrationsRepo() { - return getIntegrationsRepo().toLowerCase() == defaultIntegrationsRepo; - } - Future initialize() async { _prefs = await SharedPreferences.getInstance(); isRooted = await _rootAPI.isRooted(); @@ -73,14 +65,23 @@ class ManagerAPI { } // Migrate to new API URL if not done yet as the old one is sunset. - final bool hasMigrated = _prefs.getBool('migratedToNewApiUrl') ?? false; - if (!hasMigrated) { + final bool hasMigratedToNewApi = _prefs.getBool('migratedToNewApiUrl') ?? false; + if (!hasMigratedToNewApi) { final String apiUrl = getApiUrl().toLowerCase(); if (apiUrl.contains('releases.revanced.app')) { await setApiUrl(''); // Reset to default. _prefs.setBool('migratedToNewApiUrl', true); } } + + final bool hasMigratedToAlternativeSource = _prefs.getBool('migratedToAlternativeSource') ?? false; + if (!hasMigratedToAlternativeSource) { + final String patchesRepo = getPatchesRepo(); + final String integrationsRepo = getIntegrationsRepo(); + final bool usingAlternativeSources = patchesRepo.toLowerCase() != defaultPatchesRepo || integrationsRepo.toLowerCase() != defaultIntegrationsRepo; + _prefs.setBool('useAlternativeSources', usingAlternativeSources); + _prefs.setBool('migratedToAlternativeSource', true); + } } Future getSdkVersion() async { @@ -102,14 +103,7 @@ class ManagerAPI { } String getRepoUrl() { - return _prefs.getString('repoUrl') ?? defaultRepoUrl; - } - - Future setRepoUrl(String url) async { - if (url.isEmpty || url == ' ') { - url = defaultRepoUrl; - } - await _prefs.setString('repoUrl', url); + return defaultRepoUrl; } String getPatchesDownloadURL() { @@ -219,6 +213,15 @@ class ManagerAPI { await _prefs.setStringList('usedPatches-$packageName', patchesJson); } + void useAlternativeSources(bool value) { + _prefs.setBool('useAlternativeSources', value); + _toast.showBottom(t.settingsView.restartAppForChanges); + } + + bool isUsingAlternativeSources() { + return _prefs.getBool('useAlternativeSources') ?? false; + } + Option? getPatchOption(String packageName, String patchName, String key) { final String? optionJson = _prefs.getString('patchOption-$packageName-$patchName-$key'); @@ -416,7 +419,7 @@ class ManagerAPI { Future downloadPatches() async { try { - final String repoName = getPatchesRepo(); + final String repoName = !isUsingAlternativeSources() ? defaultPatchesRepo : getPatchesRepo(); final String currentVersion = await getCurrentPatchesVersion(); final String url = getPatchesDownloadURL(); return await _githubAPI.getPatchesReleaseFile( @@ -435,7 +438,7 @@ class ManagerAPI { Future downloadIntegrations() async { try { - final String repoName = getIntegrationsRepo(); + final String repoName = !isUsingAlternativeSources() ? defaultIntegrationsRepo : getIntegrationsRepo(); final String currentVersion = await getCurrentIntegrationsVersion(); final String url = getIntegrationsDownloadURL(); return await _githubAPI.getPatchesReleaseFile( @@ -460,7 +463,7 @@ class ManagerAPI { } Future getLatestPatchesReleaseTime() async { - if (isDefaultPatchesRepo()) { + if (!isUsingAlternativeSources()) { return await _revancedAPI.getLatestReleaseTime( '.json', defaultPatchesRepo, @@ -493,7 +496,7 @@ class ManagerAPI { } Future getLatestIntegrationsVersion() async { - if (isDefaultIntegrationsRepo()) { + if (!isUsingAlternativeSources()) { return await _revancedAPI.getLatestReleaseVersion( '.apk', defaultIntegrationsRepo, @@ -509,7 +512,7 @@ class ManagerAPI { } Future getLatestPatchesVersion() async { - if (isDefaultPatchesRepo()) { + if (!isUsingAlternativeSources()) { return await _revancedAPI.getLatestReleaseVersion( '.json', defaultPatchesRepo, diff --git a/lib/services/revanced_api.dart b/lib/services/revanced_api.dart index 2c22d23e..cc62f0d5 100644 --- a/lib/services/revanced_api.dart +++ b/lib/services/revanced_api.dart @@ -33,7 +33,7 @@ class RevancedAPI { final response = await _dio.get('/contributors'); final List repositories = response.data['repositories']; for (final Map repo in repositories) { - final String name = repo['name'].toLowerCase(); + final String name = repo['name']; contributors[name] = repo['contributors']; } } on Exception catch (e) { @@ -58,7 +58,7 @@ class RevancedAPI { final List tools = response.data['tools']; return tools.firstWhereOrNull( (t) => - (t['repository'] as String).toLowerCase() == repoName.toLowerCase() && + (t['repository'] as String) == repoName && (t['name'] as String).endsWith(extension), ); } on Exception catch (e) { diff --git a/lib/ui/views/contributors/contributors_viewmodel.dart b/lib/ui/views/contributors/contributors_viewmodel.dart index 3085683c..785148f5 100644 --- a/lib/ui/views/contributors/contributors_viewmodel.dart +++ b/lib/ui/views/contributors/contributors_viewmodel.dart @@ -14,9 +14,9 @@ class ContributorsViewModel extends BaseViewModel { final Map> contributors = await _managerAPI.getContributors(); patcherContributors = contributors[_managerAPI.defaultPatcherRepo] ?? []; - patchesContributors = contributors[_managerAPI.getPatchesRepo().toLowerCase()] ?? []; + patchesContributors = contributors[_managerAPI.defaultPatchesRepo] ?? []; integrationsContributors = - contributors[_managerAPI.getIntegrationsRepo().toLowerCase()] ?? []; + contributors[_managerAPI.defaultIntegrationsRepo] ?? []; cliContributors = contributors[_managerAPI.defaultCliRepo] ?? []; managerContributors = contributors[_managerAPI.defaultManagerRepo] ?? []; notifyListeners(); diff --git a/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart b/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart index 1e7daabc..14f3fec4 100644 --- a/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart +++ b/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart @@ -12,17 +12,14 @@ class SManageSources extends BaseViewModel { final ManagerAPI _managerAPI = locator(); final Toast _toast = locator(); - final TextEditingController _hostSourceController = TextEditingController(); final TextEditingController _orgPatSourceController = TextEditingController(); final TextEditingController _patSourceController = TextEditingController(); final TextEditingController _orgIntSourceController = TextEditingController(); final TextEditingController _intSourceController = TextEditingController(); Future showSourcesDialog(BuildContext context) async { - final String hostRepository = _managerAPI.getRepoUrl(); final String patchesRepo = _managerAPI.getPatchesRepo(); final String integrationsRepo = _managerAPI.getIntegrationsRepo(); - _hostSourceController.text = hostRepository; _orgPatSourceController.text = patchesRepo.split('/')[0]; _patSourceController.text = patchesRepo.split('/')[1]; _orgIntSourceController.text = integrationsRepo.split('/')[0]; @@ -44,26 +41,6 @@ class SManageSources extends BaseViewModel { content: SingleChildScrollView( child: Column( children: [ - /* - API for accessing the specified repositories - If default is used, will use the ReVanced API - */ - TextField( - controller: _hostSourceController, - autocorrect: false, - onChanged: (value) => notifyListeners(), - decoration: InputDecoration( - icon: Icon( - Icons.rocket_launch_outlined, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - border: const OutlineInputBorder(), - labelText: t.settingsView.hostRepositoryLabel, - hintText: hostRepository, - ), - ), - const SizedBox(height: 8), - // Patches owner's name TextField( controller: _orgPatSourceController, autocorrect: false, @@ -144,7 +121,6 @@ class SManageSources extends BaseViewModel { ), FilledButton( onPressed: () { - _managerAPI.setRepoUrl(_hostSourceController.text.trim()); _managerAPI.setPatchesRepo( '${_orgPatSourceController.text.trim()}/${_patSourceController.text.trim()}', ); @@ -176,7 +152,6 @@ class SManageSources extends BaseViewModel { ), FilledButton( onPressed: () { - _managerAPI.setRepoUrl(''); _managerAPI.setPatchesRepo(''); _managerAPI.setIntegrationsRepo(''); _managerAPI.setCurrentPatchesVersion('0.0.0'); diff --git a/lib/ui/views/settings/settings_view.dart b/lib/ui/views/settings/settings_view.dart index 9ae5df62..93151b7d 100644 --- a/lib/ui/views/settings/settings_view.dart +++ b/lib/ui/views/settings/settings_view.dart @@ -7,6 +7,7 @@ import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_upd import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_update_theme.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_advanced_section.dart'; +import 'package:revanced_manager/ui/widgets/settingsView/settings_data_section.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_debug_section.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_export_section.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_team_section.dart'; @@ -49,6 +50,8 @@ class SettingsView extends StatelessWidget { _settingsDivider, SAdvancedSection(), _settingsDivider, + SDataSection(), + _settingsDivider, SExportSection(), _settingsDivider, STeamSection(), diff --git a/lib/ui/views/settings/settings_viewmodel.dart b/lib/ui/views/settings/settings_viewmodel.dart index 09c0ce70..8dbfefc4 100644 --- a/lib/ui/views/settings/settings_viewmodel.dart +++ b/lib/ui/views/settings/settings_viewmodel.dart @@ -53,6 +53,17 @@ class SettingsViewModel extends BaseViewModel { return _managerAPI.isPatchesChangeEnabled(); } + void useAlternativeSources(bool value) { + _managerAPI.useAlternativeSources(value); + _managerAPI.setCurrentPatchesVersion('0.0.0'); + _managerAPI.setCurrentIntegrationsVersion('0.0.0'); + notifyListeners(); + } + + bool isUsingAlternativeSources() { + return _managerAPI.isUsingAlternativeSources(); + } + Future showPatchesChangeEnableDialog( bool value, BuildContext context, diff --git a/lib/ui/widgets/settingsView/settings_advanced_section.dart b/lib/ui/widgets/settingsView/settings_advanced_section.dart index 45fa8919..3287f61b 100644 --- a/lib/ui/widgets/settingsView/settings_advanced_section.dart +++ b/lib/ui/widgets/settingsView/settings_advanced_section.dart @@ -2,8 +2,6 @@ import 'package:flutter/material.dart'; import 'package:revanced_manager/gen/strings.g.dart'; -import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_api_url.dart'; -import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_sources.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_auto_update_patches.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_enable_patches_selection.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_require_suggested_app_version.dart'; @@ -26,8 +24,6 @@ class SAdvancedSection extends StatelessWidget { SRequireSuggestedAppVersion(), SVersionCompatibilityCheck(), SUniversalPatches(), - SManageSourcesUI(), - SManageApiUrlUI(), ], ); } diff --git a/lib/ui/widgets/settingsView/settings_data_section.dart b/lib/ui/widgets/settingsView/settings_data_section.dart new file mode 100644 index 00000000..b464038e --- /dev/null +++ b/lib/ui/widgets/settingsView/settings_data_section.dart @@ -0,0 +1,22 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:flutter/material.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; +import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_api_url.dart'; +import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart'; +import 'package:revanced_manager/ui/widgets/settingsView/settings_use_alternative_sources.dart'; + +class SDataSection extends StatelessWidget { + const SDataSection({super.key}); + + @override + Widget build(BuildContext context) { + return SettingsSection( + title: t.settingsView.dataSectionTitle, + children: const [ + SManageApiUrlUI(), + SUseAlternativeSources(), + ], + ); + } +} diff --git a/lib/ui/widgets/settingsView/settings_use_alternative_sources.dart b/lib/ui/widgets/settingsView/settings_use_alternative_sources.dart new file mode 100644 index 00000000..2876288f --- /dev/null +++ b/lib/ui/widgets/settingsView/settings_use_alternative_sources.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; +import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_sources.dart'; +import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; +import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart'; + +class SUseAlternativeSources extends StatefulWidget { + const SUseAlternativeSources({super.key}); + + @override + State createState() => _SUseAlternativeSourcesState(); +} + +final _settingsViewModel = SettingsViewModel(); + +class _SUseAlternativeSourcesState extends State { + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + HapticSwitchListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), + title: Text( + t.settingsView.useAlternativeSources, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + ), + ), + subtitle: Text(t.settingsView.useAlternativeSourcesHint), + value: _settingsViewModel.isUsingAlternativeSources(), + onChanged: (value) { + _settingsViewModel.useAlternativeSources(value); + setState(() {}); + }, + ), + if (_settingsViewModel.isUsingAlternativeSources()) + const SManageSourcesUI(), + ], + ); + } +}