Skip to content

Commit

Permalink
feat: Add a toggle for alternative sources (#1686)
Browse files Browse the repository at this point in the history
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
  • Loading branch information
TheAabedKhan and oSumAtrIX committed Feb 19, 2024
1 parent ce5088a commit f89c742
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 61 deletions.
Empty file modified assets/i18n/en_US.json 100755 → 100644
Empty file.
12 changes: 7 additions & 5 deletions assets/i18n/strings.i18n.json
Expand Up @@ -164,6 +164,7 @@
"debugSectionTitle": "Debugging",
"advancedSectionTitle": "Advanced",
"exportSectionTitle": "Import & export",
"dataSectionTitle": "Data sources",
"themeModeLabel": "App theme",
"systemThemeLabel": "System",
"lightThemeLabel": "Light",
Expand All @@ -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",
Expand Down
49 changes: 26 additions & 23 deletions lib/services/manager_api.dart
Expand Up @@ -53,14 +53,6 @@ class ManagerAPI {
String? patchesVersion = '';
String? integrationsVersion = '';

bool isDefaultPatchesRepo() {
return getPatchesRepo().toLowerCase() == defaultPatchesRepo;
}

bool isDefaultIntegrationsRepo() {
return getIntegrationsRepo().toLowerCase() == defaultIntegrationsRepo;
}

Future<void> initialize() async {
_prefs = await SharedPreferences.getInstance();
isRooted = await _rootAPI.isRooted();
Expand All @@ -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<int> getSdkVersion() async {
Expand All @@ -102,14 +103,7 @@ class ManagerAPI {
}

String getRepoUrl() {
return _prefs.getString('repoUrl') ?? defaultRepoUrl;
}

Future<void> setRepoUrl(String url) async {
if (url.isEmpty || url == ' ') {
url = defaultRepoUrl;
}
await _prefs.setString('repoUrl', url);
return defaultRepoUrl;
}

String getPatchesDownloadURL() {
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -416,7 +419,7 @@ class ManagerAPI {

Future<File?> 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(
Expand All @@ -435,7 +438,7 @@ class ManagerAPI {

Future<File?> 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(
Expand All @@ -460,7 +463,7 @@ class ManagerAPI {
}

Future<String?> getLatestPatchesReleaseTime() async {
if (isDefaultPatchesRepo()) {
if (!isUsingAlternativeSources()) {
return await _revancedAPI.getLatestReleaseTime(
'.json',
defaultPatchesRepo,
Expand Down Expand Up @@ -493,7 +496,7 @@ class ManagerAPI {
}

Future<String?> getLatestIntegrationsVersion() async {
if (isDefaultIntegrationsRepo()) {
if (!isUsingAlternativeSources()) {
return await _revancedAPI.getLatestReleaseVersion(
'.apk',
defaultIntegrationsRepo,
Expand All @@ -509,7 +512,7 @@ class ManagerAPI {
}

Future<String?> getLatestPatchesVersion() async {
if (isDefaultPatchesRepo()) {
if (!isUsingAlternativeSources()) {
return await _revancedAPI.getLatestReleaseVersion(
'.json',
defaultPatchesRepo,
Expand Down
4 changes: 2 additions & 2 deletions lib/services/revanced_api.dart
Expand Up @@ -33,7 +33,7 @@ class RevancedAPI {
final response = await _dio.get('/contributors');
final List<dynamic> repositories = response.data['repositories'];
for (final Map<String, dynamic> repo in repositories) {
final String name = repo['name'].toLowerCase();
final String name = repo['name'];
contributors[name] = repo['contributors'];
}
} on Exception catch (e) {
Expand All @@ -58,7 +58,7 @@ class RevancedAPI {
final List<dynamic> 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) {
Expand Down
4 changes: 2 additions & 2 deletions lib/ui/views/contributors/contributors_viewmodel.dart
Expand Up @@ -14,9 +14,9 @@ class ContributorsViewModel extends BaseViewModel {
final Map<String, List<dynamic>> 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();
Expand Down
Expand Up @@ -12,17 +12,14 @@ class SManageSources extends BaseViewModel {
final ManagerAPI _managerAPI = locator<ManagerAPI>();
final Toast _toast = locator<Toast>();

final TextEditingController _hostSourceController = TextEditingController();
final TextEditingController _orgPatSourceController = TextEditingController();
final TextEditingController _patSourceController = TextEditingController();
final TextEditingController _orgIntSourceController = TextEditingController();
final TextEditingController _intSourceController = TextEditingController();

Future<void> 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];
Expand All @@ -44,26 +41,6 @@ class SManageSources extends BaseViewModel {
content: SingleChildScrollView(
child: Column(
children: <Widget>[
/*
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,
Expand Down Expand Up @@ -144,7 +121,6 @@ class SManageSources extends BaseViewModel {
),
FilledButton(
onPressed: () {
_managerAPI.setRepoUrl(_hostSourceController.text.trim());
_managerAPI.setPatchesRepo(
'${_orgPatSourceController.text.trim()}/${_patSourceController.text.trim()}',
);
Expand Down Expand Up @@ -176,7 +152,6 @@ class SManageSources extends BaseViewModel {
),
FilledButton(
onPressed: () {
_managerAPI.setRepoUrl('');
_managerAPI.setPatchesRepo('');
_managerAPI.setIntegrationsRepo('');
_managerAPI.setCurrentPatchesVersion('0.0.0');
Expand Down
3 changes: 3 additions & 0 deletions lib/ui/views/settings/settings_view.dart
Expand Up @@ -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';
Expand Down Expand Up @@ -49,6 +50,8 @@ class SettingsView extends StatelessWidget {
_settingsDivider,
SAdvancedSection(),
_settingsDivider,
SDataSection(),
_settingsDivider,
SExportSection(),
_settingsDivider,
STeamSection(),
Expand Down
11 changes: 11 additions & 0 deletions lib/ui/views/settings/settings_viewmodel.dart
Expand Up @@ -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<void> showPatchesChangeEnableDialog(
bool value,
BuildContext context,
Expand Down
4 changes: 0 additions & 4 deletions lib/ui/widgets/settingsView/settings_advanced_section.dart
Expand Up @@ -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';
Expand All @@ -26,8 +24,6 @@ class SAdvancedSection extends StatelessWidget {
SRequireSuggestedAppVersion(),
SVersionCompatibilityCheck(),
SUniversalPatches(),
SManageSourcesUI(),
SManageApiUrlUI(),
],
);
}
Expand Down
22 changes: 22 additions & 0 deletions 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 <Widget>[
SManageApiUrlUI(),
SUseAlternativeSources(),
],
);
}
}
43 changes: 43 additions & 0 deletions 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<SUseAlternativeSources> createState() => _SUseAlternativeSourcesState();
}

final _settingsViewModel = SettingsViewModel();

class _SUseAlternativeSourcesState extends State<SUseAlternativeSources> {
@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(),
],
);
}
}

0 comments on commit f89c742

Please sign in to comment.