Compare commits

..

12 Commits

13 changed files with 198 additions and 44 deletions

View File

@ -22,7 +22,8 @@ jobs:
uses: crowdin/github-action@1.5.0
with:
config: crowdin.yml
upload_translations: true
upload_sources: true
upload_translations: false
download_translations: true
push_translations: true
create_pull_request: false
@ -42,4 +43,4 @@ jobs:
# git checkout flutter
# git add *
# git merge i18n_flutter
# git push
# git push

View File

@ -28,7 +28,7 @@ If you wish to translate ReVanced Manager, we're accepting translations on [Crow
## 🛠️ Building Manager from source
1. Setup flutter environment for your [platform](https://docs.flutter.dev/get-started/install)
2. Clone the repository locally
3. Add your github token in gradle.properties like [this](https://github.com/revanced/revanced-documentation/wiki/Building-from-source)
3. Add your github token in gradle.properties like [this](https://github.com/revanced/revanced-documentation/blob/main/docs/revanced-development/2_building_from_source.md)
4. Open the project in terminal
5. Run `flutter pub get` in terminal
6. Then `flutter packages pub run build_runner build --delete-conflicting-outputs` (Must be done on each git pull)

View File

@ -71,7 +71,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// ReVanced
implementation "app.revanced:revanced-patcher:6.0.0"
implementation "app.revanced:revanced-patcher:6.3.0"
// Signing & aligning
implementation("org.bouncycastle:bcpkix-jdk15on:1.70")

View File

@ -1,6 +1,7 @@
{
"okButton": "OK",
"cancelButton": "Cancel",
"updateButton": "Update",
"enabledLabel": "Enabled",
"disabledLabel": "Disabled",
"yesButton": "Yes",
@ -21,7 +22,7 @@
"noInstallations": "No patched applications installed",
"installed": "Installed",
"updateDialogTitle": "Update Manager",
"updateDialogText": "Are you sure you want to download and update ReVanced Manager?",
"updateChangelogTitle": "Changelog",
"notificationTitle": "Update downloaded",
"notificationText": "Tap to install the update",
"downloadingMessage": "Downloading update...",
@ -121,6 +122,7 @@
"englishOption": "English",
"sourcesLabel": "Sources",
"sourcesLabelHint": "Configure your custom sources",
"hostRepositoryLabel": "Repository API",
"orgPatchesLabel": "Patches organization",
"sourcesPatchesLabel": "Patches source",
"orgIntegrationsLabel": "Integrations organization",

View File

@ -25,7 +25,8 @@ Future main() async {
await locator<RevancedAPI>().initialize(apiUrl);
await locator<CrowdinAPI>().initialize();
bool isSentryEnabled = locator<ManagerAPI>().isSentryEnabled();
locator<GithubAPI>().initialize();
String repoUrl = locator<ManagerAPI>().getRepoUrl();
locator<GithubAPI>().initialize(repoUrl);
await locator<PatcherAPI>().initialize();
tz.initializeTimeZones();
prefs = await SharedPreferences.getInstance();
@ -60,10 +61,11 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
String rawLocale = prefs.getString('language') ?? 'en_US';
String replaceLocale = rawLocale.replaceAll('_', '-');
List<String> localeList = replaceLocale.split('-');
Locale locale = Locale(localeList[0], localeList[1]);
// String rawLocale = prefs.getString('language') ?? 'en_US';
// String replaceLocale = rawLocale.replaceAll('_', '-');
// List<String> localeList = replaceLocale.split('-');
// Locale locale = Locale(localeList[0], localeList[1]);
Locale locale = const Locale('en', 'US');
return DynamicThemeBuilder(
title: 'ReVanced Manager',
@ -71,6 +73,7 @@ class MyApp extends StatelessWidget {
localizationsDelegates: [
FlutterI18nDelegate(
translationLoader: FileTranslationLoader(
fallbackFile: 'en_US',
forcedLocale: locale,
basePath: 'assets/i18n',
useCountryCode: true,

View File

@ -28,10 +28,10 @@ class GithubAPI {
'com.spotify.music': 'spotify',
};
void initialize() async {
void initialize(String repoUrl) async {
try {
_dio = Dio(BaseOptions(
baseUrl: 'https://api.github.com',
baseUrl: repoUrl,
));
_dio.interceptors.add(_dioCacheManager.interceptor);
@ -51,13 +51,13 @@ class GithubAPI {
}
}
Future<Map<String, dynamic>?> _getLatestRelease(String repoName) async {
Future<Map<String, dynamic>?> getLatestRelease(String repoName) async {
try {
var response = await _dio.get(
'/repos/$repoName/releases/latest',
'/repos/$repoName/releases',
options: _cacheOptions,
);
return response.data;
return response.data[0];
} on Exception catch (e, s) {
await Sentry.captureException(e, stackTrace: s);
return null;
@ -97,7 +97,7 @@ class GithubAPI {
Future<File?> getLatestReleaseFile(String extension, String repoName) async {
try {
Map<String, dynamic>? release = await _getLatestRelease(repoName);
Map<String, dynamic>? release = await getLatestRelease(repoName);
if (release != null) {
Map<String, dynamic>? asset =
(release['assets'] as List<dynamic>).firstWhereOrNull(
@ -133,7 +133,7 @@ class GithubAPI {
Future<String> getLastestReleaseVersion(String repoName) async {
try {
Map<String, dynamic>? release = await _getLatestRelease(repoName);
Map<String, dynamic>? release = await getLatestRelease(repoName);
if (release != null) {
return release['tag_name'];
} else {

View File

@ -23,6 +23,7 @@ class ManagerAPI {
late String storedPatchesFile = '/selected-patches.json';
late SharedPreferences _prefs;
String defaultApiUrl = 'https://releases.revanced.app/';
String defaultRepoUrl = 'https://api.github.com';
String defaultPatcherRepo = 'revanced/revanced-patcher';
String defaultPatchesRepo = 'revanced/revanced-patches';
String defaultIntegrationsRepo = 'revanced/revanced-integrations';
@ -48,6 +49,17 @@ class ManagerAPI {
await _prefs.setString('apiUrl', url);
}
String getRepoUrl() {
return _prefs.getString('repoUrl') ?? defaultRepoUrl;
}
Future<void> setRepoUrl(String url) async {
if (url.isEmpty || url == ' ') {
url = defaultRepoUrl;
}
await _prefs.setString('repoUrl', url);
}
String getPatchesRepo() {
return _prefs.getString('patchesRepo') ?? defaultPatchesRepo;
}

View File

@ -12,10 +12,11 @@ import 'package:revanced_manager/app/app.router.dart';
import 'package:revanced_manager/models/patched_application.dart';
import 'package:revanced_manager/services/manager_api.dart';
import 'package:revanced_manager/services/patcher_api.dart';
import 'package:revanced_manager/services/github_api.dart';
import 'package:revanced_manager/services/toast.dart';
import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart';
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart';
import 'package:revanced_manager/ui/widgets/homeView/update_confirmation_dialog.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart';
@ -26,6 +27,7 @@ class HomeViewModel extends BaseViewModel {
final NavigationService _navigationService = locator<NavigationService>();
final ManagerAPI _managerAPI = locator<ManagerAPI>();
final PatcherAPI _patcherAPI = locator<PatcherAPI>();
final GithubAPI _githubAPI = locator<GithubAPI>();
final Toast _toast = locator<Toast>();
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
DateTime? _lastUpdate;
@ -147,36 +149,26 @@ class HomeViewModel extends BaseViewModel {
_toast.showBottom('homeView.updatesDisabled');
}
Future<void> showUpdateConfirmationDialog(BuildContext parentContext) async {
return showDialog(
Future<void> showUpdateConfirmationDialog(BuildContext parentContext) {
return showModalBottomSheet(
context: parentContext,
builder: (context) => AlertDialog(
title: I18nText('homeView.updateDialogTitle'),
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
content: I18nText('homeView.updateDialogText'),
actions: <Widget>[
CustomMaterialButton(
isFilled: false,
label: I18nText('noButton'),
onPressed: () => Navigator.of(context).pop(),
),
CustomMaterialButton(
label: I18nText('yesButton'),
onPressed: () {
Navigator.of(context).pop();
updateManager(parentContext);
},
)
],
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(24.0)),
),
builder: (context) => const UpdateConfirmationDialog(),
);
}
Future<String?> getLatestPatcherReleaseTime() async {
Future<Map<String, dynamic>?> getLatestManagerRelease() {
return _githubAPI.getLatestRelease(_managerAPI.defaultManagerRepo);
}
Future<String?> getLatestPatcherReleaseTime() {
return _managerAPI.getLatestPatcherReleaseTime();
}
Future<String?> getLatestManagerReleaseTime() async {
Future<String?> getLatestManagerReleaseTime() {
return _managerAPI.getLatestManagerReleaseTime();
}

View File

@ -30,7 +30,6 @@ class PatchesSelectorViewModel extends BaseViewModel {
locator<PatcherViewModel>().selectedApp!.originalPackageName,
));
patches.sort((a, b) => a.name.compareTo(b.name));
selectRecommendedPatches();
notifyListeners();
}

View File

@ -12,14 +12,17 @@ import 'package:stacked/stacked.dart';
class SManageSources extends BaseViewModel {
final ManagerAPI _managerAPI = locator<ManagerAPI>();
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 {
String hostRepository = _managerAPI.getRepoUrl();
String patchesRepo = _managerAPI.getPatchesRepo();
String integrationsRepo = _managerAPI.getIntegrationsRepo();
_hostSourceController.text = hostRepository;
_orgPatSourceController.text = patchesRepo.split('/')[0];
_patSourceController.text = patchesRepo.split('/')[1];
_orgIntSourceController.text = integrationsRepo.split('/')[0];
@ -42,6 +45,17 @@ class SManageSources extends BaseViewModel {
content: SingleChildScrollView(
child: Column(
children: <Widget>[
CustomTextField(
leadingIcon: const Icon(
Icons.extension_outlined,
color: Colors.transparent,
),
inputController: _hostSourceController,
label: I18nText('settingsView.hostRepositoryLabel'),
hint: hostRepository,
onChanged: (value) => notifyListeners(),
),
const SizedBox(height: 20),
CustomTextField(
leadingIcon: Icon(
Icons.extension_outlined,
@ -103,6 +117,7 @@ class SManageSources extends BaseViewModel {
CustomMaterialButton(
label: I18nText('okButton'),
onPressed: () {
_managerAPI.setRepoUrl(_hostSourceController.text);
_managerAPI.setPatchesRepo(
'${_orgPatSourceController.text}/${_patSourceController.text}',
);
@ -133,10 +148,12 @@ class SManageSources extends BaseViewModel {
CustomMaterialButton(
label: I18nText('yesButton'),
onPressed: () {
_managerAPI.setRepoUrl('');
_managerAPI.setPatchesRepo('');
_managerAPI.setIntegrationsRepo('');
Navigator.of(context).pop();
Navigator.of(context).pop();
Navigator.of(context).pop();
},
)
],

View File

@ -42,8 +42,8 @@ class SettingsView extends StatelessWidget {
delegate: SliverChildListDelegate.fixed(
<Widget>[
SUpdateThemeUI(),
SUpdateLanguageUI(),
_settingsDivider,
// SUpdateLanguageUI(),
// _settingsDivider,
STeamSection(),
_settingsDivider,
SAdvancedSection(),

View File

@ -0,0 +1,127 @@
import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/ui/views/home/home_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart';
class UpdateConfirmationDialog extends StatelessWidget {
const UpdateConfirmationDialog({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final HomeViewModel model = locator<HomeViewModel>();
return DraggableScrollableSheet(
expand: false,
initialChildSize: 0.5,
snap: true,
snapSizes: const [0.5],
builder: (context, scrollController) => SingleChildScrollView(
controller: scrollController,
child: SafeArea(
child: FutureBuilder<Map<String, dynamic>?>(
future: model.getLatestManagerRelease(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const SizedBox(
height: 300,
child: Center(
child: CircularProgressIndicator(),
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(
top: 40.0, left: 24.0, right: 24.0, bottom: 32.0),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
I18nText(
'homeView.updateDialogTitle',
child: const Text(
"",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold),
),
),
const SizedBox(height: 4.0),
Row(
children: [
Icon(
Icons.new_releases_outlined,
color:
Theme.of(context).colorScheme.secondary,
),
const SizedBox(width: 8.0),
Text(
snapshot.data!["tag_name"] ?? "Unknown",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.colorScheme
.secondary,
),
),
],
),
],
),
),
CustomMaterialButton(
isExpanded: true,
label: I18nText('updateButton'),
onPressed: () {
Navigator.of(context).pop();
model.updateManager(context);
},
)
],
),
),
Padding(
padding: const EdgeInsets.only(left: 24.0, bottom: 12.0),
child: I18nText(
'homeView.updateChangelogTitle',
child: Text(
"",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.colorScheme
.onSecondaryContainer),
),
),
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 24.0),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.secondaryContainer,
borderRadius: BorderRadius.circular(12.0),
),
child: Markdown(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(20.0),
data: snapshot.data!["body"] ?? "",
),
),
],
);
},
),
),
),
);
}
}

View File

@ -4,7 +4,7 @@ homepage: https://github.com/revanced/revanced-manager
publish_to: 'none'
version: 0.0.42+42
version: 0.0.45+45
environment:
sdk: ">=2.17.5 <3.0.0"
@ -76,6 +76,7 @@ dependencies:
sentry_dio: ^6.12.2
flutter_dotenv: ^5.0.2
pub_release: ^8.0.3
flutter_markdown: ^0.6.13
dev_dependencies:
json_serializable: ^6.3.1