feat: support smol:// QR sharing, deep links and in-dialog scanning

This commit is contained in:
randogoth 2026-09-30 17:14:47 +03:00
parent 7d2a147fec
commit aa74e12ee7
20 changed files with 591 additions and 101 deletions

View file

@ -1,10 +1,25 @@
import "package:auto_route/auto_route.dart";
import "package:flutter/material.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:smol_mail/presentation/routes/home_guard.dart";
import "package:smol_mail/presentation/routes/identity_guard.dart";
import "app_router.gr.dart";
/// A DialogRoute is a PageRoute whose settings carry the AutoRoutePage, so
/// auto_route's setNewRoutePath — which pops pageless top routes before
/// resolving a platform link — leaves dialog pages standing.
Route<T> dialogRouteBuilder<T>(
BuildContext context,
Widget child,
AutoRoutePage<T> page,
) =>
DialogRoute<T>(
context: context,
settings: page,
builder: (ctx) => child,
);
@AutoRouterConfig(replaceInRouteName: "Screen,Route")
class AppRouter extends RootStackRouter {
final WidgetRef ref;
@ -44,5 +59,11 @@ class AppRouter extends RootStackRouter {
path: "/contact",
guards: [IdentityGuard(ref)],
),
CustomRoute(
page: ImportContactDialogRoute.page,
path: "/import",
customRouteBuilder: dialogRouteBuilder,
guards: [IdentityGuard(ref)],
),
];
}

View file

