fix: add changelog (wip) on each app item

This commit is contained in:
Alberto Ponces 2022-08-29 15:01:51 +01:00
parent 45f4a5b207
commit 080ceae784
10 changed files with 103 additions and 167 deletions

View File

@ -397,7 +397,7 @@ class MainActivity : FlutterActivity() {
mapOf(
"progress" to 1.0,
"header" to "Finished!",
"log" to "Finished"
"log" to "Finished!"
)
)
}

View File

@ -18,7 +18,9 @@ class PatchedApplication {
DateTime patchDate;
final bool isRooted;
final bool isFromStorage;
bool hasUpdates;
List<String> appliedPatches;
List<String> changelog;
PatchedApplication({
required this.name,
@ -27,9 +29,11 @@ class PatchedApplication {
required this.apkFilePath,
required this.icon,
required this.patchDate,
required this.isRooted,
required this.isFromStorage,
required this.appliedPatches,
this.isRooted = false,
this.isFromStorage = false,
this.hasUpdates = false,
this.appliedPatches = const [],
this.changelog = const [],
});
factory PatchedApplication.fromJson(Map<String, dynamic> json) =>

View File

@ -1,6 +1,7 @@
import 'dart:convert';
import 'dart:io';
import 'package:device_apps/device_apps.dart';
import 'package:github/github.dart';
import 'package:injectable/injectable.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:revanced_manager/constants.dart';
@ -14,9 +15,11 @@ class ManagerAPI {
final GithubAPI _githubAPI = GithubAPI();
final RootAPI _rootAPI = RootAPI();
late SharedPreferences _prefs;
late List<RepositoryCommit> _commits = [];
Future<void> initialize() async {
_prefs = await SharedPreferences.getInstance();
_commits = (await _githubAPI.getCommits(ghOrg, patchesRepo)).toList();
}
Future<File?> downloadPatches(String extension) async {
@ -71,85 +74,58 @@ class ManagerAPI {
setPatchedApps(patchedApps);
}
void saveApp(
ApplicationWithIcon application,
bool isRooted,
bool isFromStorage,
) {
savePatchedApp(
PatchedApplication(
name: application.appName,
packageName: application.packageName,
version: application.versionName!,
apkFilePath: application.apkFilePath,
icon: application.icon,
patchDate: DateTime.now(),
isRooted: isRooted,
isFromStorage: isFromStorage,
appliedPatches: [],
),
);
}
Future<void> reAssessSavedApps() async {
List<PatchedApplication> patchedApps = getPatchedApps();
bool isRoot = isRooted() ?? false;
List<PatchedApplication> patchedApps = getPatchedApps();
List<PatchedApplication> toRemove = [];
for (PatchedApplication app in patchedApps) {
bool existsRoot = false;
if (isRoot) {
existsRoot = await _rootAPI.isAppInstalled(app.packageName);
}
bool existsNonRoot = await DeviceApps.isAppInstalled(app.packageName);
if (!existsRoot && !existsNonRoot) {
bool isRemove = await isAppUninstalled(app, isRoot);
if (isRemove) {
toRemove.add(app);
} else if (existsNonRoot) {
ApplicationWithIcon? application =
await DeviceApps.getApp(app.packageName, true)
as ApplicationWithIcon?;
if (application != null) {
int savedVersionInt =
int.parse(app.version.replaceAll(RegExp('[^0-9]'), ''));
int currentVersionInt = int.parse(
application.versionName!.replaceAll(RegExp('[^0-9]'), ''));
if (savedVersionInt < currentVersionInt) {
toRemove.add(app);
}
} else {
List<String> newChangelog = getAppChangelog(
app.packageName,
app.patchDate,
);
if (newChangelog.isNotEmpty) {
app.changelog = newChangelog;
app.hasUpdates = true;
} else {
app.hasUpdates = false;
}
}
}
patchedApps.removeWhere((a) => toRemove.contains(a));
setPatchedApps(patchedApps);
List<String> apps = await _rootAPI.getInstalledApps();
for (String packageName in apps) {
if (!patchedApps.any((a) => a.packageName == packageName)) {
ApplicationWithIcon? application =
await DeviceApps.getApp(packageName, true) as ApplicationWithIcon?;
if (application != null) {
saveApp(application, true, false);
}
}
}
}
Future<bool> hasAppUpdates(String packageName) async {
// TODO: get status based on last update time on the folder of this app?
return false;
Future<bool> isAppUninstalled(PatchedApplication app, bool isRoot) async {
bool existsRoot = false;
if (isRoot) {
existsRoot = await _rootAPI.isAppInstalled(app.packageName);
}
bool existsNonRoot = await DeviceApps.isAppInstalled(app.packageName);
return !existsRoot && !existsNonRoot;
}
Future<List<String>> getAppChangelog(
String packageName,
DateTime lastUpdated,
) async {
return (await _githubAPI.getCommits(ghOrg, patchesRepo))
List<String> getAppChangelog(String packageName, DateTime patchedDate) {
List<String> newCommits = _commits
.where((c) =>
c.commit != null &&
c.commit!.message != null &&
!c.commit!.message!.startsWith('chore') &&
c.commit!.author != null &&
c.commit!.author!.date != null)
.map((c) => ' - ${c.commit!.message!}')
.toList()
.sublist(0, 3);
c.commit!.author!.date != null &&
c.commit!.author!.date!.isAfter(patchedDate))
.map((c) => c.commit!.message!)
.toList();
if (newCommits.isNotEmpty) {
int firstChore = newCommits.indexWhere((c) => c.startsWith('chore'));
int secondChore =
newCommits.indexWhere((c) => c.startsWith('chore'), firstChore + 1);
if (firstChore >= 0 && secondChore > firstChore) {
return newCommits.sublist(firstChore + 1, secondChore);
}
}
return List.empty();
}
}

View File

@ -35,8 +35,6 @@ class AppSelectorViewModel extends BaseViewModel {
icon: application.icon,
patchDate: DateTime.now(),
isRooted: _isRooted,
isFromStorage: false,
appliedPatches: [],
);
locator<PatcherViewModel>().selectedPatches.clear();
locator<PatcherViewModel>().notifyListeners();
@ -63,7 +61,6 @@ class AppSelectorViewModel extends BaseViewModel {
patchDate: DateTime.now(),
isRooted: _isRooted,
isFromStorage: true,
appliedPatches: [],
);
locator<PatcherViewModel>().selectedPatches.clear();
locator<PatcherViewModel>().notifyListeners();

View File

@ -111,8 +111,8 @@ class HomeView extends StatelessWidget {
),
const SizedBox(height: 14),
model.showUpdatableApps
? AvailableUpdatesCard()
: InstalledAppsCard()
? const AvailableUpdatesCard()
: const InstalledAppsCard()
],
),
),

View File

@ -22,8 +22,11 @@ class HomeViewModel extends BaseViewModel {
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
bool showUpdatableApps = true;
List<PatchedApplication> patchedInstalledApps = [];
List<PatchedApplication> patchedUpdatableApps = [];
Future<void> initialize() async {
await _getPatchedApps();
await _patcherAPI.loadPatches();
await flutterLocalNotificationsPlugin.initialize(
const InitializationSettings(
@ -31,6 +34,7 @@ class HomeViewModel extends BaseViewModel {
),
onSelectNotification: (p) => DeviceApps.openApp('app.revanced.manager'),
);
_managerAPI.reAssessSavedApps().then((_) => notifyListeners());
}
void toggleUpdatableApps(bool value) {
@ -46,17 +50,16 @@ class HomeViewModel extends BaseViewModel {
locator<MainViewModel>().setIndex(1);
}
Future<List<PatchedApplication>> getPatchedApps(bool isUpdatable) async {
await _managerAPI.reAssessSavedApps();
List<PatchedApplication> list = [];
List<PatchedApplication> patchedApps = _managerAPI.getPatchedApps();
for (PatchedApplication app in patchedApps) {
bool hasUpdates = await _managerAPI.hasAppUpdates(app.packageName);
if (hasUpdates == isUpdatable) {
list.add(app);
}
}
return list;
Future<void> _getPatchedApps() async {
patchedInstalledApps = _managerAPI
.getPatchedApps()
.where((app) => app.hasUpdates == false)
.toList();
patchedUpdatableApps = _managerAPI
.getPatchedApps()
.where((app) => app.hasUpdates == true)
.toList();
notifyListeners();
}
Future<bool> hasManagerUpdates() async {

View File

@ -70,10 +70,10 @@ class InstallerViewModel extends BaseViewModel {
void update(double value, String header, String log) {
progress = value;
isInstalled = false;
isPatching = progress == 1.0 ? false : true;
if (progress == 0.0) {
logs = '';
isInstalled = false;
}
if (header.isNotEmpty) {
headerLogs = header;
@ -148,9 +148,9 @@ class InstallerViewModel extends BaseViewModel {
);
isInstalled = await _patcherAPI.installPatchedFile(_app!);
if (isInstalled) {
update(1.0, 'Installed!', 'Installed');
update(1.0, 'Installed!', 'Installed!');
_app!.patchDate = DateTime.now();
_app!.appliedPatches.addAll(_patches.map((p) => p.name).toList());
_app!.appliedPatches = _patches.map((p) => p.name).toList();
_managerAPI.savePatchedApp(_app!);
} else {
update(1.0, 'Aborting...', 'An error occurred! Aborting');

View File

@ -1,54 +1,32 @@
import 'package:flutter/material.dart';
import 'package:revanced_manager/app/app.locator.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';
class AvailableUpdatesCard extends StatelessWidget {
AvailableUpdatesCard({
const AvailableUpdatesCard({
Key? key,
}) : super(key: key);
final ManagerAPI _managerAPI = locator<ManagerAPI>();
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
FutureBuilder<List<PatchedApplication>>(
future: locator<HomeViewModel>().getPatchedApps(true),
builder: (context, snapshot) => snapshot.hasData &&
snapshot.data!.isNotEmpty
? ListView.builder(
return ListView(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) => FutureBuilder<List<String>>(
future: _managerAPI.getAppChangelog(
snapshot.data![index].packageName,
snapshot.data![index].patchDate,
),
initialData: List.empty(),
builder: (context, snapshot2) => ApplicationItem(
icon: snapshot.data![index].icon,
name: snapshot.data![index].name,
patchDate: snapshot.data![index].patchDate,
changelog: '${snapshot2.data!.join('\n')}\n...',
physics: const NeverScrollableScrollPhysics(),
children: locator<HomeViewModel>()
.patchedUpdatableApps
.map((app) => ApplicationItem(
icon: app.icon,
name: app.name,
patchDate: app.patchDate,
changelog: app.changelog,
isUpdatableApp: true,
onPressed: () =>
locator<HomeViewModel>().navigateToPatcher(
snapshot.data![index],
onPressed: () => locator<HomeViewModel>().navigateToPatcher(
app,
),
),
),
)
: Container(),
),
],
))
.toList(),
);
}
}

View File

@ -1,54 +1,31 @@
import 'package:device_apps/device_apps.dart';
import 'package:flutter/material.dart';
import 'package:revanced_manager/app/app.locator.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';
class InstalledAppsCard extends StatelessWidget {
InstalledAppsCard({
const InstalledAppsCard({
Key? key,
}) : super(key: key);
final ManagerAPI _managerAPI = locator<ManagerAPI>();
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
FutureBuilder<List<PatchedApplication>>(
future: locator<HomeViewModel>().getPatchedApps(false),
builder: (context, snapshot) => snapshot.hasData &&
snapshot.data!.isNotEmpty
? ListView.builder(
return ListView(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) => FutureBuilder<List<String>>(
future: _managerAPI.getAppChangelog(
snapshot.data![index].packageName,
snapshot.data![index].patchDate,
),
initialData: const ['Loading'],
builder: (context, snapshot2) => ApplicationItem(
icon: snapshot.data![index].icon,
name: snapshot.data![index].name,
patchDate: snapshot.data![index].patchDate,
changelog: '${snapshot2.data!.join('\n')}\n(...)',
physics: const NeverScrollableScrollPhysics(),
children: locator<HomeViewModel>()
.patchedInstalledApps
.map((app) => ApplicationItem(
icon: app.icon,
name: app.name,
patchDate: app.patchDate,
changelog: app.changelog,
isUpdatableApp: false,
onPressed: () => DeviceApps.openApp(
snapshot.data![index].packageName,
),
),
),
)
: Container(),
),
],
onPressed: () => DeviceApps.openApp(app.packageName),
))
.toList(),
);
}
}

View File

@ -12,7 +12,7 @@ class ApplicationItem extends StatelessWidget {
final Uint8List icon;
final String name;
final DateTime patchDate;
final String changelog;
final List<String> changelog;
final bool isUpdatableApp;
final Function() onPressed;
@ -103,8 +103,9 @@ class ApplicationItem extends StatelessWidget {
style: kRobotoTextStyle.copyWith(fontWeight: FontWeight.w700),
),
),
const SizedBox(height: 4),
Text(
changelog,
' - ${changelog.join('\n- ')}',
style: kRobotoTextStyle,
),
],