feat: Migrate to go_router

This commit is contained in:
Anton Stubenbord
2023-07-30 23:51:00 +02:00
parent 61336d9527
commit f1398e6d4c
78 changed files with 2206 additions and 1756 deletions

View File

@@ -1,51 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/features/document_details/cubit/document_details_cubit.dart';
import 'package:paperless_mobile/features/document_details/view/pages/document_details_page.dart';
class DocumentDetailsRoute extends StatelessWidget {
final DocumentModel document;
final bool isLabelClickable;
final String? titleAndContentQueryString;
const DocumentDetailsRoute({
super.key,
required this.document,
this.isLabelClickable = true,
this.titleAndContentQueryString,
});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => DocumentDetailsCubit(
context.read(),
context.read(),
context.read(),
context.read(),
initialDocument: document,
),
lazy: false,
child: DocumentDetailsPage(
isLabelClickable: isLabelClickable,
titleAndContentQueryString: titleAndContentQueryString,
),
);
}
}
class DocumentDetailsRouteArguments {
final DocumentModel document;
final bool isLabelClickable;
final bool allowEdit;
final String? titleAndContentQueryString;
DocumentDetailsRouteArguments({
required this.document,
this.isLabelClickable = true,
this.allowEdit = true,
this.titleAndContentQueryString,
});
}

View File

@@ -0,0 +1,8 @@
import 'package:flutter/material.dart';
final rootNavigatorKey = GlobalKey<NavigatorState>();
final landingNavigatorKey = GlobalKey<NavigatorState>();
final documentsNavigatorKey = GlobalKey<NavigatorState>();
final scannerNavigatorKey = GlobalKey<NavigatorState>();
final labelsNavigatorKey = GlobalKey<NavigatorState>();
final inboxNavigatorKey = GlobalKey<NavigatorState>();

20
lib/routes/routes.dart Normal file
View File

@@ -0,0 +1,20 @@
class R {
const R._();
static const landing = "landing";
static const login = "login";
static const documents = "documents";
static const verifyIdentity = "verifyIdentity";
static const switchingAccounts = "switchingAccounts";
static const savedView = "savedView";
static const createSavedView = "createSavedView";
static const documentDetails = "documentDetails";
static const editDocument = "editDocument";
static const labels = "labels";
static const createLabel = "createLabel";
static const editLabel = "editLabel";
static const scanner = "scanner";
static const uploadDocument = "upload";
static const inbox = "inbox";
static const documentPreview = "documentPreview";
static const settings = "settings";
}

View File

@@ -0,0 +1,113 @@
import 'dart:ffi';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter/widgets.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/features/document_details/cubit/document_details_cubit.dart';
import 'package:paperless_mobile/features/document_details/view/pages/document_details_page.dart';
import 'package:paperless_mobile/features/document_edit/cubit/document_edit_cubit.dart';
import 'package:paperless_mobile/features/document_edit/view/document_edit_page.dart';
import 'package:paperless_mobile/features/documents/view/pages/document_view.dart';
import 'package:paperless_mobile/features/documents/view/pages/documents_page.dart';
import 'package:paperless_mobile/routes/navigation_keys.dart';
import 'package:paperless_mobile/routes/routes.dart';
part 'documents_route.g.dart';
class DocumentsBranch extends StatefulShellBranchData {
static final GlobalKey<NavigatorState> $navigatorKey = documentsNavigatorKey;
const DocumentsBranch();
}
@TypedGoRoute<DocumentsRoute>(
path: "/documents",
name: R.documents,
routes: [
TypedGoRoute<EditDocumentRoute>(
path: "edit",
name: R.editDocument,
),
TypedGoRoute<DocumentDetailsRoute>(
path: "details",
name: R.documentDetails,
),
TypedGoRoute<DocumentPreviewRoute>(
path: "preview",
name: R.documentPreview,
)
],
)
class DocumentsRoute extends GoRouteData {
@override
Widget build(BuildContext context, GoRouterState state) {
return const DocumentsPage();
}
}
class DocumentDetailsRoute extends GoRouteData {
static final GlobalKey<NavigatorState> $parentNavigatorKey = rootNavigatorKey;
final bool isLabelClickable;
final DocumentModel $extra;
final String? queryString;
const DocumentDetailsRoute({
required this.$extra,
this.isLabelClickable = true,
this.queryString,
});
@override
Widget build(BuildContext context, GoRouterState state) {
return BlocProvider(
create: (_) => DocumentDetailsCubit(
context.read(),
context.read(),
context.read(),
context.read(),
initialDocument: $extra,
),
lazy: false,
child: DocumentDetailsPage(
isLabelClickable: isLabelClickable,
titleAndContentQueryString: queryString,
),
);
}
}
class EditDocumentRoute extends GoRouteData {
static final GlobalKey<NavigatorState> $parentNavigatorKey = rootNavigatorKey;
final DocumentModel $extra;
const EditDocumentRoute(this.$extra);
@override
Widget build(BuildContext context, GoRouterState state) {
return BlocProvider(
create: (context) => DocumentEditCubit(
context.read(),
context.read(),
context.read(),
document: $extra,
)..loadFieldSuggestions(),
child: const DocumentEditPage(),
);
}
}
class DocumentPreviewRoute extends GoRouteData {
final DocumentModel $extra;
const DocumentPreviewRoute(this.$extra);
@override
Widget build(BuildContext context, GoRouterState state) {
return DocumentView(
documentBytes: context.read<PaperlessDocumentsApi>().download($extra),
);
}
}

