diff --git a/lib/app/app.dart b/lib/app/app.dart index f9d673b6..454af0e4 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -1,6 +1,7 @@ import 'package:revanced_manager/services/patcher_api.dart'; import 'package:revanced_manager/ui/views/app_selector/app_selector_view.dart'; import 'package:revanced_manager/ui/views/app_selector/app_selector_viewmodel.dart'; +import 'package:revanced_manager/ui/views/contributors/contributors_view.dart'; import 'package:revanced_manager/ui/views/home/home_view.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_view.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; @@ -17,7 +18,8 @@ import 'package:stacked_themes/stacked_themes.dart'; MaterialRoute(page: AppSelectorView), MaterialRoute(page: PatcherView), MaterialRoute(page: PatchesSelectorView), - MaterialRoute(page: SettingsView) + MaterialRoute(page: SettingsView), + MaterialRoute(page: ContributorsView) ], dependencies: [ LazySingleton(classType: NavigationService), diff --git a/lib/app/app.router.dart b/lib/app/app.router.dart index 0e19c876..58a90262 100644 --- a/lib/app/app.router.dart +++ b/lib/app/app.router.dart @@ -7,9 +7,10 @@ // 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 _i7; +import 'package:stacked_services/stacked_services.dart' as _i8; import '../ui/views/app_selector/app_selector_view.dart' as _i3; +import '../ui/views/contributors/contributors_view.dart' as _i7; import '../ui/views/home/home_view.dart' as _i2; import '../ui/views/patcher/patcher_view.dart' as _i4; import '../ui/views/patches_selector/patches_selector_view.dart' as _i5; @@ -26,12 +27,15 @@ class Routes { static const settingsView = '/settings-view'; + static const contributorsView = '/contributors-view'; + static const all = { homeView, appSelectorView, patcherView, patchesSelectorView, - settingsView + settingsView, + contributorsView }; } @@ -41,7 +45,8 @@ class StackedRouter extends _i1.RouterBase { _i1.RouteDef(Routes.appSelectorView, page: _i3.AppSelectorView), _i1.RouteDef(Routes.patcherView, page: _i4.PatcherView), _i1.RouteDef(Routes.patchesSelectorView, page: _i5.PatchesSelectorView), - _i1.RouteDef(Routes.settingsView, page: _i6.SettingsView) + _i1.RouteDef(Routes.settingsView, page: _i6.SettingsView), + _i1.RouteDef(Routes.contributorsView, page: _i7.ContributorsView) ]; final _pagesMap = { @@ -74,6 +79,12 @@ class StackedRouter extends _i1.RouterBase { builder: (context) => const _i6.SettingsView(), settings: data, ); + }, + _i7.ContributorsView: (data) { + return MaterialPageRoute( + builder: (context) => const _i7.ContributorsView(), + settings: data, + ); } }; @@ -83,7 +94,7 @@ class StackedRouter extends _i1.RouterBase { Map get pagesMap => _pagesMap; } -extension NavigatorStateExtension on _i7.NavigationService { +extension NavigatorStateExtension on _i8.NavigationService { Future navigateToHomeView( [int? routerId, bool preventDuplicates = true, @@ -153,4 +164,18 @@ extension NavigatorStateExtension on _i7.NavigationService { parameters: parameters, transition: transition); } + + Future navigateToContributorsView( + [int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function( + BuildContext, Animation, Animation, Widget)? + transition]) async { + navigateTo(Routes.contributorsView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } } diff --git a/lib/constants.dart b/lib/constants.dart index 94e165fa..6170cd1a 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -14,3 +14,6 @@ final robotoTextStyle = GoogleFonts.roboto(); const ghOrg = 'revanced'; const patchesRepo = 'revanced-patches'; const integrationsRepo = 'revanced-integrations'; +const patcherRepo = 'revanced-patcher'; +const cliRepo = 'revanced-cli'; +const managerRepo = 'revanced-manager'; diff --git a/lib/main.dart b/lib/main.dart index a0b08a43..c8be5e38 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,7 +15,6 @@ import 'package:stacked_services/stacked_services.dart'; import 'package:stacked_themes/stacked_themes.dart'; Future main() async { - setupLocator(); await ThemeManager.initialise(); setupLocator(); WidgetsFlutterBinding.ensureInitialized(); diff --git a/lib/services/github_api.dart b/lib/services/github_api.dart index a9634d17..df4c34f4 100644 --- a/lib/services/github_api.dart +++ b/lib/services/github_api.dart @@ -37,4 +37,16 @@ class GithubAPI { } return pushedAt; } + + Future> getContributors(String org, repoName) async { + try { + var contributors = await github.repositories.listContributors( + RepositorySlug(org, repoName), + ); + return contributors.toList(); + } on Exception { + print(Exception); + return []; + } + } } diff --git a/lib/theme.dart b/lib/theme.dart index e55916d7..75eda588 100644 --- a/lib/theme.dart +++ b/lib/theme.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:revanced_manager/constants.dart'; import 'package:stacked_themes/stacked_themes.dart'; import 'app/app.locator.dart'; diff --git a/lib/ui/views/contributors/contributors_view.dart b/lib/ui/views/contributors/contributors_view.dart new file mode 100644 index 00000000..0c8b380f --- /dev/null +++ b/lib/ui/views/contributors/contributors_view.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:revanced_manager/ui/views/contributors/contributors_viewmodel.dart'; +import 'package:revanced_manager/ui/widgets/contributors_card.dart'; +import 'package:stacked/stacked.dart'; + +class ContributorsView extends StatelessWidget { + const ContributorsView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ViewModelBuilder.reactive( + disposeViewModel: false, + viewModelBuilder: () => ContributorsViewModel(), + onModelReady: (model) => model.getContributors(), + builder: (context, model, child) => Scaffold( + floatingActionButton: FloatingActionButton( + onPressed: () => model.getContributors(), + child: const Icon(Icons.refresh), + ), + body: SafeArea( + child: SingleChildScrollView( + child: Column( + children: [ + ContributorsCard( + title: "Patcher Contributors", + contributors: model.patcherContributors, + height: 60, + ), + ContributorsCard( + title: "Patches Contributors", + contributors: model.patchesContributors, + height: 230, + ), + ContributorsCard( + title: "Integrations Contributors", + contributors: model.integrationsContributors, + height: 230, + ), + ContributorsCard( + title: "CLI Contributors", + contributors: model.cliContributors, + height: 180, + ), + ContributorsCard( + title: "Manager Contributors", + contributors: model.managerContributors, + height: 130, + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/ui/views/contributors/contributors_viewmodel.dart b/lib/ui/views/contributors/contributors_viewmodel.dart new file mode 100644 index 00000000..3dbdbb80 --- /dev/null +++ b/lib/ui/views/contributors/contributors_viewmodel.dart @@ -0,0 +1,27 @@ +import 'package:github/github.dart'; +import 'package:revanced_manager/services/github_api.dart'; +import 'package:stacked/stacked.dart'; + +class ContributorsViewModel extends BaseViewModel { + final GithubAPI githubAPI = GithubAPI(); + List patchesContributors = []; + List integrationsContributors = []; + List patcherContributors = []; + List cliContributors = []; + List managerContributors = []; + + Future> getContributors() async { + patchesContributors = + await githubAPI.getContributors('revanced', 'revanced-patches'); + integrationsContributors = + await githubAPI.getContributors('revanced', 'revanced-integrations'); + patcherContributors = + await githubAPI.getContributors('revanced', 'revanced-patcher'); + cliContributors = + await githubAPI.getContributors('revanced', 'revanced-cli'); + managerContributors = + await githubAPI.getContributors('revanced', 'revanced-manager'); + + return []; + } +} diff --git a/lib/ui/views/settings/settings_view.dart b/lib/ui/views/settings/settings_view.dart index 4734f75e..b2cfac58 100644 --- a/lib/ui/views/settings/settings_view.dart +++ b/lib/ui/views/settings/settings_view.dart @@ -77,6 +77,7 @@ class SettingsView extends StatelessWidget { ), ListTile( title: I18nText('settingsView.contributorsLabel'), + onTap: model.navigateToContributors, ), ], ), diff --git a/lib/ui/views/settings/settings_viewmodel.dart b/lib/ui/views/settings/settings_viewmodel.dart index b0fbe8aa..b86eef88 100644 --- a/lib/ui/views/settings/settings_viewmodel.dart +++ b/lib/ui/views/settings/settings_viewmodel.dart @@ -1,7 +1,16 @@ +import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/app/app.router.dart'; import 'package:stacked/stacked.dart'; +import 'package:stacked_services/stacked_services.dart'; class SettingsViewModel extends BaseViewModel { + final _navigationService = locator(); + void setLanguage(String language) { notifyListeners(); } + + void navigateToContributors() { + _navigationService.navigateTo(Routes.contributorsView); + } } diff --git a/lib/ui/widgets/contributors_card.dart b/lib/ui/widgets/contributors_card.dart new file mode 100644 index 00000000..fe79bc4e --- /dev/null +++ b/lib/ui/widgets/contributors_card.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:github/github.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:revanced_manager/constants.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class ContributorsCard extends StatefulWidget { + final String title; + final List contributors; + final double height; + + const ContributorsCard({ + Key? key, + required this.title, + required this.contributors, + this.height = 200, + }) : super(key: key); + + @override + State createState() => _ContributorsCardState(); +} + +class _ContributorsCardState extends State { + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 4.0), + child: Text( + widget.title, + style: GoogleFonts.poppins( + fontSize: 20, + fontWeight: FontWeight.w600, + ), + ), + ), + Container( + margin: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(4.0), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.tertiary, + borderRadius: BorderRadius.circular(8.0), + ), + height: widget.height, + child: GridView.builder( + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 7, + mainAxisSpacing: 8, + crossAxisSpacing: 8, + ), + itemCount: widget.contributors.length, + itemBuilder: (context, index) { + return ClipRRect( + borderRadius: BorderRadius.circular(100), + child: GestureDetector( + onTap: () => + launchUrl(Uri.parse(widget.contributors[index].htmlUrl!)), + child: Image.network( + widget.contributors[index].avatarUrl!, + height: 40, + width: 40, + ), + ), + ); + }, + ), + ), + ], + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index bb1c1c0d..e147ebb0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -817,6 +817,62 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.4" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.5" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.17" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.17" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.13" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" uuid: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5d2cb09a..67b94ee7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,7 @@ dependencies: stacked_services: ^0.9.3 stacked_themes: ^0.3.9 timeago: ^3.2.2 + url_launcher: ^6.1.5 dev_dependencies: build_runner: any