feat: add alot

This commit is contained in:
2026-10-08 04:12:36 +02:00
parent ccf5165417
commit fc607cb7bd
99 changed files with 4981 additions and 3655 deletions
+7 -7
View File
@@ -2,25 +2,25 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'app_lifecycle_lock.dart';
import '../l10n/app_localizations.dart';
import '../models/settings.dart';
import '../theme.dart';
import '../viewmodels/admin_pin_view_model.dart';
import '../viewmodels/pin_lock_view_model.dart';
import '../viewmodels/remote_sync_view_model.dart';
import '../viewmodels/settings_view_model.dart';
import '../theme.dart';
import '../l10n/app_localizations.dart';
import 'app_lifecycle_lock.dart';
class KoolTabApp extends StatefulWidget {
const KoolTabApp({super.key, required this.router});
class KoolTapApp extends StatefulWidget {
const KoolTapApp({super.key, required this.router});
final GoRouter router;
@override
State<KoolTabApp> createState() => _KoolTabAppState();
State<KoolTapApp> createState() => _KoolTapAppState();
}
class _KoolTabAppState extends State<KoolTabApp> {
class _KoolTapAppState extends State<KoolTapApp> {
late final AppLifecycleLockObserver _lifecycleLockObserver;
@override
+19 -9
View File
@@ -1,14 +1,17 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import '../database/app_database.dart';
import '../services/bar_tab_service.dart';
import '../services/default_product_seeder.dart';
import '../services/export_service.dart';
import '../viewmodels/bar_screen_view_model.dart';
import '../viewmodels/product_list_view_model.dart';
import '../viewmodels/remote_sync_view_model.dart';
/// Kicks off the work that can run after the first frame.
class AppBootstrap extends StatefulWidget {
final Widget child;
@@ -26,17 +29,24 @@ class _AppBootstrapState extends State<AppBootstrap> {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
final database = context.read<AppDatabase>();
DefaultProductSeeder(database: database).seedIfEmpty();
unawaited(
DefaultProductSeeder(
database: context.read<AppDatabase>(),
).seedIfEmpty(),
);
context.read<ProductListViewModel>().ensureLoaded();
context.read<BarScreenViewModel>().ensureLoaded();
DefaultExportService(database: database).uploadToServer();
unawaited(
DefaultExportService(
barTabService: context.read<BarTabService>(),
).uploadToServer(),
);
context.read<RemoteSyncViewModel>().init();
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
unawaited(
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky),
);
});
}
@@ -44,4 +54,4 @@ class _AppBootstrapState extends State<AppBootstrap> {
Widget build(BuildContext context) {
return widget.child;
}
}
}
+39 -38
View File
@@ -3,10 +3,12 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import '../utils/app_update_util.dart';
import '../viewmodels/admin_pin_view_model.dart';
import '../viewmodels/pin_lock_view_model.dart';
import '../viewmodels/remote_sync_view_model.dart';
import '../views/admin_screen_view.dart';
import '../views/bar_screen_view.dart';
import '../views/bar/bar_screen_view.dart';
import '../views/dev_menu_view.dart';
import '../views/error_screen_view.dart';
import '../views/history_screen_view.dart';
@@ -17,22 +19,23 @@ import '../views/product_list_view.dart';
import '../views/registration_view.dart';
import '../views/settings_view.dart';
import '../views/update_progress_view.dart';
import '../utils/app_update_util.dart';
final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
String? _redirectApp({
required PinLockViewModel pinLockViewModel,
required AdminPinViewModel adminPinViewModel,
required ValueNotifier<bool> isConfiguredNotifier,
required RemoteSyncViewModel remoteSyncViewModel,
required GoRouterState state,
}) {
if (!pinLockViewModel.hasLoaded || !adminPinViewModel.hasLoaded) {
if (!pinLockViewModel.hasLoaded ||
!adminPinViewModel.hasLoaded ||
!remoteSyncViewModel.hasLoaded) {
return null;
}
final location = state.uri.path;
final isConfigured = isConfiguredNotifier.value;
final isConfigured = remoteSyncViewModel.isConfigured;
if (!isConfigured && location != '/register') {
return '/register';
@@ -71,8 +74,8 @@ bool _mustBeOnLock(PinLockViewModel pinLockViewModel) {
!pinLockViewModel.isPinSet && pinLockViewModel.pinRequired;
final isLocked =
pinLockViewModel.isPinSet &&
!pinLockViewModel.isUnlocked &&
pinLockViewModel.pinRequired;
!pinLockViewModel.isUnlocked &&
pinLockViewModel.pinRequired;
return needsPinSetup || isLocked;
}
@@ -95,9 +98,10 @@ bool _isDebugShortcutArea(String location) {
location.startsWith('/history/');
}
GoRouter createAppRouter(PinLockViewModel pinLockViewModel, {
GoRouter createAppRouter({
required PinLockViewModel pinLockViewModel,
required AdminPinViewModel adminPinViewModel,
required ValueNotifier<bool> isConfiguredNotifier,
required RemoteSyncViewModel remoteSyncViewModel,
}) {
return GoRouter(
initialLocation: '/bar',
@@ -105,15 +109,14 @@ GoRouter createAppRouter(PinLockViewModel pinLockViewModel, {
refreshListenable: Listenable.merge([
pinLockViewModel,
adminPinViewModel,
isConfiguredNotifier,
remoteSyncViewModel,
]),
redirect: (_, state) =>
_redirectApp(
pinLockViewModel: pinLockViewModel,
adminPinViewModel: adminPinViewModel,
isConfiguredNotifier: isConfiguredNotifier,
state: state,
),
redirect: (_, state) => _redirectApp(
pinLockViewModel: pinLockViewModel,
adminPinViewModel: adminPinViewModel,
remoteSyncViewModel: remoteSyncViewModel,
state: state,
),
routes: [
GoRoute(path: '/', redirect: (context, state) => '/bar'),
@@ -124,32 +127,30 @@ GoRouter createAppRouter(PinLockViewModel pinLockViewModel, {
GoRoute(
path: '/lock',
builder: (context, state) =>
PinEntryView(
mode: pinLockViewModel.isPinSet
? PinEntryMode.unlock
: PinEntryMode.create,
onSuccess: () {
context.go("/bar");
},
),
builder: (context, state) => PinEntryView(
mode: pinLockViewModel.isPinSet
? PinEntryMode.unlock
: PinEntryMode.create,
onSuccess: () {
context.go('/bar');
},
),
),
GoRoute(path: '/bar', builder: (context, state) => const BarScreenView()),
GoRoute(
path: '/admin/lock',
builder: (context, state) =>
PinEntryView(
mode: adminPinViewModel.isPinSet
? PinEntryMode.unlock
: PinEntryMode.create,
isAdmin: true,
onVerify: adminPinViewModel.verify,
onSet: adminPinViewModel.setPin,
errorMessage: () => adminPinViewModel.errorMessage,
onSuccess: () => context.go('/admin'),
),
builder: (context, state) => PinEntryView(
mode: adminPinViewModel.isPinSet
? PinEntryMode.unlock
: PinEntryMode.create,
isAdmin: true,
onVerify: adminPinViewModel.verify,
onSet: adminPinViewModel.setPin,
error: () => adminPinViewModel.error,
onSuccess: () => context.go('/admin'),
),
),
GoRoute(
@@ -213,4 +214,4 @@ GoRouter createAppRouter(PinLockViewModel pinLockViewModel, {
),
],
);
}
}