View File

@@ -0,0 +1,17 @@
import 'package:flutter/src/widgets/framework.dart';
import 'package:go_router/go_router.dart';
import 'package:paperless_mobile/features/inbox/view/pages/inbox_page.dart';
import 'package:paperless_mobile/routes/routes.dart';
part 'inbox_route.g.dart';
@TypedGoRoute<InboxRoute>(
path: "/inbox",
name: R.inbox,
)
class InboxRoute extends GoRouteData {
@override
Widget build(BuildContext context, GoRouterState state) {
return const InboxPage();
}
}

View File

@@ -0,0 +1,84 @@
import 'package:flutter/widgets.dart';
import 'package:go_router/go_router.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/features/edit_label/view/impl/add_correspondent_page.dart';
import 'package:paperless_mobile/features/edit_label/view/impl/add_document_type_page.dart';
import 'package:paperless_mobile/features/edit_label/view/impl/add_storage_path_page.dart';
import 'package:paperless_mobile/features/edit_label/view/impl/add_tag_page.dart';
import 'package:paperless_mobile/features/edit_label/view/impl/edit_correspondent_page.dart';
import 'package:paperless_mobile/features/edit_label/view/impl/edit_document_type_page.dart';
import 'package:paperless_mobile/features/edit_label/view/impl/edit_storage_path_page.dart';
import 'package:paperless_mobile/features/edit_label/view/impl/edit_tag_page.dart';
import 'package:paperless_mobile/features/labels/view/pages/labels_page.dart';
import 'package:paperless_mobile/routes/navigation_keys.dart';
import 'package:paperless_mobile/routes/routes.dart';
part 'labels_route.g.dart';
class LabelsBranch extends StatefulShellBranchData {
static final GlobalKey<NavigatorState> $navigatorKey = labelsNavigatorKey;
const LabelsBranch();
}
@TypedGoRoute<LabelsRoute>(
path: "/labels",
name: R.labels,
routes: [
TypedGoRoute<EditLabelRoute>(
path: "edit",
name: R.editLabel,
),
TypedGoRoute<CreateLabelRoute>(
path: "create",
name: R.createLabel,
),
],
)
class LabelsRoute extends GoRouteData {
@override
Widget build(BuildContext context, GoRouterState state) {
return const LabelsPage();
}
}
class EditLabelRoute extends GoRouteData {
static final GlobalKey<NavigatorState> $parentNavigatorKey = rootNavigatorKey;
final Label $extra;
const EditLabelRoute(this.$extra);
@override
Widget build(BuildContext context, GoRouterState state) {
return switch ($extra) {
Correspondent c => EditCorrespondentPage(correspondent: c),
DocumentType d => EditDocumentTypePage(documentType: d),
Tag t => EditTagPage(tag: t),
StoragePath s => EditStoragePathPage(storagePath: s),
};
}
}
class CreateLabelRoute<T extends Label> extends GoRouteData {
static final GlobalKey<NavigatorState> $parentNavigatorKey = rootNavigatorKey;
final String? name;
CreateLabelRoute({
this.name,
});
@override
Widget build(BuildContext context, GoRouterState state) {
if (T is Correspondent) {
return AddCorrespondentPage(initialName: name);
} else if (T is DocumentType) {
return AddDocumentTypePage(initialName: name);
} else if (T is Tag) {
return AddTagPage(initialName: name);
} else if (T is StoragePath) {
return AddStoragePathPage(initialName: name);
}
throw ArgumentError();
}
}

