actions-test/lib/main.dart

302 lines
10 KiB
Dart
Raw Normal View History

2023-03-17 09:41:08 +01:00
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
2023-04-01 09:49:30 +02:00
import 'package:outbag_app/backend/themes.dart';
import 'package:outbag_app/backend/user.dart';
2023-04-01 09:49:30 +02:00
import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/screens/room/categories/edit.dart';
import 'package:outbag_app/screens/room/products/edit.dart';
import 'package:outbag_app/screens/room/products/view.dart';
2023-04-01 09:49:30 +02:00
import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:outbag_app/screens/home.dart';
import 'package:outbag_app/screens/welcome.dart';
import 'package:outbag_app/screens/auth.dart';
import 'package:outbag_app/screens/room/new.dart';
import 'package:outbag_app/screens/room/join.dart';
2023-04-01 09:49:30 +02:00
import 'package:outbag_app/screens/room/main.dart';
import 'package:outbag_app/screens/room/about/members.dart';
import 'package:outbag_app/screens/room/about/permissions.dart';
import 'package:outbag_app/screens/settings/main.dart';
2023-04-01 09:49:30 +02:00
import 'package:provider/provider.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
2023-03-17 09:41:08 +01:00
void main() {
WidgetsFlutterBinding.ensureInitialized();
2023-03-17 09:41:08 +01:00
runApp(const OutbagApp());
}
final GlobalKey<NavigatorState> _rootNavigatorKey =
GlobalKey<NavigatorState>(debugLabel: 'root');
final GlobalKey<NavigatorState> _userShellNavigatorKey =
GlobalKey<NavigatorState>(debugLabel: 'user');
2023-03-17 09:41:08 +01:00
class OutbagApp extends StatefulWidget {
const OutbagApp({super.key});
@override
State<StatefulWidget> createState() => _OutbagAppState();
}
class _OutbagAppState extends State {
// assume user is logged in
// unless not userdata is found
// or the userdata turns out to be wrong
User? user;
2023-03-17 09:41:08 +01:00
AppTheme theme = AppTheme.auto;
void loadTheme() async {
// load theme
try {
final theme = await AppTheme.fromDisk();
setState(() {
this.theme = theme;
});
} catch (_) {}
}
void loadUser() async {
// load user
try {
final user = await User.fromDisk();
setState(() {
this.user = user;
});
} catch (_) {
// user unavailable
// invalid credentials
// log out
setState(() {
user = null;
});
}
}
2023-03-17 09:41:08 +01:00
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
loadTheme();
loadUser();
});
}
Future<AccountMeta?> fetchInfo(User user) async {
AccountMeta? info;
// try to obtain user account information
2023-03-17 09:41:08 +01:00
// with existing details
// NOTE: also functions as a way to verify ther data
await doNetworkRequest(null,
req: () => postWithCreadentials(
target: user.server,
path: 'getMyAccount',
credentials: user,
body: {}),
onOK: (body) async {
final i = AccountMeta.fromJSON(body['data']);
info = i;
},
onServerErr: (_) {
info = null;
setState(() {
this.user = null;
});
return true;
},
onNetworkErr: () {
info = null;
// user is currently offline
// approve login,
// until user goes back offline
// NOTE TODO: check user data once online
return true;
});
return info;
2023-03-17 09:41:08 +01:00
}
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider<AppTheme>.value(value: theme),
],
child: MaterialApp.router(
title: "Outbag",
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
AppLocalizations.delegate
],
supportedLocales: AppLocalizations.supportedLocales,
themeMode: theme.mode,
theme: ThemeData(useMaterial3: true, brightness: Brightness.light),
darkTheme: ThemeData(useMaterial3: true, brightness: Brightness.dark),
routerConfig: GoRouter(
navigatorKey: _rootNavigatorKey,
initialLocation: '/',
redirect: (context, state) async {
if (user == null) {
// prelogin
if (!state.subloc.startsWith('/welcome')) {
// prevent unauthorized user from accessing home
return '/welcome';
}
} else {
// post login
if (state.subloc.startsWith('/welcome')) {
// prevent authorized user from accessing /welcome
return '/';
}
}
return null;
},
routes: <RouteBase>[
// unauthorized routes
GoRoute(
name: 'welcome',
path: '/welcome',
builder: (context, state) => const WelcomePage(),
routes: <RouteBase>[
GoRoute(
name: 'signin',
path: 'signin',
builder: (context, state) =>
AuthPage(mode: Mode.signin, refresh: loadUser),
),
GoRoute(
name: 'signup',
path: 'signup',
builder: (context, state) =>
AuthPage(mode: Mode.signup, refresh: loadUser),
),
GoRoute(
name: 'signup-ota',
path: 'signup-ota',
builder: (context, state) =>
AuthPage(mode: Mode.signupOTA, refresh: loadUser),
),
]),
// authorized routes
ShellRoute(
navigatorKey: _userShellNavigatorKey,
builder: (context, state, child) => Provider.value(
value: user!,
child: FutureProvider(
initialData: null,
child: child,
create: (context)=>fetchInfo(context.read<User>()),
)),
routes: <RouteBase>[
GoRoute(
path: '/',
name: 'home',
builder: (context, state) => const HomePage(),
routes: [
GoRoute(
name: 'settings',
path: 'settings',
builder: (context, state) =>
SettingsPage(
refreshTheme: loadTheme,
refreshUser: loadUser
)),
GoRoute(
path: 'join-room',
name: 'add-room',
builder: (context, state) =>
const JoinRoomPage(),
routes: <RouteBase>[
GoRoute(
path: 'new',
name: 'new-room',
builder: (context, state) => NewRoomPage()),
]),
GoRoute(
name: 'room',
path: 'r/:server/:id',
builder: (context, state) => RoomPage(
state.params['server'] ?? '',
state.params['id'] ?? ''),
routes: <RouteBase>[
GoRoute(
name: 'edit-room',
path: 'edit',
builder: (context, state) => NewRoomPage(
server: state.params['server'] ?? '',
tag: state.params['id'] ?? '')),
GoRoute(
name: 'room-members',
path: 'members',
builder: (context, state) =>
ManageRoomMembersPage(
state.params['server'] ?? '',
state.params['id'] ?? '')),
GoRoute(
name: 'room-permissions',
path: 'roles',
builder: (context, state) =>
EditRoomPermissionSetPage(
state.params['server'] ?? '',
state.params['id'] ?? '')),
GoRoute(
name: 'new-category',
path: 'new-category',
builder: (context, state)=>EditCategoryPage(
state.params['server'] ?? '',
state.params['id'] ?? '')),
GoRoute(
name: 'edit-category',
path: 'edit-category/:category',
builder: (context, state)=>EditCategoryPage(
state.params['server'] ?? '',
state.params['id'] ?? '',
id: int.tryParse(state.params['category'] ?? ''))),
GoRoute(
name: 'new-product',
path: 'new-product',
builder: (context, state)=>EditProductPage(
server: state.params['server'] ?? '',
room: state.params['id'] ?? '',)),
GoRoute(
name: 'view-product',
path: 'p/:product',
builder: (context, state)=>ViewProductPage(
server: state.params['server'] ?? '',
room: state.params['id'] ?? '',
product: int.tryParse(state.params['product'] ?? '') ?? 0),
routes: [
GoRoute(
name: 'edit-product',
path: 'edit',
builder: (context, state)=>EditProductPage(
server: state.params['server'] ?? '',
room: state.params['id'] ?? '',
product: int.tryParse(state.params['product'] ?? ''))),
]
),
])
]),
]),
// routes that can be accessed
// with and without an account
// i.e the about screen
GoRoute(
path: '/about',
name: 'about',
builder: (context, state) => const Text('About'))
]),
));
2023-03-17 09:41:08 +01:00
}
}