Compare commits
36 Commits
f8f4ee754c
...
5b81d12d09
Author | SHA1 | Date |
---|---|---|
Benjamin | 5b81d12d09 | |
oSumAtrIX | 4a72267d41 | |
oSumAtrIX | 7e0f18e3b7 | |
hellidox | aab5d4411b | |
Benjamin Halko | 979cbfe94d | |
Benjamin Halko | d83869da2c | |
Benjamin Halko | a8bdafe952 | |
Benjamin Halko | cb686dabc7 | |
Benjamin | aa7a8c422e | |
Benjamin | 0cb84be764 | |
Benjamin | ffa8847eb2 | |
Benjamin | cb5641a50b | |
Benjamin Halko | a92b69b986 | |
Benjamin Halko | a3c4c8e706 | |
Benjamin Halko | b4e21ae2ee | |
Benjamin Halko | 14dd4a0d1c | |
festry0 | 1fee561345 | |
Benjamin | 5f03a8b548 | |
Benjamin Halko | d620272e9f | |
Benjamin Halko | 7e22fa25bb | |
Benjamin Halko | cebf97464d | |
Benjamin Halko | 8ac25bfb40 | |
Benjamin Halko | f375fa9b35 | |
Benjamin Halko | 443f59473a | |
oSumAtrIX | 36572abaea | |
Benjamin Halko | d0103a33d9 | |
Benjamin | 52da64b229 | |
oSumAtrIX | d63185be55 | |
Mr. X | ee8c7f297d | |
aAbed | 163160c1ec | |
aAbed | 073acdaa72 | |
Ushie | 7019d0cab5 | |
aAbed | b53bc280b6 | |
Benjamin Halko | 18885a1433 | |
Benjamin Halko | 527951397f | |
Benjamin Halko | 72a99bc7fb |
|
@ -98,10 +98,6 @@ To build a ReVanced Manager, you can follow the [documentation](/docs).
|
|||
|
||||
You can find the documentation for ReVanced Manager [here](/docs).
|
||||
|
||||
### đź‘‹ Contributing
|
||||
|
||||
Thank you for considering contributing to ReVanced Manager. You can find the contribution guidelines [here](/CONTRIBUTING.md).
|
||||
|
||||
## ⚖️ License
|
||||
|
||||
ReVanced Manager is licensed under the GPLv3 license. Please see the [license file](LICENSE) for more information.
|
||||
|
|
|
@ -27,10 +27,12 @@
|
|||
"refreshSuccess": "Refreshed successfully",
|
||||
"widgetTitle": "Dashboard",
|
||||
"updatesSubtitle": "Updates",
|
||||
"patchedSubtitle": "Patched apps",
|
||||
"patchHistorySubtitle": "Last patch",
|
||||
"patchedSubtitle": "Installed apps",
|
||||
"changeLaterSubtitle": "You can change this in the settings at a later time.",
|
||||
"noUpdates": "No updates available",
|
||||
"WIP": "Work in progress...",
|
||||
"noHistory": "No app found",
|
||||
"noInstallations": "No patched apps installed",
|
||||
"installUpdate": "Continue to install the update?",
|
||||
"updateSheetTitle": "Update ReVanced Manager",
|
||||
|
@ -203,6 +205,8 @@
|
|||
"showUpdateDialogHint": "Show a dialog when a new update is available",
|
||||
"universalPatchesLabel": "Show universal patches",
|
||||
"universalPatchesHint": "Display all apps and universal patches (may slow down the app list)",
|
||||
"patchHistoryLabel": "Save patched app",
|
||||
"patchHistoryHint": "Save the last patch to install or export later",
|
||||
"versionCompatibilityCheckLabel": "Version compatibility check",
|
||||
"versionCompatibilityCheckHint": "Prevent selecting patches that are not compatible with the selected app version",
|
||||
"requireSuggestedAppVersionLabel": "Require suggested app version",
|
||||
|
@ -254,18 +258,25 @@
|
|||
"appInfoView": {
|
||||
"widgetTitle": "App info",
|
||||
"openButton": "Open",
|
||||
"installButton": "Install",
|
||||
"uninstallButton": "Uninstall",
|
||||
"unmountButton": "Unmount",
|
||||
"exportButton": "Export",
|
||||
"deleteButton": "Delete",
|
||||
"rootDialogTitle": "Error",
|
||||
"patchHistoryDescription": "This is a backup of the last patched app. You can install or export it later.",
|
||||
"unmountDialogText": "Are you sure you want to unmount this app?",
|
||||
"uninstallDialogText": "Are you sure you want to uninstall this app?",
|
||||
"rootDialogText": "App was installed with superuser permissions, but currently ReVanced Manager has no permissions.\nPlease grant superuser permissions first.",
|
||||
"removeAppDialogTitle": "Delete app?",
|
||||
"removeAppDialogText": "Are you sure you want to delete this app?",
|
||||
"packageNameLabel": "Package name",
|
||||
"installTypeLabel": "Installation type",
|
||||
"mountTypeLabel": "Mount",
|
||||
"regularTypeLabel": "Regular",
|
||||
"patchedDateLabel": "Patched date",
|
||||
"appliedPatchesLabel": "Applied patches",
|
||||
"sizeLabel": "File size",
|
||||
"patchedDateHint": "${date} at ${time}",
|
||||
"appliedPatchesHint": "${quantity} applied patches",
|
||||
"updateNotImplemented": "This feature has not been implemented yet"
|
||||
|
|
|
@ -16,6 +16,8 @@ class PatchedApplication {
|
|||
this.isRooted = false,
|
||||
this.isFromStorage = false,
|
||||
this.appliedPatches = const [],
|
||||
this.patchedFilePath = '',
|
||||
this.fileSize = 0,
|
||||
});
|
||||
|
||||
factory PatchedApplication.fromJson(Map<String, dynamic> json) =>
|
||||
|
@ -33,6 +35,8 @@ class PatchedApplication {
|
|||
bool isRooted;
|
||||
bool isFromStorage;
|
||||
List<String> appliedPatches;
|
||||
String patchedFilePath;
|
||||
int fileSize;
|
||||
|
||||
Map<String, dynamic> toJson() => _$PatchedApplicationToJson(this);
|
||||
|
||||
|
|
|
@ -23,39 +23,6 @@ class GithubAPI {
|
|||
|
||||
Future<Map<String, dynamic>?> getLatestRelease(
|
||||
String repoName,
|
||||
) async {
|
||||
try {
|
||||
final response = await _dio.get(
|
||||
'/repos/$repoName/releases',
|
||||
);
|
||||
return response.data[0];
|
||||
} on Exception catch (e) {
|
||||
if (kDebugMode) {
|
||||
print(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>?> getPatchesRelease(
|
||||
String repoName,
|
||||
String version,
|
||||
) async {
|
||||
try {
|
||||
final response = await _dio.get(
|
||||
'/repos/$repoName/releases/tags/$version',
|
||||
);
|
||||
return response.data;
|
||||
} on Exception catch (e) {
|
||||
if (kDebugMode) {
|
||||
print(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>?> getLatestPatchesRelease(
|
||||
String repoName,
|
||||
) async {
|
||||
try {
|
||||
final response = await _dio.get(
|
||||
|
@ -108,32 +75,7 @@ class GithubAPI {
|
|||
}
|
||||
}
|
||||
|
||||
Future<File?> getLatestReleaseFile(
|
||||
String extension,
|
||||
String repoName,
|
||||
) async {
|
||||
try {
|
||||
final Map<String, dynamic>? release = await getLatestRelease(repoName);
|
||||
if (release != null) {
|
||||
final Map<String, dynamic>? asset =
|
||||
(release['assets'] as List<dynamic>).firstWhereOrNull(
|
||||
(asset) => (asset['name'] as String).endsWith(extension),
|
||||
);
|
||||
if (asset != null) {
|
||||
return await _downloadManager.getSingleFile(
|
||||
asset['browser_download_url'],
|
||||
);
|
||||
}
|
||||
}
|
||||
} on Exception catch (e) {
|
||||
if (kDebugMode) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<File?> getPatchesReleaseFile(
|
||||
Future<File?> getReleaseFile(
|
||||
String extension,
|
||||
String repoName,
|
||||
String version,
|
||||
|
@ -145,8 +87,10 @@ class GithubAPI {
|
|||
url,
|
||||
);
|
||||
}
|
||||
final Map<String, dynamic>? release =
|
||||
await getPatchesRelease(repoName, version);
|
||||
final response = await _dio.get(
|
||||
'/repos/$repoName/releases/tags/$version',
|
||||
);
|
||||
final Map<String, dynamic>? release = response.data;
|
||||
if (release != null) {
|
||||
final Map<String, dynamic>? asset =
|
||||
(release['assets'] as List<dynamic>).firstWhereOrNull(
|
||||
|
|
|
@ -296,6 +296,14 @@ class ManagerAPI {
|
|||
await _prefs.setBool('requireSuggestedAppVersionEnabled', value);
|
||||
}
|
||||
|
||||
bool isPatchHistoryEnabled() {
|
||||
return _prefs.getBool('patchHistoryEnabled') ?? true;
|
||||
}
|
||||
|
||||
Future<void> enablePatchHistoryStatus(bool value) async {
|
||||
await _prefs.setBool('patchHistoryEnabled', value);
|
||||
}
|
||||
|
||||
Future<void> setKeystorePassword(String password) async {
|
||||
await _prefs.setString('keystorePassword', password);
|
||||
}
|
||||
|
@ -328,6 +336,34 @@ class ManagerAPI {
|
|||
}
|
||||
}
|
||||
|
||||
PatchedApplication? getLastPatchedApp() {
|
||||
final String? app = _prefs.getString('lastPatchedApp');
|
||||
return app != null ? PatchedApplication.fromJson(jsonDecode(app)) : null;
|
||||
}
|
||||
|
||||
Future<void> deleteLastPatchedApp() async {
|
||||
final PatchedApplication? app = getLastPatchedApp();
|
||||
if (app != null) {
|
||||
final File file = File(app.patchedFilePath);
|
||||
await file.delete();
|
||||
await _prefs.remove('lastPatchedApp');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setLastPatchedApp(
|
||||
PatchedApplication app,
|
||||
File outFile,
|
||||
) async {
|
||||
deleteLastPatchedApp();
|
||||
final Directory appCache = await getApplicationSupportDirectory();
|
||||
app.patchedFilePath = outFile.copySync('${appCache.path}/lastPatchedApp.apk').path;
|
||||
app.fileSize = outFile.lengthSync();
|
||||
await _prefs.setString(
|
||||
'lastPatchedApp',
|
||||
json.encode(app.toJson()),
|
||||
);
|
||||
}
|
||||
|
||||
List<PatchedApplication> getPatchedApps() {
|
||||
final List<String> apps = _prefs.getStringList('patchedApps') ?? [];
|
||||
return apps.map((a) => PatchedApplication.fromJson(jsonDecode(a))).toList();
|
||||
|
@ -422,7 +458,7 @@ class ManagerAPI {
|
|||
final String repoName = !isUsingAlternativeSources() ? defaultPatchesRepo : getPatchesRepo();
|
||||
final String currentVersion = await getCurrentPatchesVersion();
|
||||
final String url = getPatchesDownloadURL();
|
||||
return await _githubAPI.getPatchesReleaseFile(
|
||||
return await _githubAPI.getReleaseFile(
|
||||
'.jar',
|
||||
repoName,
|
||||
currentVersion,
|
||||
|
@ -441,7 +477,7 @@ class ManagerAPI {
|
|||
final String repoName = !isUsingAlternativeSources() ? defaultIntegrationsRepo : getIntegrationsRepo();
|
||||
final String currentVersion = await getCurrentIntegrationsVersion();
|
||||
final String url = getIntegrationsDownloadURL();
|
||||
return await _githubAPI.getPatchesReleaseFile(
|
||||
return await _githubAPI.getReleaseFile(
|
||||
'.apk',
|
||||
repoName,
|
||||
currentVersion,
|
||||
|
@ -470,7 +506,7 @@ class ManagerAPI {
|
|||
);
|
||||
} else {
|
||||
final release =
|
||||
await _githubAPI.getLatestPatchesRelease(getPatchesRepo());
|
||||
await _githubAPI.getLatestRelease(getPatchesRepo());
|
||||
if (release != null) {
|
||||
final DateTime timestamp =
|
||||
DateTime.parse(release['created_at'] as String);
|
||||
|
@ -519,7 +555,7 @@ class ManagerAPI {
|
|||
);
|
||||
} else {
|
||||
final release =
|
||||
await _githubAPI.getLatestPatchesRelease(getPatchesRepo());
|
||||
await _githubAPI.getLatestRelease(getPatchesRepo());
|
||||
if (release != null) {
|
||||
return release['tag_name'];
|
||||
} else {
|
||||
|
@ -686,6 +722,16 @@ class ManagerAPI {
|
|||
patchedApps.addAll(mountedApps);
|
||||
|
||||
await setPatchedApps(patchedApps);
|
||||
|
||||
// Removed saved app history if the file is not found.
|
||||
final PatchedApplication? lastPatchedApp = getLastPatchedApp();
|
||||
if (lastPatchedApp != null) {
|
||||
final File file = File(lastPatchedApp.patchedFilePath);
|
||||
if (!file.existsSync()) {
|
||||
deleteLastPatchedApp();
|
||||
_prefs.remove('lastPatchedApp');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> isAppUninstalled(PatchedApplication app) async {
|
||||
|
@ -780,4 +826,82 @@ class ManagerAPI {
|
|||
selectedPatchesFile.deleteSync();
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> installTypeDialog(BuildContext context) async {
|
||||
final ValueNotifier<int> installType = ValueNotifier(0);
|
||||
if (isRooted) {
|
||||
await showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(t.installerView.installType),
|
||||
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
|
||||
icon: const Icon(Icons.file_download_outlined),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||
content: SingleChildScrollView(
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: installType,
|
||||
builder: (context, value, child) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 10,
|
||||
),
|
||||
child: Text(
|
||||
t.installerView.installTypeDescription,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
RadioListTile(
|
||||
title: Text(t.installerView.installNonRootType),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 16),
|
||||
value: 0,
|
||||
groupValue: value,
|
||||
onChanged: (selected) {
|
||||
installType.value = selected!;
|
||||
},
|
||||
),
|
||||
RadioListTile(
|
||||
title: Text(t.installerView.installRootType),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 16),
|
||||
value: 1,
|
||||
groupValue: value,
|
||||
onChanged: (selected) {
|
||||
installType.value = selected!;
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
OutlinedButton(
|
||||
child: Text(t.cancelButton),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
FilledButton(
|
||||
child: Text(t.installerView.installButton),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@ class PatcherAPI {
|
|||
BuildContext context,
|
||||
PatchedApplication patchedApp,
|
||||
) async {
|
||||
if (outFile != null) {
|
||||
if (patchedApp.patchedFilePath != '') {
|
||||
_managerAPI.ctx = context;
|
||||
try {
|
||||
if (patchedApp.isRooted) {
|
||||
|
@ -232,7 +232,7 @@ class PatcherAPI {
|
|||
return await _rootAPI.install(
|
||||
patchedApp.packageName,
|
||||
patchedApp.apkFilePath,
|
||||
outFile!.path,
|
||||
patchedApp.patchedFilePath,
|
||||
)
|
||||
? 0
|
||||
: 1;
|
||||
|
@ -246,7 +246,7 @@ class PatcherAPI {
|
|||
if (context.mounted) {
|
||||
return await installApk(
|
||||
context,
|
||||
outFile!.path,
|
||||
patchedApp.patchedFilePath,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -368,13 +368,13 @@ class PatcherAPI {
|
|||
return cleanInstall ? 10 : 1;
|
||||
}
|
||||
|
||||
void exportPatchedFile(String appName, String version) {
|
||||
void exportPatchedFile(PatchedApplication app) {
|
||||
try {
|
||||
if (outFile != null) {
|
||||
final String newName = _getFileName(appName, version);
|
||||
final String newName = _getFileName(app.name, app.version);
|
||||
FlutterFileDialog.saveFile(
|
||||
params: SaveFileDialogParams(
|
||||
sourceFilePath: outFile!.path,
|
||||
sourceFilePath: app.patchedFilePath,
|
||||
fileName: newName,
|
||||
mimeTypesFilter: ['application/vnd.android.package-archive'],
|
||||
),
|
||||
|
@ -387,14 +387,14 @@ class PatcherAPI {
|
|||
}
|
||||
}
|
||||
|
||||
void sharePatchedFile(String appName, String version) {
|
||||
void sharePatchedFile(PatchedApplication app) {
|
||||
try {
|
||||
if (outFile != null) {
|
||||
final String newName = _getFileName(appName, version);
|
||||
final int lastSeparator = outFile!.path.lastIndexOf('/');
|
||||
final String newName = _getFileName(app.name, app.version);
|
||||
final int lastSeparator = app.patchedFilePath.lastIndexOf('/');
|
||||
final String newPath =
|
||||
outFile!.path.substring(0, lastSeparator + 1) + newName;
|
||||
final File shareFile = outFile!.copySync(newPath);
|
||||
app.patchedFilePath.substring(0, lastSeparator + 1) + newName;
|
||||
final File shareFile = File(app.patchedFilePath).copySync(newPath);
|
||||
Share.shareXFiles([XFile(shareFile.path)]);
|
||||
}
|
||||
} on Exception catch (e) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:revanced_manager/gen/strings.g.dart';
|
|||
import 'package:revanced_manager/ui/views/home/home_viewmodel.dart';
|
||||
import 'package:revanced_manager/ui/widgets/homeView/installed_apps_card.dart';
|
||||
import 'package:revanced_manager/ui/widgets/homeView/latest_commit_card.dart';
|
||||
import 'package:revanced_manager/ui/widgets/homeView/patch_history_card.dart';
|
||||
import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart';
|
||||
import 'package:stacked/stacked.dart';
|
||||
|
||||
|
@ -44,6 +45,22 @@ class HomeView extends StatelessWidget {
|
|||
const SizedBox(height: 10),
|
||||
LatestCommitCard(model: model, parentContext: context),
|
||||
const SizedBox(height: 23),
|
||||
Visibility(
|
||||
visible: model.isPatchHistoryEnabled(),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
t.homeView.patchHistorySubtitle,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
PatchHistoryCard(),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
t.homeView.patchedSubtitle,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
|
|
|
@ -35,6 +35,7 @@ class HomeViewModel extends BaseViewModel {
|
|||
final Toast _toast = locator<Toast>();
|
||||
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||
bool showUpdatableApps = false;
|
||||
PatchedApplication? lastPatchedApp;
|
||||
bool releaseBuild = false;
|
||||
List<PatchedApplication> patchedInstalledApps = [];
|
||||
String _currentManagerVersion = '';
|
||||
|
@ -102,10 +103,10 @@ class HomeViewModel extends BaseViewModel {
|
|||
}
|
||||
}
|
||||
|
||||
void navigateToAppInfo(PatchedApplication app) {
|
||||
void navigateToAppInfo(PatchedApplication app, bool isHistory) {
|
||||
_navigationService.navigateTo(
|
||||
Routes.appInfoView,
|
||||
arguments: AppInfoViewArguments(app: app),
|
||||
arguments: AppInfoViewArguments(app: app, isHistory: isHistory),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -123,10 +124,15 @@ class HomeViewModel extends BaseViewModel {
|
|||
}
|
||||
|
||||
void getPatchedApps() {
|
||||
lastPatchedApp = _managerAPI.getLastPatchedApp();
|
||||
patchedInstalledApps = _managerAPI.getPatchedApps().toList();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool isPatchHistoryEnabled() {
|
||||
return _managerAPI.isPatchHistoryEnabled();
|
||||
}
|
||||
|
||||
Future<bool> hasManagerUpdates() async {
|
||||
if (!_managerAPI.releaseBuild) {
|
||||
return false;
|
||||
|
@ -480,7 +486,7 @@ class HomeViewModel extends BaseViewModel {
|
|||
}
|
||||
|
||||
Future<Map<String, dynamic>?> getLatestPatchesRelease() {
|
||||
return _githubAPI.getLatestPatchesRelease(_managerAPI.defaultPatchesRepo);
|
||||
return _githubAPI.getLatestRelease(_managerAPI.defaultPatchesRepo);
|
||||
}
|
||||
|
||||
Future<String?> getLatestPatchesReleaseTime() {
|
||||
|
|
|
@ -123,7 +123,7 @@ class InstallerViewModel extends BaseViewModel {
|
|||
});
|
||||
await WakelockPlus.enable();
|
||||
await handlePlatformChannelMethods();
|
||||
await runPatcher();
|
||||
await runPatcher(context);
|
||||
}
|
||||
|
||||
Future<dynamic> handlePlatformChannelMethods() async {
|
||||
|
@ -182,13 +182,20 @@ class InstallerViewModel extends BaseViewModel {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> runPatcher() async {
|
||||
Future<void> runPatcher(BuildContext context) async {
|
||||
try {
|
||||
await _patcherAPI.runPatcher(
|
||||
_app.packageName,
|
||||
_app.apkFilePath,
|
||||
_patches,
|
||||
);
|
||||
_app.appliedPatches = _patches.map((p) => p.name).toList();
|
||||
if (_managerAPI.isPatchHistoryEnabled()) {
|
||||
await _managerAPI.setLastPatchedApp(_app, _patcherAPI.outFile!);
|
||||
} else {
|
||||
_app.patchedFilePath = _patcherAPI.outFile!.path;
|
||||
}
|
||||
locator<HomeViewModel>().initialize(context);
|
||||
} on Exception catch (e) {
|
||||
update(
|
||||
-100.0,
|
||||
|
@ -488,7 +495,7 @@ class InstallerViewModel extends BaseViewModel {
|
|||
Future<void> installResult(BuildContext context, bool installAsRoot) async {
|
||||
isInstalling = true;
|
||||
try {
|
||||
_app.isRooted = installAsRoot;
|
||||
_app.isRooted = await _managerAPI.installTypeDialog(context);
|
||||
if (headerLogs != 'Installing...') {
|
||||
update(
|
||||
.85,
|
||||
|
@ -501,17 +508,15 @@ class InstallerViewModel extends BaseViewModel {
|
|||
isInstalled = true;
|
||||
_app.isFromStorage = false;
|
||||
_app.patchDate = DateTime.now();
|
||||
_app.appliedPatches = _patches.map((p) => p.name).toList();
|
||||
|
||||
// In case a patch changed the app name or package name,
|
||||
// update the app info.
|
||||
final app =
|
||||
await DeviceApps.getAppFromStorage(_patcherAPI.outFile!.path);
|
||||
await DeviceApps.getAppFromStorage(_patcherAPI.outFile!.path);
|
||||
if (app != null) {
|
||||
_app.name = app.appName;
|
||||
_app.packageName = app.packageName;
|
||||
}
|
||||
|
||||
await _managerAPI.savePatchedApp(_app);
|
||||
|
||||
_managerAPI
|
||||
|
@ -544,7 +549,7 @@ class InstallerViewModel extends BaseViewModel {
|
|||
|
||||
void exportResult() {
|
||||
try {
|
||||
_patcherAPI.exportPatchedFile(_app.name, _app.version);
|
||||
_patcherAPI.exportPatchedFile(_app);
|
||||
} on Exception catch (e) {
|
||||
if (kDebugMode) {
|
||||
print(e);
|
||||
|
|
|
@ -141,6 +141,18 @@ class SettingsViewModel extends BaseViewModel {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
bool isPatchHistoryEnabled() {
|
||||
return _managerAPI.isPatchHistoryEnabled();
|
||||
}
|
||||
|
||||
void usePatchHistory(bool value) {
|
||||
_managerAPI.enablePatchHistoryStatus(value);
|
||||
if (!value) {
|
||||
_managerAPI.deleteLastPatchedApp();
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool isVersionCompatibilityCheckEnabled() {
|
||||
return _managerAPI.isVersionCompatibilityCheckEnabled();
|
||||
}
|
||||
|
|
|
@ -11,8 +11,10 @@ class AppInfoView extends StatelessWidget {
|
|||
const AppInfoView({
|
||||
super.key,
|
||||
required this.app,
|
||||
required this.isHistory,
|
||||
});
|
||||
final PatchedApplication app;
|
||||
final bool isHistory;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -57,6 +59,14 @@ class AppInfoView extends StatelessWidget {
|
|||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
if (isHistory) ...[
|
||||
ListTile(
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 20.0),
|
||||
subtitle: Text(t.appInfoView.patchHistoryDescription),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
],
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||
child: CustomCard(
|
||||
|
@ -71,20 +81,26 @@ class AppInfoView extends StatelessWidget {
|
|||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
onTap: () => model.openApp(app),
|
||||
onTap: () => isHistory
|
||||
? model.installApp(context, app)
|
||||
: model.openApp(app),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
Icons.open_in_new_outlined,
|
||||
isHistory
|
||||
? Icons.download_outlined
|
||||
: Icons.open_in_new_outlined,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
t.appInfoView.openButton,
|
||||
isHistory
|
||||
? t.appInfoView.installButton
|
||||
: t.appInfoView.openButton,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
|
@ -108,24 +124,30 @@ class AppInfoView extends StatelessWidget {
|
|||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
onTap: () => model.showUninstallDialog(
|
||||
context,
|
||||
app,
|
||||
false,
|
||||
),
|
||||
onTap: () => isHistory
|
||||
? model.exportApp(app)
|
||||
: model.showUninstallDialog(
|
||||
context,
|
||||
app,
|
||||
false,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
Icons.delete_outline,
|
||||
isHistory
|
||||
? Icons.save
|
||||
: Icons.delete_outline,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
t.appInfoView.uninstallButton,
|
||||
isHistory
|
||||
? t.appInfoView.exportButton
|
||||
: t.appInfoView.uninstallButton,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
|
@ -144,14 +166,57 @@ class AppInfoView extends StatelessWidget {
|
|||
endIndent: 12.0,
|
||||
width: 1.0,
|
||||
),
|
||||
if (app.isRooted)
|
||||
if (isHistory)
|
||||
VerticalDivider(
|
||||
color: Theme.of(context).canvasColor,
|
||||
indent: 12.0,
|
||||
endIndent: 12.0,
|
||||
width: 1.0,
|
||||
),
|
||||
if (app.isRooted)
|
||||
if (isHistory)
|
||||
Expanded(
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
onTap: () => model.showDeleteDialog(
|
||||
context,
|
||||
app,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
Icons
|
||||
.delete_forever_outlined,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
t.appInfoView.deleteButton,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!isHistory && app.isRooted)
|
||||
VerticalDivider(
|
||||
color: Theme.of(context).canvasColor,
|
||||
indent: 12.0,
|
||||
endIndent: 12.0,
|
||||
width: 1.0,
|
||||
),
|
||||
if (!isHistory && app.isRooted)
|
||||
Expanded(
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// ignore_for_file: use_build_context_synchronously
|
||||
import 'dart:math';
|
||||
import 'package:device_apps/device_apps.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
@ -20,6 +21,23 @@ class AppInfoViewModel extends BaseViewModel {
|
|||
final RootAPI _rootAPI = RootAPI();
|
||||
final Toast _toast = locator<Toast>();
|
||||
|
||||
Future<void> installApp(
|
||||
BuildContext context,
|
||||
PatchedApplication app,
|
||||
) async {
|
||||
app.isRooted = await _managerAPI.installTypeDialog(context);
|
||||
final int statusCode = await _patcherAPI.installPatchedFile(context, app);
|
||||
if (statusCode == 0) {
|
||||
locator<HomeViewModel>().initialize(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> exportApp(
|
||||
PatchedApplication app,
|
||||
) async {
|
||||
_patcherAPI.exportPatchedFile(app);
|
||||
}
|
||||
|
||||
Future<void> uninstallApp(
|
||||
BuildContext context,
|
||||
PatchedApplication app,
|
||||
|
@ -123,6 +141,34 @@ class AppInfoViewModel extends BaseViewModel {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> showDeleteDialog(
|
||||
BuildContext context,
|
||||
PatchedApplication app,
|
||||
) async {
|
||||
return showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(t.appInfoView.removeAppDialogTitle),
|
||||
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
|
||||
content: Text(t.appInfoView.removeAppDialogText),
|
||||
actions: <Widget>[
|
||||
OutlinedButton(
|
||||
child: Text(t.cancelButton),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
FilledButton(
|
||||
child: Text(t.okButton),
|
||||
onPressed: () => {
|
||||
_managerAPI.deleteLastPatchedApp(),
|
||||
Navigator.of(context)..pop()..pop(),
|
||||
locator<HomeViewModel>().initialize(context),
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String getPrettyDate(BuildContext context, DateTime dateTime) {
|
||||
return DateFormat.yMMMMd(Localizations.localeOf(context).languageCode)
|
||||
.format(dateTime);
|
||||
|
@ -133,6 +179,12 @@ class AppInfoViewModel extends BaseViewModel {
|
|||
.format(dateTime);
|
||||
}
|
||||
|
||||
String getFileSizeString(int bytes) {
|
||||
const suffixes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
final i = (log(bytes) / log(1024)).floor();
|
||||
return '${(bytes / pow(1024, i)).toStringAsFixed(2)} ${suffixes[i]}';
|
||||
}
|
||||
|
||||
Future<void> showAppliedPatchesDialog(
|
||||
BuildContext context,
|
||||
PatchedApplication app,
|
||||
|
|
|
@ -76,7 +76,7 @@ class InstalledAppsCard extends StatelessWidget {
|
|||
name: app.name,
|
||||
patchDate: app.patchDate,
|
||||
onPressed: () =>
|
||||
locator<HomeViewModel>().navigateToAppInfo(app),
|
||||
locator<HomeViewModel>().navigateToAppInfo(app, false),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import 'package:device_apps/device_apps.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:revanced_manager/app/app.locator.dart';
|
||||
import 'package:revanced_manager/gen/strings.g.dart';
|
||||
import 'package:revanced_manager/models/patched_application.dart';
|
||||
import 'package:revanced_manager/services/manager_api.dart';
|
||||
import 'package:revanced_manager/ui/views/home/home_viewmodel.dart';
|
||||
import 'package:revanced_manager/ui/widgets/shared/application_item.dart';
|
||||
import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';
|
||||
|
||||
//ignore: must_be_immutable
|
||||
class PatchHistoryCard extends StatelessWidget {
|
||||
PatchHistoryCard({super.key});
|
||||
PatchedApplication? app = locator<HomeViewModel>().lastPatchedApp;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return app == null
|
||||
? CustomCard(
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
size: 40,
|
||||
Icons.update_disabled,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
t.homeView.noHistory,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
.copyWith(
|
||||
color:
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: ApplicationItem(
|
||||
icon: app!.icon,
|
||||
name: app!.name,
|
||||
patchDate: app!.patchDate,
|
||||
onPressed: () =>
|
||||
locator<HomeViewModel>().navigateToAppInfo(app!, true),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:revanced_manager/gen/strings.g.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_patch_history.dart';
|
||||
import 'package:revanced_manager/ui/widgets/settingsView/settings_require_suggested_app_version.dart';
|
||||
import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart';
|
||||
import 'package:revanced_manager/ui/widgets/settingsView/settings_show_update_dialog.dart';
|
||||
|
@ -24,6 +25,7 @@ class SAdvancedSection extends StatelessWidget {
|
|||
SRequireSuggestedAppVersion(),
|
||||
SVersionCompatibilityCheck(),
|
||||
SUniversalPatches(),
|
||||
SPatchHistory(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:revanced_manager/gen/strings.g.dart';
|
||||
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
||||
|
||||
class SPatchHistory extends StatefulWidget {
|
||||
const SPatchHistory({super.key});
|
||||
|
||||
@override
|
||||
State<SPatchHistory> createState() =>
|
||||
_SPatchHistoryState();
|
||||
}
|
||||
|
||||
final _settingsViewModel = SettingsViewModel();
|
||||
|
||||
class _SPatchHistoryState
|
||||
extends State<SPatchHistory> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SwitchListTile(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||
title: Text(
|
||||
t.settingsView.patchHistoryLabel,
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
subtitle: Text(t.settingsView.patchHistoryHint),
|
||||
value: _settingsViewModel.isPatchHistoryEnabled(),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_settingsViewModel.usePatchHistory(value);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -33,6 +33,7 @@ class _ApplicationItemState extends State<ApplicationItem> {
|
|||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 16.0),
|
||||
child: CustomCard(
|
||||
onTap: widget.onPressed,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
File diff suppressed because it is too large
Load Diff
172
pubspec.lock
172
pubspec.lock
|
@ -29,10 +29,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||
sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
version: "2.5.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -109,10 +109,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e
|
||||
sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.9.1"
|
||||
version: "8.9.2"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -157,10 +157,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: connectivity_plus
|
||||
sha256: e9feae83b1849f61bad9f6f33ee00646e3410d54ce0821e02f262f9901dad3c9
|
||||
sha256: db7a4e143dc72cc3cb2044ef9b052a7ebfe729513e6a82943bc3526f784365b8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.1"
|
||||
version: "6.0.3"
|
||||
connectivity_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -197,10 +197,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: csv
|
||||
sha256: "63ed2871dd6471193dffc52c0e6c76fb86269c00244d244297abbb355c84a86e"
|
||||
sha256: c6aa2679b2a18cb57652920f674488d89712efaf4d3fdf2e537215b35fc19d6c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
version: "6.0.0"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -230,10 +230,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: device_info_plus
|
||||
sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110"
|
||||
sha256: eead12d1a1ed83d8283ab4c2f3fca23ac4082f29f25f29dff0f758f57d06ec91
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.1.2"
|
||||
version: "10.1.0"
|
||||
device_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -246,10 +246,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: dio
|
||||
sha256: "49af28382aefc53562459104f64d16b9dfd1e8ef68c862d5af436cc8356ce5a8"
|
||||
sha256: "11e40df547d418cc0c4900a9318b26304e665da6fa4755399a9ff9efd09034b5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.4.1"
|
||||
version: "5.4.3+1"
|
||||
dio_cache_interceptor:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -332,10 +332,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_cache_manager
|
||||
sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba"
|
||||
sha256: "395d6b7831f21f3b989ebedbb785545932adb9afe2622c1ffacf7f4b53a7e544"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.1"
|
||||
version: "3.3.2"
|
||||
flutter_file_dialog:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -356,10 +356,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
sha256: f9a05409385b77b06c18f200a41c7c2711ebf7415669350bb0f8474c07bd40d1
|
||||
sha256: "8cdc719114ab1c86c64bb7a86d3a679674c3637edd229e3a994797d4a1504ce4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "17.0.0"
|
||||
version: "17.1.0"
|
||||
flutter_local_notifications_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -372,10 +372,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_platform_interface
|
||||
sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef"
|
||||
sha256: "340abf67df238f7f0ef58f4a26d2a83e1ab74c77ab03cd2b2d5018ac64db30b7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0+1"
|
||||
version: "7.1.0"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
@ -385,10 +385,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_markdown
|
||||
sha256: "31c12de79262b5431c5492e9c89948aa789158435f707d3519a7fdef6af28af7"
|
||||
sha256: "9921f9deda326f8a885e202b1e35237eadfc1345239a0f6f0f1ff287e047547f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.22+1"
|
||||
version: "0.7.1"
|
||||
flutter_test:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -403,10 +403,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: fluttertoast
|
||||
sha256: dfdde255317af381bfc1c486ed968d5a43a2ded9c931e87cbecd88767d6a71c1
|
||||
sha256: "81b68579e23fcbcada2db3d50302813d2371664afe6165bc78148050ab94bf66"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.2.4"
|
||||
version: "8.2.5"
|
||||
font_awesome_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -427,10 +427,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
|
||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
version: "4.0.0"
|
||||
get:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -443,10 +443,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: get_it
|
||||
sha256: e6017ce7fdeaf218dc51a100344d8cb70134b80e28b760f8bb23c242437bafd7
|
||||
sha256: d85128a5dae4ea777324730dc65edd9c9f43155c109d5cc0a69cab74139fbac1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.6.7"
|
||||
version: "7.7.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -499,18 +499,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: injectable
|
||||
sha256: cd3c422e13270c81f64ab73c80406b2b2ed563fe59d0ff2093eb7eee63d0bbeb
|
||||
sha256: "3d98967224a5fdd4094a61bf53ed9616c3fbcf3e090bf83e7cb7d436d0c20041"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
version: "2.4.1"
|
||||
injectable_generator:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: injectable_generator
|
||||
sha256: f9d3c05f0938403f79ad6c6d23ec8e37a7a05ad980b1bf9399493f3e41845788
|
||||
sha256: "2ca3ada337eac0ef6b82f8049c970ddb63947738fdf32ac6cbef8d1567d7ba05"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
version: "2.6.1"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -531,10 +531,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
version: "0.7.1"
|
||||
json2yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -547,26 +547,26 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
|
||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.8.1"
|
||||
version: "4.9.0"
|
||||
json_serializable:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: json_serializable
|
||||
sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969
|
||||
sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.7.1"
|
||||
version: "6.8.0"
|
||||
language_code:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: language_code
|
||||
sha256: "45b5320eedf35075176a6398b5d46c408c423be293280f1a95a92c216e7de40b"
|
||||
sha256: "7272519879a86e64fb5f183716ba10cefeb2f191e6e0aa043e0259d0ca0aa122"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
version: "0.5.3+2"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -628,10 +628,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: markdown
|
||||
sha256: "1b134d9f8ff2da15cb298efe6cd8b7d2a78958c1b00384ebcbdf13fe340a6c90"
|
||||
sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.2.1"
|
||||
version: "7.2.2"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -692,18 +692,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: cb44f49b6e690fa766f023d5b22cac6b9affe741dd792b6ac7ad4fabe0d7b097
|
||||
sha256: "2c582551839386fa7ddbc7770658be7c0f87f388a4bff72066478f597c34d17f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
version: "7.0.0"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
|
||||
sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "3.0.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -716,18 +716,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
|
||||
sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
version: "2.1.3"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
|
||||
sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.2"
|
||||
version: "2.2.4"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -796,10 +796,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
sha256: "23dfba8447c076ab5be3dee9ceb66aad345c4a648f0cac292c77b1eb0e800b78"
|
||||
sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.0"
|
||||
version: "4.2.1"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -902,34 +902,34 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: share_plus
|
||||
sha256: "05ec043470319bfbabe0adbc90d3a84cbff0426b9d9f3a6e2ad3e131fa5fa629"
|
||||
sha256: ef3489a969683c4f3d0239010cc8b7a2a46543a8d139e111c06c558875083544
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.2"
|
||||
version: "9.0.0"
|
||||
share_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: share_plus_platform_interface
|
||||
sha256: "251eb156a8b5fa9ce033747d73535bf53911071f8d3b6f4f0b578505ce0d4496"
|
||||
sha256: "0f9e4418835d1b2c3ae78fdb918251959106cefdbc4dd43526e182f80e82f6d4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.0"
|
||||
version: "4.0.0"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
|
||||
sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.2"
|
||||
version: "2.2.3"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
|
||||
sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
version: "2.2.2"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1003,10 +1003,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: slang
|
||||
sha256: "5e08ac915ac27a3508863f37734280d30c3713d56746cd2e4a5da77413da4b95"
|
||||
sha256: ad2a3974fa705017d40e59f9fce5ba738ce78a40c13247bf655d1760d3af018f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.30.1"
|
||||
version: "3.30.2"
|
||||
slang_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1051,18 +1051,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: sqflite
|
||||
sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6
|
||||
sha256: "5ce2e1a15e822c3b4bfb5400455775e421da7098eed8adc8f26298ada7c9308c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
version: "2.3.3"
|
||||
sqflite_common:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5"
|
||||
sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.3"
|
||||
version: "2.5.4"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1091,10 +1091,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: stacked_services
|
||||
sha256: b91f8f35043f80961f4d80cd25ec3677f035461b9e7ee12b04727911ed7f53f7
|
||||
sha256: "5cb55065d85c395da3d37ec0e52ace7f6e367c0b8477aace8c8479009e02cb41"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
version: "1.5.0"
|
||||
stacked_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1163,10 +1163,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: timezone
|
||||
sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0"
|
||||
sha256: a6ccda4a69a442098b602c44e61a1e2b4bf6f5516e875bbf0f427d5df14745d5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.2"
|
||||
version: "0.9.3"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1195,18 +1195,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e"
|
||||
sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.5"
|
||||
version: "6.2.6"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745
|
||||
sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.0"
|
||||
version: "6.3.1"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1243,10 +1243,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "3692a459204a33e04bc94f5fb91158faf4f2c8903281ddd82915adecdb1a901d"
|
||||
sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
version: "2.3.1"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1259,10 +1259,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: uuid
|
||||
sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8
|
||||
sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.3.3"
|
||||
version: "4.4.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1283,18 +1283,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: wakelock_plus
|
||||
sha256: "104d94837bb28c735894dcd592877e990149c380e6358b00c04398ca1426eed4"
|
||||
sha256: c8b7cc80f045533b40a0e6c9109905494e3cf32c0fbd5c62616998e0de44003f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
version: "1.2.4"
|
||||
wakelock_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_plus_platform_interface
|
||||
sha256: "582f2f7aecc7376332d961a0dd1efa9378ce117657e0ade55d9ff72699a55e82"
|
||||
sha256: "422d1cdbb448079a8a62a5a770b69baa489f8f7ca21aef47800c726d404f9d16"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.1"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1315,26 +1315,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2"
|
||||
sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.4"
|
||||
version: "2.4.5"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
|
||||
sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.2.0"
|
||||
version: "5.5.0"
|
||||
win32_registry:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32_registry
|
||||
sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a"
|
||||
sha256: "10589e0d7f4e053f2c61023a31c9ce01146656a70b7b7f0828c0b46d7da2a9bb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
version: "1.1.3"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
64
pubspec.yaml
64
pubspec.yaml
|
@ -10,17 +10,17 @@ environment:
|
|||
sdk: '>=3.0.0 <4.0.0'
|
||||
|
||||
dependencies:
|
||||
animations: ^2.0.7
|
||||
collection: ^1.17.0
|
||||
connectivity_plus: ^6.0.1
|
||||
animations: ^2.0.11
|
||||
collection: ^1.18.0
|
||||
connectivity_plus: ^6.0.3
|
||||
device_apps:
|
||||
git:
|
||||
url: https://github.com/ponces/flutter_plugin_device_apps
|
||||
ref: 0609662324b9e00931fccfa87e9e1b00b7610907 # Branch: revanced-manager
|
||||
device_info_plus: ^9.1.0
|
||||
dio: ^5.0.0
|
||||
dio_cache_interceptor: ^3.4.0
|
||||
dynamic_color: ^1.6.3
|
||||
device_info_plus: ^10.1.0
|
||||
dio: ^5.4.3+1
|
||||
dio_cache_interceptor: ^3.5.0
|
||||
dynamic_color: ^1.7.0
|
||||
dynamic_themes: ^1.1.0
|
||||
expandable: ^5.0.1
|
||||
flutter:
|
||||
|
@ -29,25 +29,25 @@ dependencies:
|
|||
git: # remove once https://github.com/JulianAssmann/flutter_background/pull/79 is merged
|
||||
url: https://github.com/BenjaminHalko/flutter_background
|
||||
ref: 560d21c4148b53933313573e7eafca0b0eb9aadf # Branch: specify-namespace
|
||||
flutter_cache_manager: ^3.3.0
|
||||
flutter_cache_manager: ^3.3.2
|
||||
flutter_file_dialog: ^3.0.2
|
||||
flutter_local_notifications: ^17.0.0
|
||||
flutter_local_notifications: ^17.1.0
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
flutter_markdown: ^0.6.22+1
|
||||
fluttertoast: ^8.2.4
|
||||
font_awesome_flutter: ^10.4.0
|
||||
flutter_markdown: ^0.7.1
|
||||
fluttertoast: ^8.2.5
|
||||
font_awesome_flutter: ^10.7.0
|
||||
google_fonts: ^6.2.1
|
||||
injectable: ^2.1.1
|
||||
intl: ^0.18.0
|
||||
json_annotation: ^4.8.1
|
||||
language_code: ^0.5.1
|
||||
injectable: ^2.4.1
|
||||
intl: ^0.18.1
|
||||
json_annotation: ^4.9.0
|
||||
language_code: ^0.5.3+2
|
||||
logcat:
|
||||
git:
|
||||
url: https://github.com/BenjaminHalko/logcat
|
||||
ref: 4a6d5e0e22292c8eb160cfb9365b9ea29735fd43 # Branch: master
|
||||
package_info_plus: ^6.0.0
|
||||
path_provider: ^2.0.14
|
||||
package_info_plus: ^7.0.0
|
||||
path_provider: ^2.1.3
|
||||
permission_handler: ^11.3.1
|
||||
root:
|
||||
git:
|
||||
|
@ -57,26 +57,26 @@ dependencies:
|
|||
git: # remove once https://github.com/flutter-moum/flutter_screenshot_callback/pull/81 is merged
|
||||
url: https://github.com/BenjaminHalko/flutter_screenshot_callback
|
||||
ref: 1a1616ac91e16cd1f3dd170a81febf27ffce3587 # Branch: master
|
||||
share_plus: ^8.0.2
|
||||
shared_preferences: ^2.1.0
|
||||
share_plus: ^9.0.0
|
||||
shared_preferences: ^2.2.3
|
||||
skeletons: ^0.0.3
|
||||
slang: ^3.25.0
|
||||
slang_flutter: ^3.25.0
|
||||
stacked: ^3.2.0
|
||||
stacked_generator: ^1.1.0
|
||||
stacked_services: ^1.0.0
|
||||
synchronized: ^3.1.0
|
||||
timeago: ^3.3.0
|
||||
timezone: ^0.9.0
|
||||
url_launcher: ^6.1.10
|
||||
wakelock_plus: ^1.1.3
|
||||
slang: ^3.30.2
|
||||
slang_flutter: ^3.30.0
|
||||
stacked: ^3.4.2
|
||||
stacked_generator: ^1.6.0
|
||||
stacked_services: ^1.5.0
|
||||
synchronized: ^3.1.0+1
|
||||
timeago: ^3.6.1
|
||||
timezone: ^0.9.3
|
||||
url_launcher: ^6.2.6
|
||||
wakelock_plus: ^1.2.4
|
||||
|
||||
dev_dependencies:
|
||||
analyzer: ^6.4.1
|
||||
build_runner: 2.4.9
|
||||
flutter_lints: ^3.0.2
|
||||
injectable_generator: ^2.1.5
|
||||
json_serializable: ^6.7.1
|
||||
injectable_generator: ^2.6.1
|
||||
json_serializable: ^6.8.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
|
Loading…
Reference in New Issue