View File

@@ -0,0 +1,38 @@
import 'package:flutter/widgets.dart';
import 'package:go_router/go_router.dart';
import 'package:paperless_mobile/features/landing/view/landing_page.dart';
import 'package:paperless_mobile/routes/navigation_keys.dart';
import 'package:paperless_mobile/routes/routes.dart';
part 'landing_route.g.dart';
class LandingBranch extends StatefulShellBranchData {
static final GlobalKey<NavigatorState> $navigatorKey = landingNavigatorKey;
const LandingBranch();
}
@TypedGoRoute<LandingRoute>(
path: "/landing",
name: R.landing,
routes: [
TypedGoRoute<SavedViewRoute>(
path: "saved-view",
name: R.savedView,
),
],
)
class LandingRoute extends GoRouteData {
const LandingRoute();
@override
Widget build(BuildContext context, GoRouterState state) {
return const LandingPage();
}
}
class SavedViewRoute extends GoRouteData {
@override
Widget build(BuildContext context, GoRouterState state) {
return Placeholder();
}
}

View File

@@ -0,0 +1,82 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:paperless_mobile/features/document_scan/view/scanner_page.dart';
import 'package:paperless_mobile/features/document_upload/cubit/document_upload_cubit.dart';
import 'package:paperless_mobile/features/document_upload/view/document_upload_preparation_page.dart';
import 'package:paperless_mobile/routes/navigation_keys.dart';
import 'package:paperless_mobile/routes/routes.dart';
part 'scanner_route.g.dart';
// @TypedStatefulShellBranch<ScannerBranch>(
// routes: [
// TypedGoRoute<ScannerRoute>(
// path: "/scanner",
// name: R.scanner,
// routes: [
// TypedGoRoute<DocumentUploadRoute>(
// path: "upload",
// name: R.uploadDocument,
// ),
// ],
// ),
// ],
// )
class ScannerBranch extends StatefulShellBranchData {
static final GlobalKey<NavigatorState> $navigatorKey = scannerNavigatorKey;
const ScannerBranch();
}
@TypedGoRoute<ScannerRoute>(
path: "/scanner",
name: R.scanner,
routes: [
TypedGoRoute<DocumentUploadRoute>(
path: "upload",
name: R.uploadDocument,
),
],
)
class ScannerRoute extends GoRouteData {
const ScannerRoute();
@override
Widget build(BuildContext context, GoRouterState state) {
return const ScannerPage();
}
}
class DocumentUploadRoute extends GoRouteData {
static final GlobalKey<NavigatorState> $parentNavigatorKey = rootNavigatorKey;
final Uint8List $extra;
final String? title;
final String? filename;
final String? fileExtension;
const DocumentUploadRoute({
required this.$extra,
this.title,
this.filename,
this.fileExtension,
});
@override
Widget build(BuildContext context, GoRouterState state) {
return BlocProvider(
create: (_) => DocumentUploadCubit(
context.read(),
context.read(),
context.read(),
),
child: DocumentUploadPreparationPage(
title: title,
fileExtension: fileExtension,
filename: filename,
fileBytes: $extra,
),
);
}
}

View File