@ -10,27 +10,29 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:auto_route/auto_route.dart' as _i9;
import 'package:flutter/material.dart' as _i10;
import 'package:auto_route/auto_route.dart' as _i10;
import 'package:flutter/material.dart' as _i11;
import 'package:smol_mail/presentation/screens/compose_screen.dart' as _i1;
import 'package:smol_mail/presentation/screens/contact_detail_screen.dart'
as _i2;
import 'package:smol_mail/presentation/screens/contacts_screen.dart' as _i3;
import 'package:smol_mail/presentation/screens/home_screen.dart' as _i4;
import 'package:smol_mail/presentation/screens/inbox_screen.dart' as _i5;
import 'package:smol_mail/presentation/screens/import_contact_dialog.dart'
as _i5;
import 'package:smol_mail/presentation/screens/inbox_screen.dart' as _i6;
import 'package:smol_mail/presentation/screens/message_detail_screen.dart'
as _i6;
import 'package:smol_mail/presentation/screens/onboarding_screen.dart' as _i7;
import 'package:smol_mail/presentation/screens/settings_screen.dart' as _i8;
as _i7;
import 'package:smol_mail/presentation/screens/onboarding_screen.dart' as _i8;
import 'package:smol_mail/presentation/screens/settings_screen.dart' as _i9;
/// generated route for
/// [_i1.ComposeScreen]
class ComposeRoute extends _i9.PageRouteInfo<ComposeRouteArgs> {
class ComposeRoute extends _i10.PageRouteInfo<ComposeRouteArgs> {
ComposeRoute({
_i10.Key? key,
_i11.Key? key,
String? to,
String? subject,
List<_i9.PageRouteInfo>? children,
List<_i10.PageRouteInfo>? children,
}) : super(
ComposeRoute.name,
args: ComposeRouteArgs(key: key, to: to, subject: subject),
@ -39,7 +41,7 @@ class ComposeRoute extends _i9.PageRouteInfo<ComposeRouteArgs> {
static const String name = 'ComposeRoute';
static _i9.PageInfo page = _i9.PageInfo(
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
final args = data.argsAs<ComposeRouteArgs>(
@ -57,7 +59,7 @@ class ComposeRoute extends _i9.PageRouteInfo<ComposeRouteArgs> {
class ComposeRouteArgs {
const ComposeRouteArgs({this.key, this.to, this.subject});
final _i10.Key? key;
final _i11.Key? key;
final String? to;
@ -81,11 +83,11 @@ class ComposeRouteArgs {
/// generated route for
/// [_i2.ContactDetailScreen]
class ContactDetailRoute extends _i9.PageRouteInfo<ContactDetailRouteArgs> {
class ContactDetailRoute extends _i10.PageRouteInfo<ContactDetailRouteArgs> {
ContactDetailRoute({
_i10.Key? key,
_i11.Key? key,
required String address,
List<_i9.PageRouteInfo>? children,
List<_i10.PageRouteInfo>? children,
}) : super(
ContactDetailRoute.name,
args: ContactDetailRouteArgs(key: key, address: address),
@ -94,7 +96,7 @@ class ContactDetailRoute extends _i9.PageRouteInfo<ContactDetailRouteArgs> {
static const String name = 'ContactDetailRoute';
static _i9.PageInfo page = _i9.PageInfo(
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
final args = data.argsAs<ContactDetailRouteArgs>();
@ -106,7 +108,7 @@ class ContactDetailRoute extends _i9.PageRouteInfo<ContactDetailRouteArgs> {
class ContactDetailRouteArgs {
const ContactDetailRouteArgs({this.key, required this.address});
final _i10.Key? key;
final _i11.Key? key;
final String address;
@ -128,13 +130,13 @@ class ContactDetailRouteArgs {
/// generated route for
/// [_i3.ContactsScreen]
class ContactsRoute extends _i9.PageRouteInfo<void> {
const ContactsRoute({List<_i9.PageRouteInfo>? children})
class ContactsRoute extends _i10.PageRouteInfo<void> {
const ContactsRoute({List<_i10.PageRouteInfo>? children})
: super(ContactsRoute.name, initialChildren: children);
static const String name = 'ContactsRoute';
static _i9.PageInfo page = _i9.PageInfo(
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
return const _i3.ContactsScreen();
@ -144,13 +146,13 @@ class ContactsRoute extends _i9.PageRouteInfo<void> {
/// generated route for
/// [_i4.HomeScreen]
class HomeRoute extends _i9.PageRouteInfo<void> {
const HomeRoute({List<_i9.PageRouteInfo>? children})
class HomeRoute extends _i10.PageRouteInfo<void> {
const HomeRoute({List<_i10.PageRouteInfo>? children})
: super(HomeRoute.name, initialChildren: children);
static const String name = 'HomeRoute';
static _i9.PageInfo page = _i9.PageInfo(
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
return const _i4.HomeScreen();
@ -159,29 +161,82 @@ class HomeRoute extends _i9.PageRouteInfo<void> {
}
/// generated route for
/// [_i5.InboxScreen]
class InboxRoute extends _i9.PageRouteInfo<void> {
const InboxRoute({List<_i9.PageRouteInfo>? children})
/// [_i5.ImportContactDialogScreen]
class ImportContactDialogRoute
extends _i10.PageRouteInfo<ImportContactDialogRouteArgs> {
ImportContactDialogRoute({
_i11.Key? key,
String? prefill,
List<_i10.PageRouteInfo>? children,
}) : super(
ImportContactDialogRoute.name,
args: ImportContactDialogRouteArgs(key: key, prefill: prefill),
initialChildren: children,
);
static const String name = 'ImportContactDialogRoute';
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
final args = data.argsAs<ImportContactDialogRouteArgs>(
orElse: () => const ImportContactDialogRouteArgs(),
);
return _i5.ImportContactDialogScreen(
key: args.key,
prefill: args.prefill,
);
},
);
}
class ImportContactDialogRouteArgs {
const ImportContactDialogRouteArgs({this.key, this.prefill});
final _i11.Key? key;
final String? prefill;
@override
String toString() {
return 'ImportContactDialogRouteArgs{key: $key, prefill: $prefill}';
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! ImportContactDialogRouteArgs) return false;
return key == other.key && prefill == other.prefill;
}
@override
int get hashCode => key.hashCode ^ prefill.hashCode;
}
/// generated route for
/// [_i6.InboxScreen]
class InboxRoute extends _i10.PageRouteInfo<void> {
const InboxRoute({List<_i10.PageRouteInfo>? children})
: super(InboxRoute.name, initialChildren: children);
static const String name = 'InboxRoute';
static _i9.PageInfo page = _i9.PageInfo(
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
return const _i5.InboxScreen();
return const _i6.InboxScreen();
},
);
}
/// generated route for
/// [_i6.MessageDetailScreen]
class MessageDetailRoute extends _i9.PageRouteInfo<MessageDetailRouteArgs> {
/// [_i7.MessageDetailScreen]
class MessageDetailRoute extends _i10.PageRouteInfo<MessageDetailRouteArgs> {
MessageDetailRoute({
_i10.Key? key,
_i11.Key? key,
required String folder,
required String id,
List<_i9.PageRouteInfo>? children,
List<_i10.PageRouteInfo>? children,
}) : super(
MessageDetailRoute.name,
args: MessageDetailRouteArgs(key: key, folder: folder, id: id),
@ -190,11 +245,11 @@ class MessageDetailRoute extends _i9.PageRouteInfo<MessageDetailRouteArgs> {
static const String name = 'MessageDetailRoute';
static _i9.PageInfo page = _i9.PageInfo(
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
final args = data.argsAs<MessageDetailRouteArgs>();
return _i6.MessageDetailScreen(
return _i7.MessageDetailScreen(
key: args.key,
folder: args.folder,
id: args.id,
@ -210,7 +265,7 @@ class MessageDetailRouteArgs {
required this.id,
});
final _i10.Key? key;
final _i11.Key? key;
final String folder;
@ -233,33 +288,33 @@ class MessageDetailRouteArgs {
}
/// generated route for
/// [_i7.OnboardingScreen]
class OnboardingRoute extends _i9.PageRouteInfo<void> {
const OnboardingRoute({List<_i9.PageRouteInfo>? children})
/// [_i8.OnboardingScreen]
class OnboardingRoute extends _i10.PageRouteInfo<void> {
const OnboardingRoute({List<_i10.PageRouteInfo>? children})
: super(OnboardingRoute.name, initialChildren: children);
static const String name = 'OnboardingRoute';
static _i9.PageInfo page = _i9.PageInfo(
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
return const _i7.OnboardingScreen();
return const _i8.OnboardingScreen();
},
);
}
/// generated route for
/// [_i8.SettingsScreen]
class SettingsRoute extends _i9.PageRouteInfo<void> {
const SettingsRoute({List<_i9.PageRouteInfo>? children})
/// [_i9.SettingsScreen]
class SettingsRoute extends _i10.PageRouteInfo<void> {
const SettingsRoute({List<_i10.PageRouteInfo>? children})
: super(SettingsRoute.name, initialChildren: children);
static const String name = 'SettingsRoute';
static _i9.PageInfo page = _i9.PageInfo(
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
return const _i8.SettingsScreen();
return const _i9.SettingsScreen();
},
);
}