diff --git a/lib/backend/request.dart b/lib/backend/request.dart index faf76e5..cbb7ffc 100644 --- a/lib/backend/request.dart +++ b/lib/backend/request.dart @@ -3,10 +3,8 @@ import 'dart:convert'; import './resolve_url.dart'; import './user.dart'; -enum Result { - ok, - err -} +enum Result { ok, err } + class Response { final Map body; final Result res; @@ -22,7 +20,8 @@ Future usePostApi( final resp = await http.post(Uri.parse('${target.base}api/$path'), headers: headers, body: jsonEncode({'data': body})); final json = jsonDecode(resp.body); - return Response(body: json, res: resp.statusCode==200?Result.ok:Result.err); + return Response( + body: json, res: resp.statusCode == 200 ? Result.ok : Result.err); } Future postWithCreadentials( diff --git a/lib/main.dart b/lib/main.dart index 9c207a3..4cb3884 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:outbag_app/backend/user.dart'; +import 'package:outbag_app/screens/room/join.dart'; import 'package:outbag_app/screens/room/new.dart'; import './screens/home.dart'; import './screens/welcome.dart'; @@ -20,7 +21,8 @@ final routesUnauthorized = RouteMap(routes: { // routes when user is logged in final routesLoggedIn = RouteMap(routes: { '/': (_) => const MaterialPage(child: HomePage()), - '/new': (_) => const MaterialPage(child: NewRoomPage()), + '/new-room': (_) => const MaterialPage(child: NewRoomPage()), + '/add-room': (_) => const MaterialPage(child: JoinRoomPage()), '/r/:server/:tag/:page?': (info) => MaterialPage( child: RoomPage(info.pathParameters['server'] ?? "", info.pathParameters['tag'] ?? "", diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 38ed29d..a7d3251 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -147,13 +147,13 @@ class _HomePageState extends State { }, ), floatingActionButton: FloatingActionButton.extended( - label: const Text('New'), + label: const Text('Add Room'), icon: const Icon(Icons.add), onPressed: () { // create new room - Routemaster.of(context).push("/new"); + Routemaster.of(context).push("/add-room"); }, - tooltip: 'Create Room', + tooltip: 'Add new Room', ), ); } diff --git a/lib/screens/room/join.dart b/lib/screens/room/join.dart new file mode 100644 index 0000000..2e01c1f --- /dev/null +++ b/lib/screens/room/join.dart @@ -0,0 +1,108 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:outbag_app/backend/request.dart'; +import 'package:outbag_app/backend/room.dart'; +import 'package:outbag_app/backend/user.dart'; +import 'package:routemaster/routemaster.dart'; + +class JoinRoomPage extends StatefulWidget { + const JoinRoomPage({super.key}); + + @override + State createState() => _JoinRoomPageState(); +} + +class _JoinRoomPageState extends State { + List rooms = []; + + @override + void initState() { + super.initState(); + (() async { + User user; + try { + user = await User.fromDisk(); + } catch (_) { + return; + } + + try { + final resp = await postWithCreadentials( + path: 'listPublicRooms', + credentials: user, + target: user.server, + body: {}); + if (resp.res == Result.ok) { + // parse rooms + final List list = resp.body['data'].map((json) { + return Room.fromJSON(json); + }).toList(); + setState(() { + rooms = list; + }); + } else { + throw Error(); + } + } catch (_) { + // network error + // unable to load room list + // NOTE: might want to show snackbar + // with warning + } + })(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Join Room'), + leading: IconButton( + onPressed: () { + // go back + Routemaster.of(context).history.back(); + }, + icon: const Icon(Icons.arrow_back), + tooltip: "Go back", + ), + ), + body: ListView.builder( + itemCount: rooms.length, + itemBuilder: (ctx, i) { + final room = rooms[i]; + return Card( + margin: const EdgeInsets.all(8.0), + clipBehavior: Clip.antiAliasWithSaveLayer, + semanticContainer: true, + child: InkWell( + onTap: () { + // TODO: show modalBottomSheet + // with room information + // and join button + }, + child: Container( + padding: const EdgeInsets.fromLTRB(10, 5, 5, 10), + child: ListTile( + title: Text(room.name), + visualDensity: const VisualDensity(vertical: 3), + subtitle: Text(room.description), + leading: AspectRatio( + aspectRatio: 1 / 1, + child: SvgPicture.asset("${room.icon?.img}"), + ), + hoverColor: Colors.transparent, + )))); + }, + ), + floatingActionButton: FloatingActionButton.extended( + label: const Text('New'), + icon: const Icon(Icons.add), + onPressed: () { + // create new room + Routemaster.of(context).push("/new-room"); + }, + tooltip: 'Create Room', + ), + ); + } +}