@@ -0,0 +1,72 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:hive_flutter/adapters.dart';
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
import 'package:paperless_mobile/core/factory/paperless_api_factory.dart';
import 'package:paperless_mobile/features/home/view/home_shell_widget.dart';
import 'package:paperless_mobile/routes/navigation_keys.dart';
//part 'provider_shell_route.g.dart';
//TODO: Wait for https://github.com/flutter/flutter/issues/127371 to be merged
// @TypedShellRoute<ProviderShellRoute>(
// routes: [
// TypedStatefulShellRoute(
// branches: [
// TypedStatefulShellBranch<LandingBranch>(
// routes: [
// TypedGoRoute<LandingRoute>(
// path: "/landing",
// // name: R.landing,
// )
// ],
// ),
// TypedStatefulShellBranch<DocumentsBranch>(
// routes: [
// TypedGoRoute<DocumentsRoute>(
// path: "/documents",
// routes: [
// TypedGoRoute<DocumentDetailsRoute>(
// path: "details",
// // name: R.documentDetails,
// ),
// TypedGoRoute<DocumentEditRoute>(
// path: "edit",
// // name: R.editDocument,
// ),
// ],
// )
// ],
// ),
// ],
// ),
// ],
// )
class ProviderShellRoute extends ShellRouteData {
final PaperlessApiFactory apiFactory;
static final GlobalKey<NavigatorState> $navigatorKey = rootNavigatorKey;
const ProviderShellRoute(this.apiFactory);
Widget build(
BuildContext context,
GoRouterState state,
Widget navigator,
) {
final currentUserId = Hive.box<GlobalSettings>(HiveBoxes.globalSettings)
.getValue()!
.loggedInUserId!;
final authenticatedUser =
Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).get(
currentUserId,
)!;
return HomeShellWidget(
localUserId: authenticatedUser.id,
paperlessApiVersion: authenticatedUser.apiVersion,
paperlessProviderFactory: apiFactory,
child: navigator,
);
}
}

View File

@@ -0,0 +1,29 @@
import 'package:flutter/widgets.dart';
import 'package:go_router/go_router.dart';
import 'package:hive/hive.dart';
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
import 'package:paperless_mobile/features/home/view/scaffold_with_navigation_bar.dart';
class ScaffoldShellRoute extends StatefulShellRouteData {
const ScaffoldShellRoute();
@override
Widget builder(
BuildContext context,
GoRouterState state,
StatefulNavigationShell navigationShell,
) {
final currentUserId = Hive.box<GlobalSettings>(HiveBoxes.globalSettings)
.getValue()!
.loggedInUserId!;
final authenticatedUser =
Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).get(
currentUserId,
)!;
return ScaffoldWithNavigationBar(
authenticatedUser: authenticatedUser.paperlessUser,
navigationShell: navigationShell,
);
}
}

View File

@@ -0,0 +1,30 @@
import 'dart:async';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
import 'package:paperless_mobile/features/login/view/login_page.dart';
import 'package:paperless_mobile/routes/routes.dart';
part 'login_route.g.dart';
@TypedGoRoute<LoginRoute>(
path: "/login",
name: R.login,
)
class LoginRoute extends GoRouteData {
const LoginRoute();
@override
Widget build(BuildContext context, GoRouterState state) {
return const LoginPage();
}
@override
FutureOr<String?> redirect(BuildContext context, GoRouterState state) {
if (context.read<AuthenticationCubit>().state.isAuthenticated) {
return "/landing";
}
return null;
}
}

View File

@@ -0,0 +1,17 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:paperless_mobile/features/settings/view/settings_page.dart';
import 'package:paperless_mobile/routes/routes.dart';
part 'settings_route.g.dart';
@TypedGoRoute<SettingsRoute>(
path: "/settings",
name: R.settings,
)
class SettingsRoute extends GoRouteData {
@override
Widget build(BuildContext context, GoRouterState state) {
return const SettingsPage();
}
}

View File

@@ -0,0 +1,18 @@
import 'package:flutter/widgets.dart';
import 'package:go_router/go_router.dart';
import 'package:paperless_mobile/features/settings/view/pages/switching_accounts_page.dart';
import 'package:paperless_mobile/routes/routes.dart';
part 'switching_accounts_route.g.dart';
@TypedGoRoute<SwitchingAccountsRoute>(
path: '/switching-accounts',
name: R.switchingAccounts,
)
class SwitchingAccountsRoute extends GoRouteData {
const SwitchingAccountsRoute();
@override
Widget build(BuildContext context, GoRouterState state) {
return const SwitchingAccountsPage();
}
}

View File

@@ -0,0 +1,19 @@
import 'package:go_router/go_router.dart';
import 'package:flutter/widgets.dart';
import 'package:paperless_mobile/features/home/view/widget/verify_identity_page.dart';
import 'package:paperless_mobile/routes/routes.dart';
part 'verify_identity_route.g.dart';
@TypedGoRoute<VerifyIdentityRoute>(
path: '/verify-identity',
name: R.verifyIdentity,
)
class VerifyIdentityRoute extends GoRouteData {
const VerifyIdentityRoute();
@override
Widget build(BuildContext context, GoRouterState state) {
return const VerifyIdentityPage();
}
}