refactor(router): Use GoRouter instead of Navigator

Please note that Recovery flow is not refactored yet.

Also:
- Merged two "About" pages
- DiskStatus now has a getVolumeByName function
This commit is contained in:
inexcode 2022-11-08 12:18:34 +03:00
parent 6eb49fa8f1
commit f07f2e803c
26 changed files with 299 additions and 354 deletions

View File

@ -119,4 +119,13 @@ class DiskStatus {
bool get isDiskOkay => diskVolumes.every((final volume) => volume.isDiskOkay); bool get isDiskOkay => diskVolumes.every((final volume) => volume.isDiskOkay);
List<DiskVolume> diskVolumes = []; List<DiskVolume> diskVolumes = [];
DiskVolume getVolumeByName(final String name) {
for (final DiskVolume volume in diskVolumes) {
if (volume.name == name) {
return volume;
}
}
throw Exception('Volume $name not found');
}
} }

View File

@ -2,20 +2,17 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:selfprivacy/config/brand_colors.dart';
import 'package:selfprivacy/config/hive_config.dart';
import 'package:selfprivacy/theming/factory/app_theme_factory.dart';
import 'package:selfprivacy/ui/pages/setup/initializing/initializing.dart';
import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart';
import 'package:selfprivacy/ui/pages/root_route.dart';
import 'package:wakelock/wakelock.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:selfprivacy/config/bloc_config.dart'; import 'package:selfprivacy/config/bloc_config.dart';
import 'package:selfprivacy/config/bloc_observer.dart'; import 'package:selfprivacy/config/bloc_observer.dart';
import 'package:selfprivacy/config/brand_colors.dart';
import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/config/get_it_config.dart';
import 'package:selfprivacy/config/hive_config.dart';
import 'package:selfprivacy/config/localization.dart'; import 'package:selfprivacy/config/localization.dart';
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart'; import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
import 'package:selfprivacy/router.dart';
import 'package:selfprivacy/theming/factory/app_theme_factory.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:wakelock/wakelock.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
@ -76,10 +73,10 @@ class MyApp extends StatelessWidget {
final BuildContext context, final BuildContext context,
final AppSettingsState appSettings, final AppSettingsState appSettings,
) => ) =>
MaterialApp( MaterialApp.router(
scaffoldMessengerKey: scaffoldMessengerKey:
getIt.get<NavigationService>().scaffoldMessengerKey, getIt.get<NavigationService>().scaffoldMessengerKey,
navigatorKey: getIt.get<NavigationService>().navigatorKey, // navigatorKey: getIt.get<NavigationService>().navigatorKey,
localizationsDelegates: context.localizationDelegates, localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales, supportedLocales: context.supportedLocales,
locale: context.locale, locale: context.locale,
@ -89,9 +86,8 @@ class MyApp extends StatelessWidget {
darkTheme: darkThemeData, darkTheme: darkThemeData,
themeMode: themeMode:
appSettings.isDarkModeOn ? ThemeMode.dark : ThemeMode.light, appSettings.isDarkModeOn ? ThemeMode.dark : ThemeMode.light,
home: appSettings.isOnboardingShowing routerConfig: router,
? const OnboardingPage(nextPage: InitializingPage()) // home: appSettings.isOnboardingShowing ? const OnboardingPage(nextPage: InitializingPage()) : const RootPage(),
: const RootPage(),
builder: (final BuildContext context, final Widget? widget) { builder: (final BuildContext context, final Widget? widget) {
Widget error = const Text('...rendering error...'); Widget error = const Text('...rendering error...');
if (widget is Scaffold || widget is Navigator) { if (widget is Scaffold || widget is Navigator) {

139
lib/router.dart Normal file
View File

@ -0,0 +1,139 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
import 'package:selfprivacy/logic/models/service.dart';
import 'package:selfprivacy/ui/pages/backup_details/backup_details.dart';
import 'package:selfprivacy/ui/pages/devices/devices.dart';
import 'package:selfprivacy/ui/pages/devices/new_device.dart';
import 'package:selfprivacy/ui/pages/dns_details/dns_details.dart';
import 'package:selfprivacy/ui/pages/more/about_application.dart';
import 'package:selfprivacy/ui/pages/more/app_settings/app_setting.dart';
import 'package:selfprivacy/ui/pages/more/console.dart';
import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart';
import 'package:selfprivacy/ui/pages/recovery_key/recovery_key.dart';
import 'package:selfprivacy/ui/pages/recovery_key/recovery_key_receiving.dart';
import 'package:selfprivacy/ui/pages/root_route.dart';
import 'package:selfprivacy/ui/pages/server_details/server_details_screen.dart';
import 'package:selfprivacy/ui/pages/server_storage/binds_migration/services_migration.dart';
import 'package:selfprivacy/ui/pages/server_storage/extending_volume.dart';
import 'package:selfprivacy/ui/pages/server_storage/server_storage.dart';
import 'package:selfprivacy/ui/pages/services/service_page.dart';
import 'package:selfprivacy/ui/pages/setup/initializing/initializing.dart';
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_routing.dart';
import 'package:selfprivacy/ui/pages/users/users.dart';
final GoRouter router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (final _, final __) => const RootPage(),
),
GoRoute(
path: '/server',
builder: (final _, final __) => const ServerDetailsScreen(),
routes: [
GoRoute(
path: 'storage',
builder: (final _, final __) => const ServerStoragePage(),
routes: [
GoRoute(
path: 'extend/:volumeName',
builder: (final context, final state) => ExtendingVolumePage(
diskVolumeToResize: context
.read<ApiServerVolumeCubit>()
.state
.diskStatus
.getVolumeByName(state.params['volumeName']!),
),
),
],
),
GoRoute(
path: 'settings/timezone',
builder: (final _, final __) => const SelectTimezone(),
),
],
),
GoRoute(
path: '/dns',
builder: (final _, final __) => const DnsDetailsPage(),
),
GoRoute(
path: '/backups',
builder: (final _, final __) => const BackupDetails(),
),
GoRoute(
path: '/services/:serviceId',
builder: (final context, final state) => ServicePage(
serviceId: state.params['serviceId']!,
),
routes: [
GoRoute(
path: 'move',
builder: (final context, final state) => ServicesMigrationPage(
services: state.extra! as List<Service>,
isMigration: false,
),
),
],
),
GoRoute(
path: '/users/:userId',
builder: (final context, final state) =>
UserDetails(login: state.params['userId']!),
),
GoRoute(
path: '/migrations/binds',
builder: (final context, final state) => ServicesMigrationPage(
services: state.extra! as List<Service>,
isMigration: true,
),
),
GoRoute(
path: '/initial-setup',
builder: (final _, final __) => const InitializingPage(),
),
GoRoute(
path: '/recover-access',
builder: (final _, final __) => const RecoveryRouting(),
),
GoRoute(
path: '/recovery-key',
builder: (final _, final __) => const RecoveryKeyPage(),
routes: [
GoRoute(
path: 'new',
builder: (final context, final state) => RecoveryKeyReceiving(
recoveryKey: state.extra! as String,
),
),
],
),
GoRoute(
path: '/devices',
builder: (final _, final __) => const DevicesScreen(),
routes: [
GoRoute(
path: 'new',
builder: (final _, final __) => const NewDeviceScreen(),
),
],
),
GoRoute(
path: '/settings',
builder: (final _, final __) => const AppSettingsPage(),
),
GoRoute(
path: '/about',
builder: (final _, final __) => const AboutPage(),
),
GoRoute(
path: '/onboarding',
builder: (final _, final __) => const OnboardingPage(),
),
GoRoute(
path: '/console',
builder: (final _, final __) => const ConsolePage(),
)
],
);

View File

@ -1,9 +1,8 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/brand_colors.dart';
import 'package:selfprivacy/config/text_themes.dart'; import 'package:selfprivacy/config/text_themes.dart';
import 'package:selfprivacy/ui/pages/setup/initializing/initializing.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
import 'package:easy_localization/easy_localization.dart';
class NotReadyCard extends StatelessWidget { class NotReadyCard extends StatelessWidget {
const NotReadyCard({super.key}); const NotReadyCard({super.key});
@ -26,11 +25,7 @@ class NotReadyCard extends StatelessWidget {
child: Padding( child: Padding(
padding: const EdgeInsets.only(bottom: 0.5), padding: const EdgeInsets.only(bottom: 0.5),
child: GestureDetector( child: GestureDetector(
onTap: () => Navigator.of(context).push( onTap: () => context.go('/initial-setup'),
materialRoute(
const InitializingPage(),
),
),
child: Text( child: Text(
'not_ready_card.insertion'.tr(), 'not_ready_card.insertion'.tr(),
style: body1Style.copyWith( style: body1Style.copyWith(

View File

@ -1,14 +1,13 @@
import 'package:cubit_form/cubit_form.dart'; import 'package:cubit_form/cubit_form.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/logic/common_enum/common_enum.dart'; import 'package:selfprivacy/logic/common_enum/common_enum.dart';
import 'package:selfprivacy/logic/cubit/devices/devices_cubit.dart'; import 'package:selfprivacy/logic/cubit/devices/devices_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/models/json/api_token.dart'; import 'package:selfprivacy/logic/models/json/api_token.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:selfprivacy/ui/components/info_box/info_box.dart'; import 'package:selfprivacy/ui/components/info_box/info_box.dart';
import 'package:selfprivacy/ui/pages/devices/new_device.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
class DevicesScreen extends StatefulWidget { class DevicesScreen extends StatefulWidget {
const DevicesScreen({super.key}); const DevicesScreen({super.key});
@ -45,8 +44,7 @@ class _DevicesScreenState extends State<DevicesScreen> {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
OutlinedButton( OutlinedButton(
onPressed: () => Navigator.of(context) onPressed: () => context.go('/devices/new'),
.push(materialRoute(const NewDeviceScreen())),
child: Text('devices.main_screen.authorize_new_device'.tr()), child: Text('devices.main_screen.authorize_new_device'.tr()),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),

View File

@ -1,13 +1,14 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:package_info/package_info.dart';
import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server.dart'; import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
import 'package:package_info/package_info.dart';
import 'package:easy_localization/easy_localization.dart';
class AboutApplicationPage extends StatelessWidget { class AboutPage extends StatelessWidget {
const AboutApplicationPage({super.key}); const AboutPage({super.key});
@override @override
Widget build(final BuildContext context) => SafeArea( Widget build(final BuildContext context) => SafeArea(
@ -22,7 +23,7 @@ class AboutApplicationPage extends StatelessWidget {
body: ListView( body: ListView(
padding: paddingH15V0, padding: paddingH15V0,
children: [ children: [
const SizedBox(height: 10), const SizedBox(height: 16),
FutureBuilder( FutureBuilder(
future: _packageVersion(), future: _packageVersion(),
builder: (final context, final snapshot) => BrandText.body1( builder: (final context, final snapshot) => BrandText.body1(
@ -37,6 +38,10 @@ class AboutApplicationPage extends StatelessWidget {
.tr(args: [snapshot.data.toString()]), .tr(args: [snapshot.data.toString()]),
), ),
), ),
const SizedBox(height: 16),
const BrandMarkdown(
fileName: 'about',
),
], ],
), ),
), ),

View File

@ -1,30 +0,0 @@
import 'package:flutter/material.dart';
import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
class AboutUsPage extends StatelessWidget {
const AboutUsPage({super.key});
@override
Widget build(final BuildContext context) => SafeArea(
child: Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(52),
child: BrandHeader(
title: 'about_us_page.title'.tr(),
hasBackButton: true,
),
),
body: ListView(
padding: paddingH15V0,
children: const [
BrandMarkdown(
fileName: 'about',
),
],
),
),
);
}

View File

@ -7,14 +7,14 @@ import 'package:selfprivacy/config/get_it_config.dart';
import 'package:selfprivacy/logic/models/message.dart'; import 'package:selfprivacy/logic/models/message.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
class Console extends StatefulWidget { class ConsolePage extends StatefulWidget {
const Console({super.key}); const ConsolePage({super.key});
@override @override
State<Console> createState() => _ConsoleState(); State<ConsolePage> createState() => _ConsolePageState();
} }
class _ConsoleState extends State<Console> { class _ConsolePageState extends State<ConsolePage> {
@override @override
void initState() { void initState() {
getIt.get<ConsoleModel>().addListener(update); getIt.get<ConsoleModel>().addListener(update);

View File

@ -1,5 +1,6 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:ionicons/ionicons.dart'; import 'package:ionicons/ionicons.dart';
import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
@ -8,19 +9,6 @@ import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart'; import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
import 'package:selfprivacy/ui/pages/devices/devices.dart';
import 'package:selfprivacy/ui/pages/recovery_key/recovery_key.dart';
import 'package:selfprivacy/ui/pages/server_storage/binds_migration/services_migration.dart';
import 'package:selfprivacy/ui/pages/setup/initializing/initializing.dart';
import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart';
import 'package:selfprivacy/ui/pages/root_route.dart';
import 'package:selfprivacy/ui/pages/users/users.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
import 'package:selfprivacy/ui/pages/more/about_us.dart';
import 'package:selfprivacy/ui/pages/more/app_settings/app_setting.dart';
import 'package:selfprivacy/ui/pages/more/console.dart';
import 'package:selfprivacy/ui/pages/more/about_application.dart';
class MorePage extends StatelessWidget { class MorePage extends StatelessWidget {
const MorePage({super.key}); const MorePage({super.key});
@ -50,26 +38,20 @@ class MorePage extends StatelessWidget {
_MoreMenuItem( _MoreMenuItem(
title: 'storage.start_migration_button'.tr(), title: 'storage.start_migration_button'.tr(),
iconData: Icons.drive_file_move_outline, iconData: Icons.drive_file_move_outline,
goTo: ServicesMigrationPage( goToPath: '/migrations/binds',
diskStatus: context goToExtra: context
.watch<ApiServerVolumeCubit>() .read<ServicesCubit>()
.state .state
.diskStatus, .services
services: context .where(
.read<ServicesCubit>() (final service) =>
.state service.id == 'bitwarden' ||
.services service.id == 'gitea' ||
.where( service.id == 'pleroma' ||
(final service) => service.id == 'mailserver' ||
service.id == 'bitwarden' || service.id == 'nextcloud',
service.id == 'gitea' || )
service.id == 'pleroma' || .toList(),
service.id == 'mailserver' ||
service.id == 'nextcloud',
)
.toList(),
isMigration: true,
),
subtitle: 'storage.data_migration_notice'.tr(), subtitle: 'storage.data_migration_notice'.tr(),
accent: true, accent: true,
), ),
@ -77,7 +59,7 @@ class MorePage extends StatelessWidget {
_MoreMenuItem( _MoreMenuItem(
title: 'more_page.configuration_wizard'.tr(), title: 'more_page.configuration_wizard'.tr(),
iconData: Icons.change_history_outlined, iconData: Icons.change_history_outlined,
goTo: const InitializingPage(), goToPath: '/initial-setup',
subtitle: 'not_ready_card.in_menu'.tr(), subtitle: 'not_ready_card.in_menu'.tr(),
accent: true, accent: true,
), ),
@ -85,47 +67,40 @@ class MorePage extends StatelessWidget {
_MoreMenuItem( _MoreMenuItem(
title: 'more_page.create_ssh_key'.tr(), title: 'more_page.create_ssh_key'.tr(),
iconData: Ionicons.key_outline, iconData: Ionicons.key_outline,
goTo: const UserDetails( goToPath: '/users/root',
login: 'root',
),
), ),
if (isReady) if (isReady)
_MoreMenuItem( _MoreMenuItem(
iconData: Icons.password_outlined, iconData: Icons.password_outlined,
goTo: const RecoveryKey(), goToPath: '/recovery-key',
title: 'recovery_key.key_main_header'.tr(), title: 'recovery_key.key_main_header'.tr(),
), ),
if (isReady) if (isReady)
_MoreMenuItem( _MoreMenuItem(
iconData: Icons.devices_outlined, iconData: Icons.devices_outlined,
goTo: const DevicesScreen(), goToPath: '/devices',
title: 'devices.main_screen.header'.tr(), title: 'devices.main_screen.header'.tr(),
), ),
_MoreMenuItem( _MoreMenuItem(
title: 'more_page.application_settings'.tr(), title: 'more_page.application_settings'.tr(),
iconData: Icons.settings_outlined, iconData: Icons.settings_outlined,
goTo: const AppSettingsPage(), goToPath: '/settings',
),
_MoreMenuItem(
title: 'more_page.about_project'.tr(),
iconData: BrandIcons.engineer,
goTo: const AboutUsPage(),
), ),
_MoreMenuItem( _MoreMenuItem(
title: 'more_page.about_application'.tr(), title: 'more_page.about_application'.tr(),
iconData: BrandIcons.fire, iconData: BrandIcons.engineer,
goTo: const AboutApplicationPage(), goToPath: '/about',
), ),
if (!isReady) if (!isReady)
_MoreMenuItem( _MoreMenuItem(
title: 'more_page.onboarding'.tr(), title: 'more_page.onboarding'.tr(),
iconData: BrandIcons.start, iconData: BrandIcons.start,
goTo: const OnboardingPage(nextPage: RootPage()), goToPath: '/onboarding',
), ),
_MoreMenuItem( _MoreMenuItem(
title: 'more_page.console'.tr(), title: 'more_page.console'.tr(),
iconData: BrandIcons.terminal, iconData: BrandIcons.terminal,
goTo: const Console(), goToPath: '/console',
), ),
], ],
), ),
@ -141,13 +116,15 @@ class _MoreMenuItem extends StatelessWidget {
required this.iconData, required this.iconData,
required this.title, required this.title,
this.subtitle, this.subtitle,
this.goTo, this.goToPath,
this.goToExtra,
this.accent = false, this.accent = false,
}); });
final IconData iconData; final IconData iconData;
final String title; final String title;
final Widget? goTo; final String? goToPath;
final Object? goToExtra;
final String? subtitle; final String? subtitle;
final bool accent; final bool accent;
@ -160,8 +137,9 @@ class _MoreMenuItem extends StatelessWidget {
tertiary: accent, tertiary: accent,
child: ListTile( child: ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
onTap: goTo != null // onTap: goTo != null ? () => Navigator.of(context).push(materialRoute(goTo!)) : null,
? () => Navigator.of(context).push(materialRoute(goTo!)) onTap: goToPath != null
? () => context.go(goToPath!, extra: goToExtra)
: null, : null,
leading: Icon( leading: Icon(
iconData, iconData,

View File

@ -1,14 +1,12 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart'; import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
import 'package:easy_localization/easy_localization.dart';
class OnboardingPage extends StatefulWidget { class OnboardingPage extends StatefulWidget {
const OnboardingPage({required this.nextPage, super.key}); const OnboardingPage({super.key});
final Widget nextPage;
@override @override
State<OnboardingPage> createState() => _OnboardingPageState(); State<OnboardingPage> createState() => _OnboardingPageState();
} }
@ -117,10 +115,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
BrandButton.rised( BrandButton.rised(
onPressed: () { onPressed: () {
context.read<AppSettingsCubit>().turnOffOnboarding(); context.read<AppSettingsCubit>().turnOffOnboarding();
Navigator.of(context).pushAndRemoveUntil( context.go('/initial-setup');
materialRoute(widget.nextPage),
(final route) => false,
);
}, },
text: 'basis.got_it'.tr(), text: 'basis.got_it'.tr(),
), ),

View File

@ -1,5 +1,6 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart'; import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
import 'package:selfprivacy/logic/cubit/dns_records/dns_records_cubit.dart'; import 'package:selfprivacy/logic/cubit/dns_records/dns_records_cubit.dart';
@ -10,10 +11,6 @@ import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart'; import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart';
import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart'; import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart';
import 'package:selfprivacy/ui/pages/backup_details/backup_details.dart';
import 'package:selfprivacy/ui/pages/dns_details/dns_details.dart';
import 'package:selfprivacy/ui/pages/server_details/server_details_screen.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@ -81,8 +78,7 @@ class _ProvidersPageState extends State<ProvidersPage> {
subtitle: diskStatus.isDiskOkay subtitle: diskStatus.isDiskOkay
? 'storage.status_ok'.tr() ? 'storage.status_ok'.tr()
: 'storage.status_error'.tr(), : 'storage.status_error'.tr(),
onTap: () => Navigator.of(context) onTap: () => context.go('/server'),
.push(materialRoute(const ServerDetailsScreen())),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
_Card( _Card(
@ -92,11 +88,7 @@ class _ProvidersPageState extends State<ProvidersPage> {
subtitle: appConfig.isDomainSelected subtitle: appConfig.isDomainSelected
? appConfig.serverDomain!.domainName ? appConfig.serverDomain!.domainName
: '', : '',
onTap: () => Navigator.of(context).push( onTap: () => context.go('/dns'),
materialRoute(
const DnsDetailsPage(),
),
),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
// TODO: When backups are fixed, show this card // TODO: When backups are fixed, show this card
@ -108,8 +100,7 @@ class _ProvidersPageState extends State<ProvidersPage> {
icon: BrandIcons.save, icon: BrandIcons.save,
title: 'backup.card_title'.tr(), title: 'backup.card_title'.tr(),
subtitle: isBackupInitialized ? 'backup.card_subtitle'.tr() : '', subtitle: isBackupInitialized ? 'backup.card_subtitle'.tr() : '',
onTap: () => Navigator.of(context) onTap: () => context.go('/backups'),
.push(materialRoute(const BackupDetails())),
), ),
], ],
), ),

View File

@ -2,6 +2,7 @@ import 'package:cubit_form/cubit_form.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/config/get_it_config.dart';
import 'package:selfprivacy/logic/common_enum/common_enum.dart'; import 'package:selfprivacy/logic/common_enum/common_enum.dart';
import 'package:selfprivacy/logic/cubit/recovery_key/recovery_key_cubit.dart'; import 'package:selfprivacy/logic/cubit/recovery_key/recovery_key_cubit.dart';
@ -10,17 +11,15 @@ import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart'; import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart'; import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:selfprivacy/ui/pages/recovery_key/recovery_key_receiving.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
class RecoveryKey extends StatefulWidget { class RecoveryKeyPage extends StatefulWidget {
const RecoveryKey({super.key}); const RecoveryKeyPage({super.key});
@override @override
State<RecoveryKey> createState() => _RecoveryKeyState(); State<RecoveryKeyPage> createState() => _RecoveryKeyPageState();
} }
class _RecoveryKeyState extends State<RecoveryKey> { class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
@override @override
Widget build(final BuildContext context) { Widget build(final BuildContext context) {
final RecoveryKeyState keyStatus = context.watch<RecoveryKeyCubit>().state; final RecoveryKeyState keyStatus = context.watch<RecoveryKeyCubit>().state;
@ -240,11 +239,7 @@ class _RecoveryKeyConfigurationState extends State<RecoveryKeyConfiguration> {
setState(() { setState(() {
_isLoading = false; _isLoading = false;
}); });
Navigator.of(context).push( context.go('/recovery-key/new', extra: token);
materialRoute(
RecoveryKeyReceiving(recoveryKey: token), // TO DO
),
);
} on GenerationError catch (e) { } on GenerationError catch (e) {
setState(() { setState(() {
_isLoading = false; _isLoading = false;

View File

@ -1,6 +1,7 @@
import 'package:cubit_form/cubit_form.dart'; import 'package:cubit_form/cubit_form.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/brand_colors.dart';
import 'package:selfprivacy/logic/common_enum/common_enum.dart'; import 'package:selfprivacy/logic/common_enum/common_enum.dart';
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart'; import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
@ -23,7 +24,6 @@ import 'package:selfprivacy/ui/pages/server_storage/storage_card.dart';
import 'package:selfprivacy/utils/extensions/duration.dart'; import 'package:selfprivacy/utils/extensions/duration.dart';
import 'package:selfprivacy/utils/extensions/string_extensions.dart'; import 'package:selfprivacy/utils/extensions/string_extensions.dart';
import 'package:selfprivacy/utils/named_font_weight.dart'; import 'package:selfprivacy/utils/named_font_weight.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
import 'package:timezone/timezone.dart'; import 'package:timezone/timezone.dart';
part 'charts/chart.dart'; part 'charts/chart.dart';

View File

@ -85,11 +85,7 @@ class _ServerSettingsState extends State<_ServerSettings> {
context.read<JobsCubit>().addJob( context.read<JobsCubit>().addJob(
RebuildServerJob(title: 'jobs.upgrade_server'.tr()), RebuildServerJob(title: 'jobs.upgrade_server'.tr()),
); );
Navigator.of(context).push( context.go('/server/settings/timezone');
materialRoute(
const SelectTimezone(),
),
);
}, },
), ),
], ],

View File

@ -1,79 +0,0 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
import 'package:selfprivacy/logic/models/json/server_job.dart';
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:selfprivacy/ui/components/brand_linear_indicator/brand_linear_indicator.dart';
import 'package:selfprivacy/ui/pages/root_route.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
class MigrationProcessPage extends StatefulWidget {
const MigrationProcessPage({super.key});
@override
State<MigrationProcessPage> createState() => _MigrationProcessPageState();
}
class _MigrationProcessPageState extends State<MigrationProcessPage> {
@override
void initState() {
super.initState();
}
@override
Widget build(final BuildContext context) {
ServerJob? job;
String? subtitle = '';
double value = 0.0;
List<Widget> children = [];
final serverJobsState = context.watch<ServerJobsCubit>().state;
if (serverJobsState.migrationJobUid != null) {
job = context.read<ServerJobsCubit>().getServerJobByUid(
serverJobsState.migrationJobUid!,
);
}
if (job == null) {
subtitle = 'basis.loading'.tr();
} else {
value = job.progress == null ? 0.0 : job.progress! / 100;
subtitle = job.statusText;
children = [
...children,
const SizedBox(height: 16),
if (job.finishedAt != null)
Text(
job.result!,
style: Theme.of(context).textTheme.titleMedium,
),
if (job.finishedAt != null) const SizedBox(height: 16),
if (job.finishedAt != null)
FilledButton(
title: 'storage.migration_done'.tr(),
onPressed: () {
Navigator.of(context).pushAndRemoveUntil(
materialRoute(const RootPage()),
(final predicate) => false,
);
},
),
];
}
return BrandHeroScreen(
hasBackButton: false,
heroTitle: 'storage.migration_process'.tr(),
heroSubtitle: subtitle,
children: [
BrandLinearIndicator(
value: value,
color: Theme.of(context).colorScheme.primary,
backgroundColor: Theme.of(context).colorScheme.surfaceVariant,
height: 4.0,
),
...children,
],
);
}
}

View File

@ -1,30 +1,28 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart'; import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
import 'package:selfprivacy/logic/models/disk_size.dart'; import 'package:selfprivacy/logic/models/disk_size.dart';
import 'package:selfprivacy/logic/models/disk_status.dart';
import 'package:selfprivacy/logic/models/service.dart'; import 'package:selfprivacy/logic/models/service.dart';
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart'; import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:selfprivacy/ui/components/info_box/info_box.dart'; import 'package:selfprivacy/ui/components/info_box/info_box.dart';
import 'package:selfprivacy/logic/models/disk_status.dart';
import 'package:selfprivacy/ui/components/jobs_content/jobs_content.dart'; import 'package:selfprivacy/ui/components/jobs_content/jobs_content.dart';
import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart'; import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart';
import 'package:selfprivacy/ui/components/storage_list_items/service_migration_list_item.dart'; import 'package:selfprivacy/ui/components/storage_list_items/service_migration_list_item.dart';
import 'package:selfprivacy/ui/helpers/modals.dart'; import 'package:selfprivacy/ui/helpers/modals.dart';
import 'package:selfprivacy/ui/pages/root_route.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
class ServicesMigrationPage extends StatefulWidget { class ServicesMigrationPage extends StatefulWidget {
const ServicesMigrationPage({ const ServicesMigrationPage({
required this.services, required this.services,
required this.diskStatus,
required this.isMigration, required this.isMigration,
super.key, super.key,
}); });
final DiskStatus diskStatus;
final List<Service> services; final List<Service> services;
final bool isMigration; final bool isMigration;
@ -87,11 +85,13 @@ class _ServicesMigrationPageState extends State<ServicesMigrationPage> {
@override @override
Widget build(final BuildContext context) { Widget build(final BuildContext context) {
final DiskStatus diskStatus =
context.watch<ApiServerVolumeCubit>().state.diskStatus;
final Size appBarHeight = Size.fromHeight( final Size appBarHeight = Size.fromHeight(
headerHeight + headerHeight +
headerVerticalPadding * 2 + headerVerticalPadding * 2 +
listItemHeight * widget.diskStatus.diskVolumes.length + listItemHeight * diskStatus.diskVolumes.length +
headerVerticalPadding * widget.diskStatus.diskVolumes.length, headerVerticalPadding * diskStatus.diskVolumes.length,
); );
return SafeArea( return SafeArea(
child: Scaffold( child: Scaffold(
@ -110,7 +110,7 @@ class _ServicesMigrationPageState extends State<ServicesMigrationPage> {
), ),
child: Column( child: Column(
children: [ children: [
...widget.diskStatus.diskVolumes ...diskStatus.diskVolumes
.map( .map(
(final volume) => Column( (final volume) => Column(
children: [ children: [
@ -145,7 +145,7 @@ class _ServicesMigrationPageState extends State<ServicesMigrationPage> {
const SizedBox(height: 8), const SizedBox(height: 8),
ServiceMigrationListItem( ServiceMigrationListItem(
service: service, service: service,
diskStatus: widget.diskStatus, diskStatus: diskStatus,
selectedVolume: serviceToDisk[service.id]!, selectedVolume: serviceToDisk[service.id]!,
onChange: onChange, onChange: onChange,
), ),
@ -180,10 +180,7 @@ class _ServicesMigrationPageState extends State<ServicesMigrationPage> {
} }
} }
} }
Navigator.of(context).pushAndRemoveUntil( context.go('/');
materialRoute(const RootPage()),
(final predicate) => false,
);
showBrandBottomSheet( showBrandBottomSheet(
context: context, context: context,
builder: (final BuildContext context) => builder: (final BuildContext context) =>

View File

@ -1,25 +1,23 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart'; import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
import 'package:selfprivacy/logic/models/disk_size.dart'; import 'package:selfprivacy/logic/models/disk_size.dart';
import 'package:selfprivacy/logic/models/disk_status.dart';
import 'package:selfprivacy/logic/models/price.dart'; import 'package:selfprivacy/logic/models/price.dart';
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart'; import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:selfprivacy/logic/models/disk_status.dart'; import 'package:selfprivacy/ui/components/info_box/info_box.dart';
import 'package:selfprivacy/ui/pages/root_route.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
class ExtendingVolumePage extends StatefulWidget { class ExtendingVolumePage extends StatefulWidget {
const ExtendingVolumePage({ const ExtendingVolumePage({
required this.diskVolumeToResize, required this.diskVolumeToResize,
required this.diskStatus,
super.key, super.key,
}); });
final DiskVolume diskVolumeToResize; final DiskVolume diskVolumeToResize;
final DiskStatus diskStatus;
@override @override
State<ExtendingVolumePage> createState() => _ExtendingVolumePageState(); State<ExtendingVolumePage> createState() => _ExtendingVolumePageState();
@ -156,10 +154,7 @@ class _ExtendingVolumePageState extends State<ExtendingVolumePage> {
DiskSize.fromGibibyte(_currentSliderGbValue), DiskSize.fromGibibyte(_currentSliderGbValue),
context.read<ApiServerVolumeCubit>().reload, context.read<ApiServerVolumeCubit>().reload,
); );
Navigator.of(context).pushAndRemoveUntil( context.go('/');
materialRoute(const RootPage()),
(final predicate) => false,
);
}, },
disabled: _isError || isAlreadyResizing, disabled: _isError || isAlreadyResizing,
), ),
@ -168,16 +163,10 @@ class _ExtendingVolumePageState extends State<ExtendingVolumePage> {
height: 1.0, height: 1.0,
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
const Align( InfoBox(
alignment: Alignment.centerLeft, text: 'storage.extending_volume_price_info'.tr(),
child: Icon(
Icons.info_outlined,
size: 24,
),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text('storage.extending_volume_price_info'.tr()),
const SizedBox(height: 16),
], ],
); );
}, },

View File

@ -1,24 +1,21 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart'; import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
import 'package:selfprivacy/logic/models/disk_status.dart';
import 'package:selfprivacy/logic/models/service.dart'; import 'package:selfprivacy/logic/models/service.dart';
import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart'; import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:selfprivacy/logic/models/disk_status.dart';
import 'package:selfprivacy/ui/pages/server_storage/extending_volume.dart';
import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart'; import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
class ServerStoragePage extends StatefulWidget { class ServerStoragePage extends StatefulWidget {
const ServerStoragePage({ const ServerStoragePage({
required this.diskStatus,
super.key, super.key,
}); });
final DiskStatus diskStatus;
@override @override
State<ServerStoragePage> createState() => _ServerStoragePageState(); State<ServerStoragePage> createState() => _ServerStoragePageState();
} }
@ -32,6 +29,9 @@ class _ServerStoragePageState extends State<ServerStoragePage> {
final List<Service> services = final List<Service> services =
context.watch<ServicesCubit>().state.services; context.watch<ServicesCubit>().state.services;
final DiskStatus diskStatus =
context.watch<ApiServerVolumeCubit>().state.diskStatus;
if (!isReady) { if (!isReady) {
return BrandHeroScreen( return BrandHeroScreen(
hasBackButton: true, hasBackButton: true,
@ -45,14 +45,14 @@ class _ServerStoragePageState extends State<ServerStoragePage> {
heroTitle: 'storage.card_title'.tr(), heroTitle: 'storage.card_title'.tr(),
children: [ children: [
// ...sections, // ...sections,
...widget.diskStatus.diskVolumes ...diskStatus.diskVolumes
.map( .map(
(final volume) => Column( (final volume) => Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
ServerStorageSection( ServerStorageSection(
volume: volume, volume: volume,
diskStatus: widget.diskStatus, diskStatus: diskStatus,
services: services services: services
.where( .where(
(final service) => (final service) =>
@ -105,14 +105,8 @@ class ServerStorageSection extends StatelessWidget {
const SizedBox(height: 16), const SizedBox(height: 16),
BrandOutlinedButton( BrandOutlinedButton(
title: 'storage.extend_volume_button.title'.tr(), title: 'storage.extend_volume_button.title'.tr(),
onPressed: () => Navigator.of(context).push( onPressed: () =>
materialRoute( context.go('/server/storage/extend/${volume.name}'),
ExtendingVolumePage(
diskVolumeToResize: volume,
diskStatus: diskStatus,
),
),
),
), ),
], ],
], ],

View File

@ -1,12 +1,11 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart'; import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart';
import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart';
import 'package:selfprivacy/logic/models/disk_status.dart'; import 'package:selfprivacy/logic/models/disk_status.dart';
import 'package:selfprivacy/ui/pages/server_storage/server_storage.dart'; import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart';
import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart'; import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
class StorageCard extends StatelessWidget { class StorageCard extends StatelessWidget {
const StorageCard({ const StorageCard({
@ -45,13 +44,7 @@ class StorageCard extends StatelessWidget {
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
child: InkResponse( child: InkResponse(
highlightShape: BoxShape.rectangle, highlightShape: BoxShape.rectangle,
onTap: () => Navigator.of(context).push( onTap: () => context.go('/server/storage'),
materialRoute(
ServerStoragePage(
diskStatus: diskStatus,
),
),
),
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Column( child: Column(

View File

@ -1,6 +1,7 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart'; import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart'; import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
@ -8,8 +9,6 @@ import 'package:selfprivacy/logic/models/job.dart';
import 'package:selfprivacy/logic/models/service.dart'; import 'package:selfprivacy/logic/models/service.dart';
import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart'; import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:selfprivacy/ui/pages/server_storage/binds_migration/services_migration.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
class ServicePage extends StatefulWidget { class ServicePage extends StatefulWidget {
@ -108,15 +107,9 @@ class _ServicePageState extends State<ServicePage> {
ListTile( ListTile(
iconColor: Theme.of(context).colorScheme.onBackground, iconColor: Theme.of(context).colorScheme.onBackground,
// Open page ServicesMigrationPage // Open page ServicesMigrationPage
onTap: () => Navigator.of(context).push( onTap: () => context.go(
materialRoute( '/services/${service.id}/migration',
ServicesMigrationPage( extra: [service],
services: [service],
diskStatus:
context.read<ApiServerVolumeCubit>().state.diskStatus,
isMigration: false,
),
),
), ),
leading: const Icon(Icons.drive_file_move_outlined), leading: const Icon(Icons.drive_file_move_outlined),
title: Text( title: Text(

View File

@ -1,10 +1,12 @@
import 'dart:ui'; import 'dart:ui';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart'; import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart'; import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
import 'package:selfprivacy/logic/models/job.dart'; import 'package:selfprivacy/logic/models/job.dart';
import 'package:selfprivacy/logic/models/service.dart'; import 'package:selfprivacy/logic/models/service.dart';
@ -15,9 +17,6 @@ import 'package:selfprivacy/ui/components/brand_switch/brand_switch.dart';
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart'; import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart';
import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart'; import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:selfprivacy/ui/pages/services/service_page.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
import 'package:selfprivacy/utils/ui_helpers.dart'; import 'package:selfprivacy/utils/ui_helpers.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@ -119,10 +118,7 @@ class _Card extends StatelessWidget {
final domainName = UiHelpers.getDomainName(config); final domainName = UiHelpers.getDomainName(config);
return GestureDetector( return GestureDetector(
onTap: isReady onTap: isReady ? () => context.go('/services/${service.id}') : null,
? () => Navigator.of(context)
.push(materialRoute(ServicePage(serviceId: service.id)))
: null,
child: BrandCards.big( child: BrandCards.big(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,

View File

@ -1,14 +1,15 @@
import 'package:cubit_form/cubit_form.dart'; import 'package:cubit_form/cubit_form.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart'; import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/backblaze_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/backblaze_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/dns_provider_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/dns_provider_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/domain_setup_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/domain_setup_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/root_user_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/root_user_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
@ -16,11 +17,9 @@ import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
import 'package:selfprivacy/ui/components/brand_timer/brand_timer.dart'; import 'package:selfprivacy/ui/components/brand_timer/brand_timer.dart';
import 'package:selfprivacy/ui/components/progress_bar/progress_bar.dart'; import 'package:selfprivacy/ui/components/progress_bar/progress_bar.dart';
import 'package:selfprivacy/ui/pages/root_route.dart';
import 'package:selfprivacy/ui/pages/setup/initializing/server_provider_picker.dart'; import 'package:selfprivacy/ui/pages/setup/initializing/server_provider_picker.dart';
import 'package:selfprivacy/ui/pages/setup/initializing/server_type_picker.dart'; import 'package:selfprivacy/ui/pages/setup/initializing/server_type_picker.dart';
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_routing.dart'; import 'package:selfprivacy/ui/pages/setup/recovering/recovery_routing.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart';
class InitializingPage extends StatelessWidget { class InitializingPage extends StatelessWidget {
const InitializingPage({super.key}); const InitializingPage({super.key});
@ -52,8 +51,7 @@ class InitializingPage extends StatelessWidget {
return BlocListener<ServerInstallationCubit, ServerInstallationState>( return BlocListener<ServerInstallationCubit, ServerInstallationState>(
listener: (final context, final state) { listener: (final context, final state) {
if (cubit.state is ServerInstallationFinished) { if (cubit.state is ServerInstallationFinished) {
Navigator.of(context) context.go('/');
.pushReplacement(materialRoute(const RootPage()));
} }
}, },
child: SafeArea( child: SafeArea(
@ -105,10 +103,7 @@ class InitializingPage extends StatelessWidget {
? 'basis.close'.tr() ? 'basis.close'.tr()
: 'basis.later'.tr(), : 'basis.later'.tr(),
onPressed: () { onPressed: () {
Navigator.of(context).pushAndRemoveUntil( context.go('/');
materialRoute(const RootPage()),
(final predicate) => false,
);
}, },
), ),
), ),
@ -120,11 +115,7 @@ class InitializingPage extends StatelessWidget {
child: BrandButton.text( child: BrandButton.text(
title: 'basis.connect_to_existing'.tr(), title: 'basis.connect_to_existing'.tr(),
onPressed: () { onPressed: () {
Navigator.of(context).push( context.go('/recover-access');
materialRoute(
const RecoveryRouting(),
),
);
}, },
), ),
) )

View File

@ -11,9 +11,7 @@ class _User extends StatelessWidget {
@override @override
Widget build(final BuildContext context) => InkWell( Widget build(final BuildContext context) => InkWell(
onTap: () { onTap: () {
Navigator.of(context).push( context.go('/users/${user.login}');
materialRoute(UserDetails(login: user.login)),
);
}, },
child: Container( child: Container(
padding: paddingH15V0, padding: paddingH15V0,

View File

@ -1,16 +1,17 @@
import 'package:cubit_form/cubit_form.dart'; import 'package:cubit_form/cubit_form.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/brand_colors.dart';
import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/logic/cubit/forms/user/ssh_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
import 'package:selfprivacy/logic/cubit/forms/user/user_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart'; import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
import 'package:selfprivacy/logic/cubit/forms/user/ssh_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/user/user_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart'; import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
import 'package:selfprivacy/logic/models/job.dart';
import 'package:selfprivacy/logic/models/hive/user.dart'; import 'package:selfprivacy/logic/models/hive/user.dart';
import 'package:selfprivacy/logic/models/job.dart';
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart'; import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart';
@ -24,14 +25,12 @@ import 'package:selfprivacy/ui/components/list_tiles/list_tile_on_surface_varian
import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart'; import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart';
import 'package:selfprivacy/utils/ui_helpers.dart'; import 'package:selfprivacy/utils/ui_helpers.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart'; part 'add_user_fab.dart';
part 'empty.dart'; part 'empty.dart';
part 'new_user.dart'; part 'new_user.dart';
part 'reset_password.dart';
part 'user.dart'; part 'user.dart';
part 'user_details.dart'; part 'user_details.dart';
part 'add_user_fab.dart';
part 'reset_password.dart';
class UsersPage extends StatelessWidget { class UsersPage extends StatelessWidget {
const UsersPage({super.key}); const UsersPage({super.key});
@ -50,7 +49,6 @@ class UsersPage extends StatelessWidget {
final List<User> users = state.users final List<User> users = state.users
.where((final user) => user.type != UserType.root) .where((final user) => user.type != UserType.root)
.toList(); .toList();
// final List<User> users = [];
users.sort( users.sort(
(final User a, final User b) => (final User a, final User b) =>
a.login.toLowerCase().compareTo(b.login.toLowerCase()), a.login.toLowerCase().compareTo(b.login.toLowerCase()),

View File

@ -35,7 +35,7 @@ packages:
name: async name: async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.8.2" version: "2.9.0"
auto_size_text: auto_size_text:
dependency: "direct main" dependency: "direct main"
description: description:
@ -126,7 +126,7 @@ packages:
name: characters name: characters
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.1"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
@ -147,7 +147,7 @@ packages:
name: clock name: clock
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.1"
code_builder: code_builder:
dependency: transitive dependency: transitive
description: description:
@ -350,7 +350,7 @@ packages:
name: fake_async name: fake_async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.3.1"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
@ -511,6 +511,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.2" version: "2.0.2"
go_router:
dependency: "direct main"
description:
name: go_router
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.5"
gql: gql:
dependency: "direct main" dependency: "direct main"
description: description:
@ -762,21 +769,21 @@ packages:
name: matcher name: matcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.12.11" version: "0.12.12"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.4" version: "0.1.5"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.7.0" version: "1.8.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@ -846,7 +853,7 @@ packages:
name: path name: path
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.1" version: "1.8.2"
path_drawing: path_drawing:
dependency: transitive dependency: transitive
description: description:
@ -1159,7 +1166,7 @@ packages:
name: source_span name: source_span
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.2" version: "1.9.0"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -1187,7 +1194,7 @@ packages:
name: string_scanner name: string_scanner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.1"
system_theme: system_theme:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1208,28 +1215,28 @@ packages:
name: term_glyph name: term_glyph
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.1"
test: test:
dependency: transitive dependency: transitive
description: description:
name: test name: test
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.21.1" version: "1.21.4"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.9" version: "0.4.12"
test_core: test_core:
dependency: transitive dependency: transitive
description: description:
name: test_core name: test_core
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.13" version: "0.4.16"
timezone: timezone:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1414,4 +1421,4 @@ packages:
version: "3.1.1" version: "3.1.1"
sdks: sdks:
dart: ">=2.17.0 <3.0.0" dart: ">=2.17.0 <3.0.0"
flutter: ">=3.0.0" flutter: ">=3.3.0"

View File

@ -26,6 +26,7 @@ dependencies:
flutter_secure_storage: ^5.0.2 flutter_secure_storage: ^5.0.2
flutter_svg: ^1.1.4 flutter_svg: ^1.1.4
get_it: ^7.2.0 get_it: ^7.2.0
go_router: ^5.1.5
gql: ^0.13.1 gql: ^0.13.1
graphql: ^5.1.1 graphql: ^5.1.1
graphql_codegen: ^0.10.2 graphql_codegen: ^0.10.2