Migrated to GoRouter

Reasons for migration:
- buggy behaviour from old router
- GoRouter is a recommended flutter plugin
- ShellRoutes allow exposing Providers
  to a limited scope of routes
- GoRoutes provides named routes,
  and the navigator allows us to provide parameters directly.
This commit is contained in:
Jakob Meier 2023-03-28 14:54:39 +02:00
parent bb9a8621a0
commit 5b9b48cd24
No known key found for this signature in database
GPG key ID: 66BDC7E6A01A6152
14 changed files with 316 additions and 278 deletions

View file

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:outbag_app/backend/themes.dart'; import 'package:outbag_app/backend/themes.dart';
import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/backend/user.dart';
import 'package:outbag_app/screens/room/edit.dart'; import 'package:outbag_app/screens/room/edit.dart';
@ -14,13 +15,19 @@ import './screens/welcome.dart';
import './screens/room/main.dart'; import './screens/room/main.dart';
import './screens/auth.dart'; import './screens/auth.dart';
import './backend/request.dart'; import './backend/request.dart';
import 'package:routemaster/routemaster.dart';
void main() { void main() {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
runApp(const OutbagApp()); runApp(const OutbagApp());
} }
final GlobalKey<NavigatorState> _rootNavigatorKey =
GlobalKey<NavigatorState>(debugLabel: 'root');
final GlobalKey<NavigatorState> _userShellNavigatorKey =
GlobalKey<NavigatorState>(debugLabel: 'user');
final GlobalKey<NavigatorState> _roomShellNavigatorKey =
GlobalKey<NavigatorState>(debugLabel: 'room');
class OutbagApp extends StatefulWidget { class OutbagApp extends StatefulWidget {
const OutbagApp({super.key}); const OutbagApp({super.key});
@ -41,43 +48,45 @@ class _OutbagAppState extends State {
void initState() { void initState() {
super.initState(); super.initState();
// wait for user to be authorized
User.listen((_) async {
try {
final user = await User.fromDisk();
setState(() {
this.user = user;
});
fetchInfo();
} catch (_) {
// no userdata found
setState(() {
user = null;
});
}
});
AppTheme.listen((_) async {
final theme = await AppTheme.fromDisk();
setState(() {
this.theme = theme;
});
});
(() async {
final theme = await AppTheme.fromDisk();
setState(() {
this.theme = theme;
});
})();
WidgetsBinding.instance.addPostFrameCallback((_) async { WidgetsBinding.instance.addPostFrameCallback((_) async {
// wait for user to be authorized
User.listen((_) async {
try {
final user = await User.fromDisk();
setState(() {
this.user = user;
});
fetchInfo(user);
} catch (_) {
// no userdata found
setState(() {
user = null;
});
}
});
AppTheme.listen((_) async {
final theme = await AppTheme.fromDisk();
setState(() {
this.theme = theme;
});
});
// load theme
try {
final theme = await AppTheme.fromDisk();
setState(() {
this.theme = theme;
});
} catch (_) {}
// load user
try { try {
final user = await User.fromDisk(); final user = await User.fromDisk();
setState(() { setState(() {
this.user = user; this.user = user;
}); });
fetchInfo(); fetchInfo(user);
} catch (_) { } catch (_) {
// user unavailable // user unavailable
// invalid credentials // invalid credentials
@ -89,15 +98,15 @@ class _OutbagAppState extends State {
}); });
} }
void fetchInfo() async { void fetchInfo(User user) async {
// try to obtain user account information // try to obtain user account information
// with existing details // with existing details
// NOTE: also functions as a way to verify ther data // NOTE: also functions as a way to verify ther data
doNetworkRequest(null, doNetworkRequest(null,
req: () => postWithCreadentials( req: () => postWithCreadentials(
target: (user?.server)!, target: user.server,
path: 'getMyAccount', path: 'getMyAccount',
credentials: user!, credentials: user,
body: {}), body: {}),
onOK: (body) { onOK: (body) {
final info = AccountMeta.fromJSON(body['data']); final info = AccountMeta.fromJSON(body['data']);
@ -111,7 +120,7 @@ class _OutbagAppState extends State {
setState(() { setState(() {
info = null; info = null;
user = null; this.user = null;
}); });
return true; return true;
}, },
@ -132,87 +141,139 @@ class _OutbagAppState extends State {
value: info, value: info,
), ),
Provider<AppTheme>.value(value: theme), Provider<AppTheme>.value(value: theme),
// conditional user provider
// used to only provide a user outside of the login area
...(user!=null)?[
Provider<User>.value(value:user!)
]:[]
], ],
child: MaterialApp.router( child: MaterialApp.router(
title: "Outbag", title: "Outbag",
themeMode: theme.mode, themeMode: theme.mode,
theme: ThemeData(useMaterial3: true, brightness: Brightness.light), theme: ThemeData(useMaterial3: true, brightness: Brightness.light),
darkTheme: ThemeData(useMaterial3: true, brightness: Brightness.dark), darkTheme: ThemeData(useMaterial3: true, brightness: Brightness.dark),
routerDelegate: RoutemasterDelegate( routerConfig: GoRouter(
routesBuilder: (context) => RouteMap( navigatorKey: _rootNavigatorKey,
routes: { initialLocation: '/',
// pre authentification routes redirect: (context, state) async {
...(user == null) if (user == null) {
? { // prelogin
'/welcome/': (_) => if (!state.subloc.startsWith('/welcome')) {
const MaterialPage(child: WelcomePage()), // prevent unauthorized user from accessing home
'/signup': (_) => const MaterialPage( return '/welcome';
child: AuthPage(mode: Mode.signup)),
'/signupOTA': (_) => const MaterialPage(
child: AuthPage(mode: Mode.signupOTA)),
'/signin': (_) => const MaterialPage(
child: AuthPage(mode: Mode.signin)),
} }
: {}, } else {
// post login
if (state.subloc.startsWith('/welcome')) {
// prevent authorized user from accessing /welcome
return '/';
}
}
// routes that need the user return null;
// to exis },
...(user!=null)?{ routes: <RouteBase>[
'/': (_) => const MaterialPage(child: HomePage()), // unauthorized routes
GoRoute(
name: 'welcome',
path: '/welcome',
builder: (context, state) => const WelcomePage(),
routes: <RouteBase>[
GoRoute(
name: 'signin',
path: 'signin',
builder: (context, state) =>
const AuthPage(mode: Mode.signin),
),
GoRoute(
name: 'signup',
path: 'signup',
builder: (context, state) =>
const AuthPage(mode: Mode.signup),
),
GoRoute(
name: 'signup-ota',
path: 'signup-ota',
builder: (context, state) =>
const AuthPage(mode: Mode.signupOTA),
),
]),
// user-space settings // authorized routes
'/settings': (_) => ShellRoute(
const MaterialPage(child: SettingsPage()), navigatorKey: _userShellNavigatorKey,
builder: (context, state, child) =>
Provider.value(value: user!, child: child),
routes: <RouteBase>[
GoRoute(
path: '/',
name: 'home',
builder: (context, state) => const HomePage(),
routes: [
GoRoute(
name: 'settings',
path: 'settings',
builder: (context, state) =>
const SettingsPage()),
GoRoute(
path: 'join-room',
name: 'add-room',
builder: (context, state) =>
const JoinRoomPage(),
routes: <RouteBase>[
GoRoute(
path: 'new',
name: 'new-room',
builder: (context, state) =>
const NewRoomPage()),
]),
GoRoute(
name: 'room',
path: 'r/:server/:id',
builder: (context, state) => RoomPage(
state.params['server'] ?? '',
state.params['id'] ?? ''),
routes: <RouteBase>[
ShellRoute(
navigatorKey: _roomShellNavigatorKey,
builder: (context, state, child) =>
Provider.value(
// TODO: provide nullable room data
value: null,
child: child),
routes: <RouteBase>[
GoRoute(
name: 'edit-room',
path: 'edit',
builder: (context, state) =>
EditRoomPage(
state.params['server'] ??
'',
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'] ?? '')),
])
])
]),
]),
// server dashboard // routes that can be accessed
// TODO: add permission check // with and without an account
// so routes are only available // i.e the about screen
// if user is allowed to view dashboard GoRoute(
...{ path: '/about',
name: 'about',
}, builder: (context, state) => const Text('About'))
// room related settings ]),
'/add-room/new': (_) =>
const MaterialPage(child: NewRoomPage()),
'/add-room': (_) =>
const MaterialPage(child: JoinRoomPage()),
'/r/:server/:tag/': (info) {
final server = info.pathParameters['server'] ?? "";
final tag = info.pathParameters['tag'] ?? "";
return MaterialPage(child: RoomPage(server, tag));
},
'/r/:server/:tag/edit': (info) {
final server = info.pathParameters['server'] ?? "";
final tag = info.pathParameters['tag'] ?? "";
return MaterialPage(child: EditRoomPage(server, tag));
},
'/r/:server/:tag/members': (info) {
final server = info.pathParameters['server'] ?? "";
final tag = info.pathParameters['tag'] ?? "";
return MaterialPage(
child: ManageRoomMembersPage(server, tag));
},
'/r/:server/:tag/permissions': (info) {
final server = info.pathParameters['server'] ?? "";
final tag = info.pathParameters['tag'] ?? "";
return MaterialPage(
child: EditRoomPermissionSetPage(server, tag));
},
}:{}
},
onUnknownRoute: (_) => (user == null)
? const MaterialPage(child: WelcomePage())
: const Redirect('/'))),
routeInformationParser: const RoutemasterParser(),
)); ));
} }
} }

View file

@ -4,7 +4,6 @@ import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/backend/user.dart';
import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:outbag_app/tools/snackbar.dart'; import 'package:outbag_app/tools/snackbar.dart';
import 'package:routemaster/routemaster.dart';
import '../backend/resolve_url.dart'; import '../backend/resolve_url.dart';
enum Mode { enum Mode {
@ -58,14 +57,6 @@ class _AuthPageState extends State<AuthPage> {
: Scaffold( : Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(modeName), title: Text(modeName),
leading: IconButton(
onPressed: () {
// go back
Routemaster.of(context).history.back();
},
icon: const Icon(Icons.arrow_back),
tooltip: "Go back",
),
), ),
body: Center( body: Center(
child: ConstrainedBox( child: ConstrainedBox(

View file

@ -5,7 +5,7 @@ import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/backend/user.dart';
import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:routemaster/routemaster.dart'; import 'package:go_router/go_router.dart';
import '../backend/room.dart'; import '../backend/room.dart';
class HomePage extends StatefulWidget { class HomePage extends StatefulWidget {
@ -23,12 +23,12 @@ class _HomePageState extends State<HomePage> {
// wait for background room changes // wait for background room changes
Room.listen((_) async { Room.listen((_) async {
try { try {
final newRooms = await Room.listRooms(); final newRooms = await Room.listRooms();
setState(() { setState(() {
rooms = newRooms; rooms = newRooms;
}); });
} catch (_) {} } catch (_) {}
}); });
WidgetsBinding.instance.addPostFrameCallback((_) => fetchList()); WidgetsBinding.instance.addPostFrameCallback((_) => fetchList());
@ -42,17 +42,17 @@ class _HomePageState extends State<HomePage> {
try { try {
final newRooms = await Room.listRooms(); final newRooms = await Room.listRooms();
setState(() { setState(() {
rooms = newRooms; rooms = newRooms;
}); });
} catch (_) {} } catch (_) {}
doNetworkRequest( doNetworkRequest(
sm, sm,
req: () => postWithCreadentials( req: () => postWithCreadentials(
path: 'listRooms', credentials: user, target: user.server, body: {}), path: 'listRooms', credentials: user, target: user.server, body: {}),
onOK: (body) async { onOK: (body) async {
final List<Room> list = body['data'].map<Room>((json) { final List<Room> list = body['data'].map<Room>((json) {
return Room.fromJSON(json); return Room.fromJSON(json);
}).toList(); }).toList();
for (Room r in list) { for (Room r in list) {
await r.toDisk(); await r.toDisk();
@ -90,33 +90,33 @@ class _HomePageState extends State<HomePage> {
}, },
menuChildren: [ menuChildren: [
MenuItemButton( MenuItemButton(
leadingIcon: const Icon(Icons.settings), leadingIcon: const Icon(Icons.settings),
child: const Text('Settings'), child: const Text('Settings'),
onPressed: () {
// show settings screen
context.goNamed('settings');
}),
...(context.watch<AccountMeta?>() != null &&
(context.watch<AccountMeta?>()?.permissions)! &
ServerPermission.allManagement !=
0)
? [
MenuItemButton(
leadingIcon: const Icon(Icons.dns),
child: const Text('Server Dashboard'),
onPressed: () { onPressed: () {
// show settings screen // show settings screen
Routemaster.of(context).push("/settings"); context.goNamed('dash');
}), }),
...(context.watch<AccountMeta?>() != null && ]
(context.watch<AccountMeta?>()?.permissions)! & : [],
ServerPermission.allManagement !=
0)
? [
MenuItemButton(
leadingIcon: const Icon(Icons.dns),
child: const Text('Server Dashboard'),
onPressed: () {
// show settings screen
Routemaster.of(context).push("/server");
}),
]
: [],
MenuItemButton( MenuItemButton(
leadingIcon: const Icon(Icons.info_rounded), leadingIcon: const Icon(Icons.info_rounded),
child: const Text('About'), child: const Text('About'),
onPressed: () { onPressed: () {
// show about screen // show about screen
Routemaster.of(context).push("/about"); context.goNamed('about');
}), }),
], ],
) )
], ],
@ -126,31 +126,31 @@ class _HomePageState extends State<HomePage> {
itemBuilder: (ctx, i) { itemBuilder: (ctx, i) {
final room = rooms[i]; final room = rooms[i];
return Card( return Card(
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
clipBehavior: Clip.antiAliasWithSaveLayer, clipBehavior: Clip.antiAliasWithSaveLayer,
semanticContainer: true, semanticContainer: true,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
// open room // open room
Routemaster.of(context) context.goNamed('room',
.push("/r/${room.serverTag}/${room.id}"); params: {'server': room.serverTag, 'id': room.id});
}, },
onLongPress: () { onLongPress: () {
// open bottom sheet // open bottom sheet
// NOTE: feature yet to be confirmed // NOTE: feature yet to be confirmed
}, },
child: Container( child: Container(
padding: const EdgeInsets.fromLTRB(10, 5, 5, 10), padding: const EdgeInsets.fromLTRB(10, 5, 5, 10),
child: ListTile( child: ListTile(
title: Text(room.name), title: Text(room.name),
visualDensity: const VisualDensity(vertical: 3), visualDensity: const VisualDensity(vertical: 3),
subtitle: Text(room.description), subtitle: Text(room.description),
leading: AspectRatio( leading: AspectRatio(
aspectRatio: 1 / 1, aspectRatio: 1 / 1,
child: SvgPicture.asset("${room.icon?.img}"), child: SvgPicture.asset("${room.icon?.img}"),
), ),
hoverColor: Colors.transparent, hoverColor: Colors.transparent,
)))); ))));
}, },
), ),
floatingActionButton: FloatingActionButton.extended( floatingActionButton: FloatingActionButton.extended(
@ -158,7 +158,7 @@ class _HomePageState extends State<HomePage> {
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
onPressed: () { onPressed: () {
// create new room // create new room
Routemaster.of(context).push("/add-room"); context.goNamed('add-room');
}, },
tooltip: 'Add new Room', tooltip: 'Add new Room',
), ),

View file

@ -1,12 +1,12 @@
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:outbag_app/backend/errors.dart'; import 'package:outbag_app/backend/errors.dart';
import 'package:outbag_app/backend/request.dart'; import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/backend/room.dart'; import 'package:outbag_app/backend/room.dart';
import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/backend/user.dart';
import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:routemaster/routemaster.dart';
import 'dart:math'; import 'dart:math';
class EditRoomPage extends StatefulWidget { class EditRoomPage extends StatefulWidget {
@ -44,7 +44,7 @@ class _EditRoomPageState extends State<EditRoomPage> {
// fetch room information // fetch room information
void fetchInfo() { void fetchInfo() {
final sm = ScaffoldMessenger.of(context); final sm = ScaffoldMessenger.of(context);
final rmaster = Routemaster.of(context); final router = GoRouter.of(context);
final user = context.read<User>(); final user = context.read<User>();
doNetworkRequest( doNetworkRequest(
@ -69,7 +69,7 @@ class _EditRoomPageState extends State<EditRoomPage> {
} catch (_) { } catch (_) {
// no room data available // no room data available
// close screen // close screen
rmaster.replace('/'); router.pushReplacementNamed('homoe');
} }
})(); })();
return true; return true;
@ -77,7 +77,7 @@ class _EditRoomPageState extends State<EditRoomPage> {
onServerErr: (json) { onServerErr: (json) {
// user not allowed to be here // user not allowed to be here
// close screen // close screen
rmaster.replace('/'); router.pushReplacementNamed('homoe');
return true; return true;
}, },
); );

View file

@ -1,11 +1,11 @@
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:outbag_app/backend/request.dart'; import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/backend/room.dart'; import 'package:outbag_app/backend/room.dart';
import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/backend/user.dart';
import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:routemaster/routemaster.dart';
import 'dart:math'; import 'dart:math';
class JoinRoomPage extends StatefulWidget { class JoinRoomPage extends StatefulWidget {
@ -99,14 +99,6 @@ class _JoinRoomPageState extends State {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('Join Room'), title: const Text('Join Room'),
leading: IconButton(
onPressed: () {
// go back
Routemaster.of(context).history.back();
},
icon: const Icon(Icons.arrow_back),
tooltip: "Go back",
),
actions: [ actions: [
IconButton( IconButton(
icon: const Icon(Icons.search), icon: const Icon(Icons.search),
@ -143,7 +135,7 @@ class _JoinRoomPageState extends State {
child: const Text('Join invite-only room'), child: const Text('Join invite-only room'),
onPressed: () { onPressed: () {
// show settings screen // show settings screen
Routemaster.of(context).push("/add-room/by-id"); context.goNamed('join-room-ota');
}), }),
]) ])
], ],
@ -243,13 +235,13 @@ class _JoinRoomPageState extends State {
final scaffMgr = final scaffMgr =
ScaffoldMessenger.of( ScaffoldMessenger.of(
context); context);
final rmaster =
Routemaster.of(
context);
final nav = final nav =
Navigator.of(context); Navigator.of(context);
final user = final user =
context.read<User>(); context.read<User>();
final router =
GoRouter.of(context);
doNetworkRequest(scaffMgr, doNetworkRequest(scaffMgr,
req: () => req: () =>
@ -269,8 +261,14 @@ class _JoinRoomPageState extends State {
onOK: (body) async { onOK: (body) async {
await room.toDisk(); await room.toDisk();
nav.pop(); nav.pop();
rmaster.replace( router
'/r/${room.serverTag}/${room.id}'); .pushReplacementNamed(
'room',
params: {
'server': room
.serverTag,
'id': room.id
});
}); });
}, },
)) ))
@ -300,7 +298,7 @@ class _JoinRoomPageState extends State {
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
onPressed: () { onPressed: () {
// create new room // create new room
Routemaster.of(context).push("/add-room/new"); context.goNamed('new-room');
}, },
tooltip: 'Create Room', tooltip: 'Create Room',
), ),

View file

@ -8,7 +8,6 @@ import 'package:outbag_app/screens/room/pages/products.dart';
import 'package:outbag_app/screens/room/pages/list.dart'; import 'package:outbag_app/screens/room/pages/list.dart';
import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:routemaster/routemaster.dart';
class RoomPage extends StatefulWidget { class RoomPage extends StatefulWidget {
final String server; final String server;
@ -105,14 +104,6 @@ class _RoomPageState extends State<RoomPage> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(room?.name ?? 'Unknown Room'), title: Text(room?.name ?? 'Unknown Room'),
leading: IconButton(
onPressed: () {
// go back
Routemaster.of(context).history.back();
},
icon: const Icon(Icons.arrow_back),
tooltip: "Go back",
),
), ),
body: PageView( body: PageView(
controller: _ctr, controller: _ctr,

View file

@ -1,11 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:outbag_app/backend/permissions.dart'; import 'package:outbag_app/backend/permissions.dart';
import 'package:outbag_app/backend/request.dart'; import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/backend/room.dart'; import 'package:outbag_app/backend/room.dart';
import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/backend/user.dart';
import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:routemaster/routemaster.dart';
class ManageRoomMembersPage extends StatefulWidget { class ManageRoomMembersPage extends StatefulWidget {
final String server; final String server;
@ -22,7 +22,7 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
RoomInfo? info; RoomInfo? info;
void fetchUserInfo() { void fetchUserInfo() {
final rmaster = Routemaster.of(context); final router = GoRouter.of(context);
final sm = ScaffoldMessenger.of(context); final sm = ScaffoldMessenger.of(context);
final user = context.read<User>(); final user = context.read<User>();
@ -36,7 +36,7 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
onAnyErr: () { onAnyErr: () {
// user should not be here // user should not be here
// close screen // close screen
rmaster.replace('/'); router.pushReplacementNamed('home');
return false; return false;
}, },
onOK: (body) async { onOK: (body) async {
@ -50,7 +50,7 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
} }
void fetchMembers() { void fetchMembers() {
final rmaster = Routemaster.of(context); final router = GoRouter.of(context);
final sm = ScaffoldMessenger.of(context); final sm = ScaffoldMessenger.of(context);
final user = context.read<User>(); final user = context.read<User>();
@ -63,7 +63,7 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
onAnyErr: () { onAnyErr: () {
// user should not be here // user should not be here
// close screen // close screen
rmaster.replace('/'); router.pushReplacementNamed('home');
return false; return false;
}, },
onOK: (body) { onOK: (body) {
@ -303,11 +303,7 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
doNetworkRequest( doNetworkRequest(
scaffMgr, scaffMgr,
req: () => req: () =>
postWithCreadentials( postWithCreadentials(path: 'kickMember', credentials: user, target: user.server, body: {
path: 'kickMember',
credentials: user,
target: user.server,
body: {
'room': widget.tag, 'room': widget.tag,
'roomServer': widget.server, 'roomServer': widget.server,
'name': item.id, 'name': item.id,

View file

@ -1,12 +1,12 @@
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:outbag_app/backend/request.dart'; import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/backend/room.dart'; import 'package:outbag_app/backend/room.dart';
import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/backend/user.dart';
import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:outbag_app/tools/snackbar.dart'; import 'package:outbag_app/tools/snackbar.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:routemaster/routemaster.dart';
import 'dart:math'; import 'dart:math';
class NewRoomPage extends StatefulWidget { class NewRoomPage extends StatefulWidget {
@ -48,14 +48,6 @@ class _NewRoomPageState extends State {
: Scaffold( : Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('New Room'), title: const Text('New Room'),
leading: IconButton(
onPressed: () {
// go back
Routemaster.of(context).history.back();
},
icon: const Icon(Icons.arrow_back),
tooltip: "Go back",
),
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
child: Center( child: Center(
@ -186,7 +178,7 @@ class _NewRoomPageState extends State {
floatingActionButton: FloatingActionButton.extended( floatingActionButton: FloatingActionButton.extended(
onPressed: () async { onPressed: () async {
final scaffMgr = ScaffoldMessenger.of(context); final scaffMgr = ScaffoldMessenger.of(context);
final rmaster = Routemaster.of(context); final router = GoRouter.of(context);
// ID should be at least three characters long // ID should be at least three characters long
if (_ctrID.text.length < 3) { if (_ctrID.text.length < 3) {
@ -233,7 +225,7 @@ class _NewRoomPageState extends State {
// save room // save room
await room.toDisk(); await room.toDisk();
// move to home page // move to home page
rmaster.replace('/'); router.pushReplacementNamed('home');
}); });
}, },
label: const Text('Create'), label: const Text('Create'),

View file

@ -1,5 +1,6 @@
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:outbag_app/backend/permissions.dart'; import 'package:outbag_app/backend/permissions.dart';
import 'package:outbag_app/backend/request.dart'; import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/backend/room.dart'; import 'package:outbag_app/backend/room.dart';
@ -7,7 +8,6 @@ import 'package:outbag_app/backend/user.dart';
import 'dart:math'; import 'dart:math';
import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:routemaster/routemaster.dart';
class AboutRoomPage extends StatefulWidget { class AboutRoomPage extends StatefulWidget {
final RoomInfo? info; final RoomInfo? info;
@ -161,8 +161,10 @@ class _AboutRoomPageState extends State<AboutRoomPage> {
'Change the rooms name, description and icon'), 'Change the rooms name, description and icon'),
onTap: () { onTap: () {
// show edit room screen // show edit room screen
Routemaster.of(context).push( context.goNamed('edit-room', params: {
'/r/${widget.room?.serverTag}/${widget.room?.id}/edit'); 'server': (widget.room?.serverTag)!,
'id': (widget.room?.id)!
});
}, },
), ),
] ]
@ -174,8 +176,10 @@ class _AboutRoomPageState extends State<AboutRoomPage> {
subtitle: const Text('Show Member list'), subtitle: const Text('Show Member list'),
onTap: () { onTap: () {
// open member view screen // open member view screen
Routemaster.of(context).push( context.goNamed('room-members', params: {
'/r/${widget.room?.serverTag}/${widget.room?.id}/members'); 'server': (widget.room?.serverTag)!,
'id': (widget.room?.id)!
});
}, },
), ),
// edit default member permission // edit default member permission
@ -193,8 +197,10 @@ class _AboutRoomPageState extends State<AboutRoomPage> {
'Change the default permission-set for all members'), 'Change the default permission-set for all members'),
onTap: () { onTap: () {
// show checkbox screen // show checkbox screen
Routemaster.of(context).push( context.goNamed('room-permissions', params: {
'/r/${widget.room?.serverTag}/${widget.room?.id}/permissions'); 'server': (widget.room?.serverTag)!,
'id': (widget.room?.id)!
});
}, },
), ),
] ]
@ -211,8 +217,10 @@ class _AboutRoomPageState extends State<AboutRoomPage> {
subtitle: const Text('Add and delete OTAs'), subtitle: const Text('Add and delete OTAs'),
onTap: () { onTap: () {
// show manage ota screen // show manage ota screen
Routemaster.of(context).push( context.goNamed('room-ota', params: {
'/r/${widget.room?.serverTag}/${widget.room?.id}/ota'); 'server': (widget.room?.serverTag)!,
'id': (widget.room?.id)!
});
}, },
), ),
ListTile( ListTile(
@ -221,8 +229,10 @@ class _AboutRoomPageState extends State<AboutRoomPage> {
subtitle: const Text('Invite people to this room'), subtitle: const Text('Invite people to this room'),
onTap: () { onTap: () {
// show manage ota screen // show manage ota screen
Routemaster.of(context).push( context.goNamed('room-invite', params: {
'/r/${widget.room?.serverTag}/${widget.room?.id}/invite'); 'server': (widget.room?.serverTag)!,
'id': (widget.room?.id)!
});
}, },
), ),
] ]
@ -262,7 +272,7 @@ class _AboutRoomPageState extends State<AboutRoomPage> {
final scaffMgr = final scaffMgr =
ScaffoldMessenger.of(ctx); ScaffoldMessenger.of(ctx);
final nav = Navigator.of(ctx); final nav = Navigator.of(ctx);
final rmaster = Routemaster.of(ctx); final router = GoRouter.of(ctx);
final user = ctx.read<User>(); final user = ctx.read<User>();
doNetworkRequest(scaffMgr, doNetworkRequest(scaffMgr,
@ -284,7 +294,7 @@ class _AboutRoomPageState extends State<AboutRoomPage> {
} catch (_) {} } catch (_) {}
// go back home // go back home
rmaster.replace('/'); router.pushReplacementNamed('home');
}, },
after: () { after: () {
// close popup // close popup

View file

@ -1,13 +1,13 @@
import 'dart:math'; import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:outbag_app/backend/permissions.dart'; import 'package:outbag_app/backend/permissions.dart';
import 'package:outbag_app/backend/request.dart'; import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/backend/room.dart'; import 'package:outbag_app/backend/room.dart';
import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/backend/user.dart';
import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:routemaster/routemaster.dart';
class EditRoomPermissionSetPage extends StatefulWidget { class EditRoomPermissionSetPage extends StatefulWidget {
final String server; final String server;
@ -24,7 +24,7 @@ class _EditRoomPermissionSetPageState extends State<EditRoomPermissionSetPage> {
int permissions = 0; int permissions = 0;
void fetchInfo() { void fetchInfo() {
final rmaster = Routemaster.of(context); final router = GoRouter.of(context);
final sm = ScaffoldMessenger.of(context); final sm = ScaffoldMessenger.of(context);
final user = context.read<User>(); final user = context.read<User>();
@ -38,7 +38,7 @@ class _EditRoomPermissionSetPageState extends State<EditRoomPermissionSetPage> {
onAnyErr: () { onAnyErr: () {
// user should not be here // user should not be here
// close screen // close screen
rmaster.replace('/'); router.pushReplacementNamed('home');
return false; return false;
}, },
onOK: (body) async { onOK: (body) async {
@ -95,7 +95,7 @@ class _EditRoomPermissionSetPageState extends State<EditRoomPermissionSetPage> {
tooltip: "Update default permission set", tooltip: "Update default permission set",
label: const Text('Edit'), label: const Text('Edit'),
onPressed: () { onPressed: () {
final rmaster = Routemaster.of(context); final router = GoRouter.of(context);
final sm = ScaffoldMessenger.of(context); final sm = ScaffoldMessenger.of(context);
final user = context.read<User>(); final user = context.read<User>();
@ -111,7 +111,7 @@ class _EditRoomPermissionSetPageState extends State<EditRoomPermissionSetPage> {
'rights': permissions 'rights': permissions
}), }),
onOK: (_) { onOK: (_) {
rmaster.pop(); router.pop();
}); });
}, },
), ),

View file

@ -1,11 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:outbag_app/backend/request.dart'; import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/backend/themes.dart'; import 'package:outbag_app/backend/themes.dart';
import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/backend/user.dart';
import 'package:outbag_app/screens/settings/dialogs/password.dart'; import 'package:outbag_app/screens/settings/dialogs/password.dart';
import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:routemaster/routemaster.dart';
class SettingsPage extends StatefulWidget { class SettingsPage extends StatefulWidget {
const SettingsPage({super.key}); const SettingsPage({super.key});
@ -27,14 +27,6 @@ class _SettingsPageState extends State<SettingsPage> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('Settings'), title: const Text('Settings'),
leading: IconButton(
onPressed: () {
// go back
Navigator.of(context).pop();
},
icon: const Icon(Icons.arrow_back),
tooltip: "Go back",
),
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
child: Center( child: Center(
@ -182,7 +174,7 @@ class _SettingsPageState extends State<SettingsPage> {
// send request // send request
final scaffMgr = ScaffoldMessenger.of(ctx); final scaffMgr = ScaffoldMessenger.of(ctx);
final nav = Navigator.of(ctx); final nav = Navigator.of(ctx);
final rmaster = Routemaster.of(ctx); final router = GoRouter.of(ctx);
doNetworkRequest(scaffMgr, doNetworkRequest(scaffMgr,
req: () => postWithCreadentials( req: () => postWithCreadentials(
@ -199,7 +191,7 @@ class _SettingsPageState extends State<SettingsPage> {
// TODO: delete all rooms // TODO: delete all rooms
// go back home // go back home
rmaster.replace('/'); router.pushReplacementNamed('home');
}, },
after: () { after: () {
// close popup // close popup
@ -238,7 +230,7 @@ class _SettingsPageState extends State<SettingsPage> {
FilledButton( FilledButton(
onPressed: () async { onPressed: () async {
// send request // send request
final rmaster = Routemaster.of(ctx); final router = GoRouter.of(ctx);
// delete everything // delete everything
// delete user data (meta) // delete user data (meta)
@ -248,7 +240,7 @@ class _SettingsPageState extends State<SettingsPage> {
// TODO: delete all rooms // TODO: delete all rooms
// go back home // go back home
rmaster.replace('/'); router.pushReplacementNamed('home');
}, },
child: const Text('Log out'), child: const Text('Log out'),
) )

View file

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:outbag_app/tools/assets.dart'; import 'package:outbag_app/tools/assets.dart';
import 'package:routemaster/routemaster.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'dart:math'; import 'dart:math';
@ -63,9 +63,8 @@ class _WelcomePageState extends State<WelcomePage> {
children: <Widget>[ children: <Widget>[
SvgPicture.asset(asset("undraw/undraw_shopping_app.svg"), SvgPicture.asset(asset("undraw/undraw_shopping_app.svg"),
fit: BoxFit.contain, fit: BoxFit.contain,
width: smallest*0.5, width: smallest * 0.5,
height: smallest*0.5 height: smallest * 0.5),
),
Text( Text(
'Welcome to Outbag', 'Welcome to Outbag',
style: textTheme.displaySmall, style: textTheme.displaySmall,
@ -79,8 +78,8 @@ class _WelcomePageState extends State<WelcomePage> {
children: <Widget>[ children: <Widget>[
SvgPicture.asset(asset("undraw/undraw_mobile_login.svg"), SvgPicture.asset(asset("undraw/undraw_mobile_login.svg"),
fit: BoxFit.contain, fit: BoxFit.contain,
width: smallest*0.5, width: smallest * 0.5,
height: smallest*0.5), height: smallest * 0.5),
Text( Text(
'Open. Decentralized', 'Open. Decentralized',
style: textTheme.displaySmall, style: textTheme.displaySmall,
@ -95,8 +94,8 @@ class _WelcomePageState extends State<WelcomePage> {
children: <Widget>[ children: <Widget>[
SvgPicture.asset(asset("undraw/undraw_online_connection.svg"), SvgPicture.asset(asset("undraw/undraw_online_connection.svg"),
fit: BoxFit.contain, fit: BoxFit.contain,
width: smallest*0.5, width: smallest * 0.5,
height: smallest*0.5), height: smallest * 0.5),
Text( Text(
'Made to share', 'Made to share',
style: textTheme.displaySmall, style: textTheme.displaySmall,
@ -111,8 +110,8 @@ class _WelcomePageState extends State<WelcomePage> {
children: <Widget>[ children: <Widget>[
SvgPicture.asset(asset("undraw/undraw_online_groceries.svg"), SvgPicture.asset(asset("undraw/undraw_online_groceries.svg"),
fit: BoxFit.contain, fit: BoxFit.contain,
width: smallest*0.5, width: smallest * 0.5,
height: smallest*0.5), height: smallest * 0.5),
Text( Text(
'Pocket-sized', 'Pocket-sized',
style: textTheme.displaySmall, style: textTheme.displaySmall,
@ -125,7 +124,7 @@ class _WelcomePageState extends State<WelcomePage> {
)), )),
TextButton( TextButton(
onPressed: () { onPressed: () {
Routemaster.of(context).push("/signin"); context.goNamed('signin');
}, },
child: const Text('I already have an account'), child: const Text('I already have an account'),
) )
@ -138,7 +137,7 @@ class _WelcomePageState extends State<WelcomePage> {
onPressed: () { onPressed: () {
if (controller.page == 4 - 1) { if (controller.page == 4 - 1) {
// open signup screen // open signup screen
Routemaster.of(context).push("/signup"); context.goNamed('signup');
} else { } else {
// move to next page // move to next page
controller.nextPage( controller.nextPage(

View file

@ -152,6 +152,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
go_router:
dependency: "direct main"
description:
name: go_router
sha256: "432409518740645ce7f28802171b78783197d01149fad44f9b8ae55f40277139"
url: "https://pub.dev"
source: hosted
version: "6.5.0"
http: http:
dependency: "direct main" dependency: "direct main"
description: description:
@ -208,6 +216,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.5" version: "1.3.5"
logging:
dependency: transitive
description:
name: logging
sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@ -352,14 +368,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.5" version: "6.0.5"
routemaster:
dependency: "direct main"
description:
name: routemaster
sha256: b3b10b6ee31c741b453091e6b33323cc96631b19e4a14fc6069e9de056c7311c
url: "https://pub.dev"
source: hosted
version: "1.0.1"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter

View file

@ -30,12 +30,12 @@ environment:
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
routemaster: ^1.0.1
flutter_svg: ^2.0.4 flutter_svg: ^2.0.4
http: ^0.13.5 http: ^0.13.5
localstore: ^1.3.5 localstore: ^1.3.5
crypto: ^3.0.2 crypto: ^3.0.2
provider: ^6.0.5 provider: ^6.0.5
go_router: ^6.5.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: