From 769ff72f9838c8f569a7269c97e3c68fde9fb7fe Mon Sep 17 00:00:00 2001 From: Aunali321 <48486084+Aunali321@users.noreply.github.com> Date: Sat, 6 Aug 2022 17:43:28 +0530 Subject: [PATCH] refactor: migrate to stacked architecture. * feat: mostly done stacked architecture. * refactor: migration to stacked architecture. --- lib/app/app.dart | 14 + lib/app/app.locator.dart | 22 ++ lib/app/app.router.dart | 102 ++++++ lib/main.dart | 75 ++-- lib/main_viewmodel.dart | 6 + lib/{backend/api => services}/github_api.dart | 24 +- .../api => services}/manager_api.dart | 3 +- .../third_party_services_modules.dart | 12 + lib/ui/screens/app_selector_screen.dart | 92 ----- lib/ui/screens/home_screen.dart | 66 ---- lib/ui/screens/patcher_screen.dart | 51 --- .../views/app_selector/app_selector_view.dart | 101 ++++++ .../app_selector/app_selector_viewmodel.dart | 15 + lib/ui/views/home/home_view.dart | 71 ++++ lib/ui/views/home/home_viewmodel.dart | 8 + lib/ui/views/patcher/patcher_view.dart | 53 +++ lib/ui/views/patcher/patcher_viewmodel.dart | 12 + lib/ui/widgets/latest_commit_card.dart | 2 +- pubspec.lock | 343 ++++++++++++++++++ pubspec.yaml | 20 +- 20 files changed, 825 insertions(+), 267 deletions(-) create mode 100644 lib/app/app.dart create mode 100644 lib/app/app.locator.dart create mode 100644 lib/app/app.router.dart create mode 100644 lib/main_viewmodel.dart rename lib/{backend/api => services}/github_api.dart (60%) rename lib/{backend/api => services}/manager_api.dart (96%) create mode 100644 lib/services/third_party_services_modules.dart delete mode 100644 lib/ui/screens/app_selector_screen.dart delete mode 100644 lib/ui/screens/home_screen.dart delete mode 100644 lib/ui/screens/patcher_screen.dart create mode 100644 lib/ui/views/app_selector/app_selector_view.dart create mode 100644 lib/ui/views/app_selector/app_selector_viewmodel.dart create mode 100644 lib/ui/views/home/home_view.dart create mode 100644 lib/ui/views/home/home_viewmodel.dart create mode 100644 lib/ui/views/patcher/patcher_view.dart create mode 100644 lib/ui/views/patcher/patcher_viewmodel.dart diff --git a/lib/app/app.dart b/lib/app/app.dart new file mode 100644 index 00000000..d256ef6c --- /dev/null +++ b/lib/app/app.dart @@ -0,0 +1,14 @@ +import 'package:revanced_manager_flutter/ui/views/app_selector/app_selector_view.dart'; +import 'package:revanced_manager_flutter/ui/views/home/home_view.dart'; +import 'package:revanced_manager_flutter/ui/views/patcher/patcher_view.dart'; +import 'package:stacked/stacked_annotations.dart'; +import 'package:stacked_services/stacked_services.dart'; + +@StackedApp(routes: [ + MaterialRoute(page: HomeView), + MaterialRoute(page: AppSelectorView), + MaterialRoute(page: PatcherView), +], dependencies: [ + LazySingleton(classType: NavigationService), +]) +class AppSetup {} diff --git a/lib/app/app.locator.dart b/lib/app/app.locator.dart new file mode 100644 index 00000000..88ad8733 --- /dev/null +++ b/lib/app/app.locator.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// StackedLocatorGenerator +// ************************************************************************** + +// ignore_for_file: public_member_api_docs + +import 'package:stacked_core/stacked_core.dart'; +import 'package:stacked_services/src/navigation/navigation_service.dart'; + +final locator = StackedLocator.instance; + +Future setupLocator( + {String? environment, EnvironmentFilter? environmentFilter}) async { +// Register environments + locator.registerEnvironment( + environment: environment, environmentFilter: environmentFilter); + +// Register dependencies + locator.registerLazySingleton(() => NavigationService()); +} diff --git a/lib/app/app.router.dart b/lib/app/app.router.dart new file mode 100644 index 00000000..3dd06437 --- /dev/null +++ b/lib/app/app.router.dart @@ -0,0 +1,102 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// StackedRouterGenerator +// ************************************************************************** + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:flutter/material.dart'; +import 'package:stacked/stacked.dart' as _i1; +import 'package:stacked_services/stacked_services.dart' as _i5; + +import '../ui/views/app_selector/app_selector_view.dart' as _i3; +import '../ui/views/home/home_view.dart' as _i2; +import '../ui/views/patcher/patcher_view.dart' as _i4; + +class Routes { + static const homeView = '/home-view'; + + static const appSelectorView = '/app-selector-view'; + + static const patcherView = '/patcher-view'; + + static const all = {homeView, appSelectorView, patcherView}; +} + +class StackedRouter extends _i1.RouterBase { + final _routes = <_i1.RouteDef>[ + _i1.RouteDef(Routes.homeView, page: _i2.HomeView), + _i1.RouteDef(Routes.appSelectorView, page: _i3.AppSelectorView), + _i1.RouteDef(Routes.patcherView, page: _i4.PatcherView) + ]; + + final _pagesMap = { + _i2.HomeView: (data) { + return MaterialPageRoute( + builder: (context) => const _i2.HomeView(), + settings: data, + ); + }, + _i3.AppSelectorView: (data) { + return MaterialPageRoute( + builder: (context) => const _i3.AppSelectorView(), + settings: data, + ); + }, + _i4.PatcherView: (data) { + return MaterialPageRoute( + builder: (context) => const _i4.PatcherView(), + settings: data, + ); + } + }; + + @override + List<_i1.RouteDef> get routes => _routes; + @override + Map get pagesMap => _pagesMap; +} + +extension NavigatorStateExtension on _i5.NavigationService { + Future navigateToHomeView( + [int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function( + BuildContext, Animation, Animation, Widget)? + transition]) async { + navigateTo(Routes.homeView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToAppSelectorView( + [int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function( + BuildContext, Animation, Animation, Widget)? + transition]) async { + navigateTo(Routes.appSelectorView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToPatcherView( + [int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function( + BuildContext, Animation, Animation, Widget)? + transition]) async { + navigateTo(Routes.patcherView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } +} diff --git a/lib/main.dart b/lib/main.dart index fd601a65..76bf3ecb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,16 @@ import 'package:flutter/material.dart'; +import 'package:revanced_manager_flutter/app/app.locator.dart'; +import 'package:revanced_manager_flutter/app/app.router.dart'; +import 'package:revanced_manager_flutter/main_viewmodel.dart'; import 'package:revanced_manager_flutter/theme.dart'; -import 'package:revanced_manager_flutter/ui/screens/home_screen.dart'; -import 'package:revanced_manager_flutter/ui/screens/patcher_screen.dart'; +import 'package:revanced_manager_flutter/ui/views/home/home_view.dart'; +import 'package:revanced_manager_flutter/ui/views/patcher/patcher_view.dart'; +import 'package:stacked/stacked.dart'; +import 'package:stacked_services/stacked_services.dart'; -void main() { +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + setupLocator(); runApp(const MyApp()); } @@ -17,47 +24,47 @@ class MyApp extends StatelessWidget { title: 'ReVanced Manager', theme: lightTheme, darkTheme: darkTheme, + navigatorKey: StackedService.navigatorKey, + onGenerateRoute: StackedRouter().onGenerateRoute, home: const Navigation(), ); } } -class Navigation extends StatefulWidget { +class Navigation extends StatelessWidget { const Navigation({Key? key}) : super(key: key); - @override - State createState() => _NavigationState(); -} - -class _NavigationState extends State { - int currentPageIndex = 0; - final List screens = [ - const HomeScreen(), - const PatcherScreen(), - ]; - @override Widget build(BuildContext context) { - return Scaffold( - body: screens[currentPageIndex], - bottomNavigationBar: NavigationBar( - onDestinationSelected: (int index) { - setState(() { - currentPageIndex = index; - }); - }, - selectedIndex: currentPageIndex, - destinations: const [ - NavigationDestination( - icon: Icon(Icons.dashboard), - label: "Dashboard", - ), - NavigationDestination( - icon: Icon(Icons.build), - label: "Patcher", - ), - ], + return ViewModelBuilder.reactive( + viewModelBuilder: () => MainViewModel(), + builder: (context,MainViewModel model, child) => Scaffold( + body: getViewForIndex(model.currentIndex), + bottomNavigationBar: NavigationBar( + onDestinationSelected: model.setIndex, + selectedIndex: model.currentIndex, + destinations: const [ + NavigationDestination( + icon: Icon(Icons.dashboard), + label: "Dashboard", + ), + NavigationDestination( + icon: Icon(Icons.build), + label: "Patcher", + ), + ], + ), ), ); } + Widget getViewForIndex(int index) { + switch (index) { + case 0: + return const HomeView(); + case 1: + return const PatcherView(); + default: + return const HomeView(); + } + } } diff --git a/lib/main_viewmodel.dart b/lib/main_viewmodel.dart new file mode 100644 index 00000000..5555e751 --- /dev/null +++ b/lib/main_viewmodel.dart @@ -0,0 +1,6 @@ +import 'package:stacked/stacked.dart'; + +class MainViewModel extends IndexTrackingViewModel { + + +} diff --git a/lib/backend/api/github_api.dart b/lib/services/github_api.dart similarity index 60% rename from lib/backend/api/github_api.dart rename to lib/services/github_api.dart index 09b05009..5696be19 100644 --- a/lib/backend/api/github_api.dart +++ b/lib/services/github_api.dart @@ -1,17 +1,14 @@ import 'package:github/github.dart'; +import 'package:injectable/injectable.dart'; +@lazySingleton class GithubAPI { var github = GitHub(); Future latestRelease(String org, repoName) async { var latestRelease = await github.repositories .getLatestRelease(RepositorySlug(org, repoName)); - var dlurl = latestRelease.assets - ?.firstWhere((element) => - element.browserDownloadUrl!.contains(".jar") || - element.browserDownloadUrl!.contains(".apk")) - .browserDownloadUrl; - print(dlurl); + var dlurl = latestRelease.assets?.first.browserDownloadUrl; return dlurl; } @@ -27,15 +24,12 @@ class GithubAPI { if (hours > 24) { var days = (commitTime.inDays).abs().toString(); - print("$days days"); return "$days days"; } else if (hours > 1 && hours < 24) { var hours = (commitTime.inHours).abs().toString(); - print("$hours hours"); return "$hours hours"; } else { var minutes = (commitTime.inMinutes).abs().toString(); - print("$minutes minutes"); return "$minutes mins"; } } @@ -43,17 +37,7 @@ class GithubAPI { Future contributors(String org, repoName) async { var contributors = github.repositories.listContributors(RepositorySlug(org, repoName)); - contributors.forEach((contributor) { - print(contributor.login); - print(contributor.avatarUrl); - }); + contributors.forEach((contributor) {}); return contributors; } } - -void main(List args) { - GithubAPI githubAPI = GithubAPI(); - githubAPI.latestRelease('revanced', 'revanced-patches'); - // githubAPI.latestCommitTime("revanced", "revanced-patches"); - // githubAPI.contributors("revanced", "revanced-manager"); -} diff --git a/lib/backend/api/manager_api.dart b/lib/services/manager_api.dart similarity index 96% rename from lib/backend/api/manager_api.dart rename to lib/services/manager_api.dart index e4857c1f..168c67bc 100644 --- a/lib/backend/api/manager_api.dart +++ b/lib/services/manager_api.dart @@ -1,11 +1,12 @@ import 'dart:io'; import 'package:dio/dio.dart'; +import 'package:injectable/injectable.dart'; import 'package:path_provider/path_provider.dart' as p; import 'package:revanced_manager_flutter/constants.dart'; import 'github_api.dart'; // use path_provider to get the path of the storage directory - +@lazySingleton class ManagerAPI { Dio dio = Dio(); GithubAPI githubAPI = GithubAPI(); diff --git a/lib/services/third_party_services_modules.dart b/lib/services/third_party_services_modules.dart new file mode 100644 index 00000000..6f54f6fb --- /dev/null +++ b/lib/services/third_party_services_modules.dart @@ -0,0 +1,12 @@ +import 'package:injectable/injectable.dart'; +import 'package:stacked_services/stacked_services.dart'; + +@module +abstract class ThirdPartyServicesModule { + @lazySingleton + NavigationService get navigationService; + @lazySingleton + DialogService get dialogService; + @lazySingleton + SnackbarService get snackbarService; +} diff --git a/lib/ui/screens/app_selector_screen.dart b/lib/ui/screens/app_selector_screen.dart deleted file mode 100644 index 3dbd0512..00000000 --- a/lib/ui/screens/app_selector_screen.dart +++ /dev/null @@ -1,92 +0,0 @@ -import 'package:device_apps/device_apps.dart'; -import 'package:flutter/material.dart'; -import 'package:revanced_manager_flutter/ui/widgets/installed_app_item.dart'; -import 'package:revanced_manager_flutter/ui/widgets/search_bar.dart'; - -class AppSelectorScreen extends StatefulWidget { - const AppSelectorScreen({Key? key}) : super(key: key); - - @override - State createState() => _AppSelectorScreenState(); -} - -class _AppSelectorScreenState extends State { - List apps = []; - String query = ''; - - void getApps() async { - apps = await DeviceApps.getInstalledApplications(); - setState(() {}); - } - - @override - void initState() { - getApps(); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - body: SafeArea( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 12.0), - child: Column( - children: [ - SearchBar( - onQueryChanged: (searchQuery) { - setState(() { - query = searchQuery; - }); - }, - ), - if (query.isEmpty || query.length < 2) - apps.isEmpty - ? const Center( - child: CircularProgressIndicator(), - ) - : Expanded( - child: ListView.builder( - itemCount: apps.length, - itemBuilder: (context, index) { - //sort alphabetically - apps.sort((a, b) => a.appName.compareTo(b.appName)); - return InstalledAppItem( - name: apps[index].appName, - pkgName: apps[index].packageName, - isSelected: false, - ); - }, - ), - ), - if (query.isNotEmpty) - apps.isEmpty - ? const Center( - child: Text('No apps found'), - ) - : Expanded( - child: ListView.builder( - itemCount: apps.length, - itemBuilder: (context, index) { - apps.sort((a, b) => a.appName.compareTo(b.appName)); - if (apps[index].appName.toLowerCase().contains( - query.toLowerCase(), - )) { - return InstalledAppItem( - name: apps[index].appName, - pkgName: apps[index].packageName, - isSelected: false, - ); - } else { - return SizedBox(); - } - }, - ), - ), - ], - ), - ), - ), - ); - } -} diff --git a/lib/ui/screens/home_screen.dart b/lib/ui/screens/home_screen.dart deleted file mode 100644 index ec1377ad..00000000 --- a/lib/ui/screens/home_screen.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:revanced_manager_flutter/ui/widgets/available_updates_card.dart'; -import 'package:revanced_manager_flutter/ui/widgets/installed_apps_card.dart'; -import 'package:revanced_manager_flutter/ui/widgets/latest_commit_card.dart'; - -class HomeScreen extends StatelessWidget { - const HomeScreen({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: SafeArea( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 0.0, - horizontal: 20.0, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: () {}, - icon: const Icon( - Icons.more_vert, - ), - ), - ), - const SizedBox(height: 60), - Text( - "Dashboard", - style: GoogleFonts.inter( - fontSize: 28, - ), - ), - const SizedBox(height: 23), - Text( - "ReVanced Updates", - style: GoogleFonts.inter( - fontSize: 18, - ), - ), - const SizedBox(height: 10), - const LatestCommitCard(), - const SizedBox(height: 14), - Text( - "Patched Applications", - style: GoogleFonts.inter( - fontSize: 18, - ), - ), - const SizedBox(height: 14), - const AvailableUpdatesCard(), - const SizedBox(height: 15), - const InstalledAppsCard(), - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/ui/screens/patcher_screen.dart b/lib/ui/screens/patcher_screen.dart deleted file mode 100644 index d87ff2fc..00000000 --- a/lib/ui/screens/patcher_screen.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:revanced_manager_flutter/ui/screens/app_selector_screen.dart'; -import 'package:revanced_manager_flutter/ui/widgets/app_selector_card.dart'; -import 'package:revanced_manager_flutter/ui/widgets/patch_selector_card.dart'; - -class PatcherScreen extends StatelessWidget { - const PatcherScreen({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Scaffold( - floatingActionButton: FloatingActionButton( - onPressed: () {}, - child: const Icon( - Icons.build, - color: Colors.white, - ), - ), - body: SafeArea( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 12), - Text( - "Patcher", - style: GoogleFonts.inter( - fontSize: 28, - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 23), - AppSelectorCard( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const AppSelectorScreen())); - }, - ), - const SizedBox(height: 16), - const PatchSelectorCard(), - ], - ), - ), - ), - ); - } -} diff --git a/lib/ui/views/app_selector/app_selector_view.dart b/lib/ui/views/app_selector/app_selector_view.dart new file mode 100644 index 00000000..93d78c61 --- /dev/null +++ b/lib/ui/views/app_selector/app_selector_view.dart @@ -0,0 +1,101 @@ +import 'package:device_apps/device_apps.dart'; +import 'package:flutter/material.dart'; +import 'package:revanced_manager_flutter/ui/widgets/installed_app_item.dart'; +import 'package:revanced_manager_flutter/ui/widgets/search_bar.dart'; +import 'package:stacked/stacked.dart'; + +import 'app_selector_viewmodel.dart'; + +class AppSelectorView extends StatefulWidget { + const AppSelectorView({Key? key}) : super(key: key); + + @override + State createState() => _AppSelectorViewState(); +} + +class _AppSelectorViewState extends State { + List apps = []; + String query = ''; + + void getApps() async { + apps = await DeviceApps.getInstalledApplications(); + setState(() {}); + } + + @override + void initState() { + getApps(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return ViewModelBuilder.reactive( + builder: (context, model, child) => Scaffold( + body: SafeArea( + child: Padding( + padding: + const EdgeInsets.symmetric(vertical: 4.0, horizontal: 12.0), + child: Column( + children: [ + SearchBar( + onQueryChanged: (searchQuery) { + setState(() { + query = searchQuery; + }); + }, + ), + if (query.isEmpty || query.length < 2) + apps.isEmpty + ? const Center( + child: CircularProgressIndicator(), + ) + : Expanded( + child: ListView.builder( + itemCount: apps.length, + itemBuilder: (context, index) { + //sort alphabetically + apps.sort( + (a, b) => a.appName.compareTo(b.appName)); + return InstalledAppItem( + name: apps[index].appName, + pkgName: apps[index].packageName, + isSelected: false, + ); + }, + ), + ), + if (query.isNotEmpty) + apps.isEmpty + ? const Center( + child: Text('No apps found'), + ) + : Expanded( + child: ListView.builder( + itemCount: apps.length, + itemBuilder: (context, index) { + apps.sort( + (a, b) => a.appName.compareTo(b.appName)); + if (apps[index].appName.toLowerCase().contains( + query.toLowerCase(), + )) { + return InstalledAppItem( + name: apps[index].appName, + pkgName: apps[index].packageName, + isSelected: false, + ); + } else { + return SizedBox(); + } + }, + ), + ), + ], + ), + ), + ), + ), + viewModelBuilder: () => AppSelectorViewModel(), + ); + } +} diff --git a/lib/ui/views/app_selector/app_selector_viewmodel.dart b/lib/ui/views/app_selector/app_selector_viewmodel.dart new file mode 100644 index 00000000..50d972ca --- /dev/null +++ b/lib/ui/views/app_selector/app_selector_viewmodel.dart @@ -0,0 +1,15 @@ +import 'package:device_apps/device_apps.dart'; +import 'package:stacked/stacked.dart'; + +class AppSelectorViewModel extends BaseViewModel { + List apps = []; + String query = ''; + + void initialization() { + getApps(); + } + + void getApps() async { + apps = await DeviceApps.getInstalledApplications(); + } +} diff --git a/lib/ui/views/home/home_view.dart b/lib/ui/views/home/home_view.dart new file mode 100644 index 00000000..ea214761 --- /dev/null +++ b/lib/ui/views/home/home_view.dart @@ -0,0 +1,71 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:revanced_manager_flutter/ui/widgets/available_updates_card.dart'; +import 'package:revanced_manager_flutter/ui/widgets/installed_apps_card.dart'; +import 'package:revanced_manager_flutter/ui/widgets/latest_commit_card.dart'; +import 'package:stacked/stacked.dart'; +import 'home_viewmodel.dart'; + +class HomeView extends StatelessWidget { + const HomeView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ViewModelBuilder.reactive( + builder: (context, model, child) => Scaffold( + body: SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 0.0, + horizontal: 20.0, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.topRight, + child: IconButton( + onPressed: () {}, + icon: const Icon( + Icons.more_vert, + ), + ), + ), + const SizedBox(height: 60), + Text( + "Dashboard", + style: GoogleFonts.inter( + fontSize: 28, + ), + ), + const SizedBox(height: 23), + Text( + "ReVanced Updates", + style: GoogleFonts.inter( + fontSize: 18, + ), + ), + const SizedBox(height: 10), + const LatestCommitCard(), + const SizedBox(height: 14), + Text( + "Patched Applications", + style: GoogleFonts.inter( + fontSize: 18, + ), + ), + const SizedBox(height: 14), + const AvailableUpdatesCard(), + const SizedBox(height: 15), + const InstalledAppsCard(), + ], + ), + ), + ), + ), + ), + viewModelBuilder: () => HomeViewModel(), + ); + } +} diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart new file mode 100644 index 00000000..a73debe7 --- /dev/null +++ b/lib/ui/views/home/home_viewmodel.dart @@ -0,0 +1,8 @@ +import 'package:revanced_manager_flutter/app/app.locator.dart'; +import 'package:revanced_manager_flutter/services/manager_api.dart'; +import 'package:stacked/stacked.dart'; + +class HomeViewModel extends BaseViewModel { + Future downloadPatches() => locator().downloadPatches(); + Future downloadIntegrations() => locator().downloadIntegrations(); +} diff --git a/lib/ui/views/patcher/patcher_view.dart b/lib/ui/views/patcher/patcher_view.dart new file mode 100644 index 00000000..43f7c6a5 --- /dev/null +++ b/lib/ui/views/patcher/patcher_view.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:revanced_manager_flutter/ui/views/app_selector/app_selector_view.dart'; +import 'package:revanced_manager_flutter/ui/widgets/app_selector_card.dart'; +import 'package:revanced_manager_flutter/ui/widgets/patch_selector_card.dart'; +import 'package:stacked/stacked.dart'; + +import 'patcher_viewmodel.dart'; + +class PatcherView extends StatelessWidget { + const PatcherView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ViewModelBuilder.reactive( + builder: (context, PatcherViewModel model, child) => Scaffold( + floatingActionButton: FloatingActionButton( + onPressed: () {}, + child: const Icon( + Icons.build, + color: Colors.white, + ), + ), + body: SafeArea( + child: Padding( + padding: + const EdgeInsets.symmetric(vertical: 12.0, horizontal: 12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 12), + Text( + "Patcher", + style: GoogleFonts.inter( + fontSize: 28, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 23), + AppSelectorCard( + onPressed: model.navigateToAppSelector, + ), + const SizedBox(height: 16), + const PatchSelectorCard(), + ], + ), + ), + ), + ), + viewModelBuilder: () => PatcherViewModel(), + ); + } +} diff --git a/lib/ui/views/patcher/patcher_viewmodel.dart b/lib/ui/views/patcher/patcher_viewmodel.dart new file mode 100644 index 00000000..cfa3ba8a --- /dev/null +++ b/lib/ui/views/patcher/patcher_viewmodel.dart @@ -0,0 +1,12 @@ +import 'package:revanced_manager_flutter/app/app.locator.dart'; +import 'package:revanced_manager_flutter/app/app.router.dart'; +import 'package:stacked/stacked.dart'; +import 'package:stacked_services/stacked_services.dart'; + +class PatcherViewModel extends BaseViewModel { + final _naviagtionService = locator(); + + void navigateToAppSelector() { + _naviagtionService.navigateTo(Routes.appSelectorView); + } +} diff --git a/lib/ui/widgets/latest_commit_card.dart b/lib/ui/widgets/latest_commit_card.dart index 6ba7b44a..5c7dfbfb 100644 --- a/lib/ui/widgets/latest_commit_card.dart +++ b/lib/ui/widgets/latest_commit_card.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:revanced_manager_flutter/backend/api/github_api.dart'; +import 'package:revanced_manager_flutter/services/github_api.dart'; import 'package:revanced_manager_flutter/constants.dart'; import 'package:revanced_manager_flutter/ui/widgets/patch_text_button.dart'; diff --git a/pubspec.lock b/pubspec.lock index b422cec1..4f90dc51 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,27 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "43.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.1" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" async: dependency: transitive description: @@ -15,6 +36,62 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + build: + dependency: transitive + description: + name: build + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" + build_config: + dependency: transitive + description: + name: build_config + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + build_daemon: + dependency: transitive + description: + name: build_daemon + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + build_runner: + dependency: "direct dev" + description: + name: build_runner + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + url: "https://pub.dartlang.org" + source: hosted + version: "7.2.3" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.dartlang.org" + source: hosted + version: "8.4.0" characters: dependency: transitive description: @@ -29,6 +106,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" clock: dependency: transitive description: @@ -36,6 +120,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.0" collection: dependency: transitive description: @@ -43,6 +134,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.16.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" crypto: dependency: transitive description: @@ -57,6 +155,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.5" + dart_style: + dependency: transitive + description: + name: dart_style + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.3" device_apps: dependency: "direct main" description: @@ -92,6 +197,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.1.2" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" flutter: dependency: "direct main" description: flutter @@ -116,6 +228,27 @@ packages: description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" + get: + dependency: transitive + description: + name: get + url: "https://pub.dartlang.org" + source: hosted + version: "4.6.5" + get_it: + dependency: "direct main" + description: + name: get_it + url: "https://pub.dartlang.org" + source: hosted + version: "7.2.0" github: dependency: "direct main" description: @@ -123,6 +256,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "9.4.0" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" google_fonts: dependency: "direct main" description: @@ -130,6 +270,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.1" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" http: dependency: "direct main" description: @@ -137,6 +284,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.13.4" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.1" http_parser: dependency: transitive description: @@ -144,6 +298,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.1" + injectable: + dependency: "direct main" + description: + name: injectable + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.3" + injectable_generator: + dependency: "direct dev" + description: + name: injectable_generator + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.4" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.4" json_annotation: dependency: transitive description: @@ -158,6 +340,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + logger: + dependency: transitive + description: + name: logger + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" matcher: dependency: transitive description: @@ -179,6 +375,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.7.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" path: dependency: transitive description: @@ -270,6 +487,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.1" process: dependency: transitive description: @@ -277,11 +501,60 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.4" + provider: + dependency: transitive + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.3" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + recase: + dependency: transitive + description: + name: recase + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.2" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.2" source_span: dependency: transitive description: @@ -296,6 +569,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.10.0" + stacked: + dependency: "direct main" + description: + name: stacked + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.15" + stacked_core: + dependency: transitive + description: + name: stacked_core + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.4" + stacked_generator: + dependency: "direct main" + description: + name: stacked_generator + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.14" + stacked_services: + dependency: "direct main" + description: + name: stacked_services + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.3" stream_channel: dependency: transitive description: @@ -303,6 +604,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" string_scanner: dependency: transitive description: @@ -324,6 +632,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.9" + timing: + dependency: transitive + description: + name: timing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" typed_data: dependency: transitive description: @@ -331,6 +646,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + universal_io: + dependency: transitive + description: + name: universal_io + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" vector_math: dependency: transitive description: @@ -338,6 +660,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" win32: dependency: transitive description: @@ -359,6 +695,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.1.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.1" sdks: dart: ">=2.17.5 <3.0.0" flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1b292c93..92da33f9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,12 +36,26 @@ dependencies: cupertino_icons: ^1.0.2 flutter_svg: ^1.1.1+1 google_fonts: ^3.0.1 + + #networking http: ^0.13.4 - github: ^9.4.0 - path_provider: ^2.0.11 dio: ^4.0.6 + github: ^9.4.0 + + path_provider: ^2.0.11 device_apps: ^2.2.0 + #state management + stacked: ^2.3.15 + + #navigation + stacked_services: ^0.9.3 + + #inversion of control + get_it: ^7.2.0 + injectable: ^1.5.3 + stacked_generator: ^0.7.14 + dev_dependencies: flutter_test: sdk: flutter @@ -52,6 +66,8 @@ dev_dependencies: # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^2.0.0 + build_runner: ^2.2.0 + injectable_generator: ^1.5.4 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec