mirror of
https://github.com/revanced/revanced-manager.git
synced 2025-04-29 21:44:26 +02:00
feat: Use ReVanced API v4
This commit is contained in:
parent
44b8d4ceee
commit
7b7d91d661
@ -30,6 +30,7 @@ class ManagerAPI {
|
|||||||
final String patcherRepo = 'revanced-patcher';
|
final String patcherRepo = 'revanced-patcher';
|
||||||
final String cliRepo = 'revanced-cli';
|
final String cliRepo = 'revanced-cli';
|
||||||
late SharedPreferences _prefs;
|
late SharedPreferences _prefs;
|
||||||
|
Map<String, List>? contributors;
|
||||||
List<Patch> patches = [];
|
List<Patch> patches = [];
|
||||||
List<Option> options = [];
|
List<Option> options = [];
|
||||||
Patch? selectedPatch;
|
Patch? selectedPatch;
|
||||||
@ -44,7 +45,7 @@ class ManagerAPI {
|
|||||||
String keystoreFile =
|
String keystoreFile =
|
||||||
'/sdcard/Android/data/app.revanced.manager.flutter/files/revanced-manager.keystore';
|
'/sdcard/Android/data/app.revanced.manager.flutter/files/revanced-manager.keystore';
|
||||||
String defaultKeystorePassword = 's3cur3p@ssw0rd';
|
String defaultKeystorePassword = 's3cur3p@ssw0rd';
|
||||||
String defaultApiUrl = 'https://api.revanced.app/v3';
|
String defaultApiUrl = 'https://api.revanced.app/v4';
|
||||||
String defaultRepoUrl = 'https://api.github.com';
|
String defaultRepoUrl = 'https://api.github.com';
|
||||||
String defaultPatcherRepo = 'revanced/revanced-patcher';
|
String defaultPatcherRepo = 'revanced/revanced-patcher';
|
||||||
String defaultPatchesRepo = 'revanced/revanced-patches';
|
String defaultPatchesRepo = 'revanced/revanced-patches';
|
||||||
@ -66,16 +67,23 @@ class ManagerAPI {
|
|||||||
releaseBuild = !(await getCurrentManagerVersion()).contains('-dev');
|
releaseBuild = !(await getCurrentManagerVersion()).contains('-dev');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate to new API URL if not done yet as the old one is sunset.
|
final hasMigratedToNewMigrationSystem = _prefs.getBool('migratedToNewApiPrefSystem') ?? false;
|
||||||
final bool hasMigratedToLatestApi =
|
if (!hasMigratedToNewMigrationSystem) {
|
||||||
_prefs.getBool('migratedToLatestApiUrl') ?? false;
|
final apiUrl = getApiUrl().toLowerCase();
|
||||||
if (!hasMigratedToLatestApi) {
|
|
||||||
final String apiUrl = getApiUrl().toLowerCase();
|
final isReleases = apiUrl.contains('releases.revanced.app');
|
||||||
if (apiUrl.contains('releases.revanced.app') ||
|
final isV2 = apiUrl.contains('api.revanced.app/v2');
|
||||||
(apiUrl.contains('api.revanced.app') &&
|
final isV3 = apiUrl.contains('api.revanced.app/v3');
|
||||||
!apiUrl.contains('v3'))) {
|
|
||||||
await setApiUrl(''); // Reset to default.
|
if (isReleases || isV2 || isV3) {
|
||||||
_prefs.setBool('migratedToLatestApiUrl', true);
|
await resetApiUrl();
|
||||||
|
// At this point, the preference is removed.
|
||||||
|
// Now, no more migration is needed because:
|
||||||
|
// If the user touches the API URL,
|
||||||
|
// it will be remembered forever as intended.
|
||||||
|
// On the other hand, if the user resets it or sets it to the default,
|
||||||
|
// the URL will be updated whenever the app is updated.
|
||||||
|
_prefs.setBool('migratedToNewApiPrefSystem', true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,12 +107,25 @@ class ManagerAPI {
|
|||||||
return _prefs.getString('apiUrl') ?? defaultApiUrl;
|
return _prefs.getString('apiUrl') ?? defaultApiUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setApiUrl(String url) async {
|
Future<void> resetApiUrl() async {
|
||||||
if (url.isEmpty || url == ' ') {
|
await _prefs.remove('apiUrl');
|
||||||
url = defaultApiUrl;
|
|
||||||
}
|
|
||||||
await _revancedAPI.clearAllCache();
|
await _revancedAPI.clearAllCache();
|
||||||
|
_toast.showBottom(t.settingsView.restartAppForChanges);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setApiUrl(String url) async {
|
||||||
|
url = url.toLowerCase();
|
||||||
|
|
||||||
|
if (url == defaultApiUrl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!url.startsWith('http')) {
|
||||||
|
url = 'https://$url';
|
||||||
|
}
|
||||||
|
|
||||||
await _prefs.setString('apiUrl', url);
|
await _prefs.setString('apiUrl', url);
|
||||||
|
await _revancedAPI.clearAllCache();
|
||||||
_toast.showBottom(t.settingsView.restartAppForChanges);
|
_toast.showBottom(t.settingsView.restartAppForChanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +427,7 @@ class ManagerAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, List<dynamic>>> getContributors() async {
|
Future<Map<String, List<dynamic>>> getContributors() async {
|
||||||
return await _revancedAPI.getContributors();
|
return contributors ??= await _revancedAPI.getContributors();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Patch>> getPatches() async {
|
Future<List<Patch>> getPatches() async {
|
||||||
@ -438,6 +459,10 @@ class ManagerAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<File?> downloadPatches() async {
|
Future<File?> downloadPatches() async {
|
||||||
|
if (!isUsingAlternativeSources()) {
|
||||||
|
return await _revancedAPI.getLatestReleaseFile('patches');
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final String repoName = getPatchesRepo();
|
final String repoName = getPatchesRepo();
|
||||||
final String currentVersion = await getCurrentPatchesVersion();
|
final String currentVersion = await getCurrentPatchesVersion();
|
||||||
|
@ -51,7 +51,7 @@ class RevancedAPI {
|
|||||||
}
|
}
|
||||||
return getToolsLock.synchronized(() async {
|
return getToolsLock.synchronized(() async {
|
||||||
try {
|
try {
|
||||||
final response = await _dio.get('/$toolName/latest');
|
final response = await _dio.get('/$toolName');
|
||||||
return response.data;
|
return response.data;
|
||||||
} on Exception catch (e) {
|
} on Exception catch (e) {
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
@ -89,7 +89,7 @@ class RevancedAPI {
|
|||||||
toolName,
|
toolName,
|
||||||
);
|
);
|
||||||
if (release != null) {
|
if (release != null) {
|
||||||
final String url = release['assets'][0]['download_url'];
|
final String url = release['download_url'];
|
||||||
return await _downloadManager.getSingleFile(url);
|
return await _downloadManager.getSingleFile(url);
|
||||||
}
|
}
|
||||||
} on Exception catch (e) {
|
} on Exception catch (e) {
|
||||||
|
@ -30,25 +30,13 @@ class ContributorsView extends StatelessWidget {
|
|||||||
sliver: SliverList(
|
sliver: SliverList(
|
||||||
delegate: SliverChildListDelegate.fixed(
|
delegate: SliverChildListDelegate.fixed(
|
||||||
<Widget>[
|
<Widget>[
|
||||||
ContributorsCard(
|
for (final String tool in model.contributors.keys) ...[
|
||||||
title: 'ReVanced Patcher',
|
ContributorsCard(
|
||||||
contributors: model.patcherContributors,
|
title: tool,
|
||||||
),
|
contributors: model.contributors[tool]!,
|
||||||
const SizedBox(height: 20),
|
),
|
||||||
ContributorsCard(
|
const SizedBox(height: 20),
|
||||||
title: 'ReVanced Patches',
|
],
|
||||||
contributors: model.patchesContributors,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
ContributorsCard(
|
|
||||||
title: 'ReVanced CLI',
|
|
||||||
contributors: model.cliContributors,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
ContributorsCard(
|
|
||||||
title: 'ReVanced Manager',
|
|
||||||
contributors: model.managerContributors,
|
|
||||||
),
|
|
||||||
SizedBox(height: MediaQuery.viewPaddingOf(context).bottom),
|
SizedBox(height: MediaQuery.viewPaddingOf(context).bottom),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -4,20 +4,10 @@ import 'package:stacked/stacked.dart';
|
|||||||
|
|
||||||
class ContributorsViewModel extends BaseViewModel {
|
class ContributorsViewModel extends BaseViewModel {
|
||||||
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
||||||
List<dynamic> patcherContributors = [];
|
Map<String, List<dynamic>> contributors = {};
|
||||||
List<dynamic> patchesContributors = [];
|
|
||||||
List<dynamic> cliContributors = [];
|
|
||||||
List<dynamic> managerContributors = [];
|
|
||||||
|
|
||||||
String repoName(String repo) => repo.split('/').last;
|
|
||||||
|
|
||||||
Future<void> getContributors() async {
|
Future<void> getContributors() async {
|
||||||
final Map<String, List<dynamic>> contributors =
|
contributors = await _managerAPI.getContributors();
|
||||||
await _managerAPI.getContributors();
|
|
||||||
patcherContributors = contributors[repoName(_managerAPI.defaultPatcherRepo)] ?? [];
|
|
||||||
patchesContributors = contributors[repoName(_managerAPI.defaultPatchesRepo)] ?? [];
|
|
||||||
cliContributors = contributors[repoName(_managerAPI.defaultCliRepo)] ?? [];
|
|
||||||
managerContributors = contributors[repoName(_managerAPI.defaultManagerRepo)] ?? [];
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,9 @@ class SManageApiUrl extends BaseViewModel {
|
|||||||
final TextEditingController _apiUrlController = TextEditingController();
|
final TextEditingController _apiUrlController = TextEditingController();
|
||||||
|
|
||||||
Future<void> showApiUrlDialog(BuildContext context) async {
|
Future<void> showApiUrlDialog(BuildContext context) async {
|
||||||
final String apiUrl = _managerAPI.getApiUrl();
|
final apiUrl = _managerAPI.getApiUrl();
|
||||||
_apiUrlController.text = apiUrl.replaceAll('https://', '');
|
|
||||||
|
_apiUrlController.text = apiUrl;
|
||||||
return showDialog(
|
return showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
@ -60,11 +61,7 @@ class SManageApiUrl extends BaseViewModel {
|
|||||||
),
|
),
|
||||||
FilledButton(
|
FilledButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
String apiUrl = _apiUrlController.text;
|
_managerAPI.setApiUrl(_apiUrlController.text);
|
||||||
if (!apiUrl.startsWith('https')) {
|
|
||||||
apiUrl = 'https://$apiUrl';
|
|
||||||
}
|
|
||||||
_managerAPI.setApiUrl(apiUrl);
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
child: Text(t.okButton),
|
child: Text(t.okButton),
|
||||||
@ -87,7 +84,7 @@ class SManageApiUrl extends BaseViewModel {
|
|||||||
),
|
),
|
||||||
FilledButton(
|
FilledButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_managerAPI.setApiUrl('');
|
_managerAPI.resetApiUrl();
|
||||||
Navigator.of(context)
|
Navigator.of(context)
|
||||||
..pop()
|
..pop()
|
||||||
..pop();
|
..pop();
|
||||||
|
@ -49,7 +49,7 @@ class _ContributorsCardState extends State<ContributorsCard> {
|
|||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => launchUrl(
|
onTap: () => launchUrl(
|
||||||
Uri.parse(
|
Uri.parse(
|
||||||
widget.contributors[index]['html_url'],
|
widget.contributors[index]['url'],
|
||||||
),
|
),
|
||||||
mode: LaunchMode.externalApplication,
|
mode: LaunchMode.externalApplication,
|
||||||
),
|
),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user