From ecd87cf2cd30d6a0e3cf4a560f34bc8b24dcb096 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Fri, 24 Mar 2023 18:21:23 +0100 Subject: [PATCH] Made content scrollable Added SingleChildScrollView to new-room, edit-room and the about-room tab. NOTE: Added a padding to the new and edit room pages, to prevent widgets from touching the screen bottom --- lib/screens/room/edit.dart | 468 +++++++++++++++--------------- lib/screens/room/new.dart | 403 ++++++++++++------------- lib/screens/room/pages/about.dart | 400 ++++++++++++------------- 3 files changed, 642 insertions(+), 629 deletions(-) diff --git a/lib/screens/room/edit.dart b/lib/screens/room/edit.dart index 2b09911..a3a19d0 100644 --- a/lib/screens/room/edit.dart +++ b/lib/screens/room/edit.dart @@ -36,7 +36,7 @@ class _EditRoomPageState extends State { _ctrIcon = room.icon!; setState(() { - this.room = room; + this.room = room; }); } @@ -48,10 +48,10 @@ class _EditRoomPageState extends State { doNetworkRequest( sm, req: (user) => postWithCreadentials( - path: 'getRoomInfo', - credentials: user!, - target: (user.server), - body: {'room': widget.tag, 'server': widget.server}), + path: 'getRoomInfo', + credentials: user!, + target: (user.server), + body: {'room': widget.tag, 'server': widget.server}), onOK: (body) async { final room = Room.fromJSON(body['data']); room.toDisk(); @@ -60,15 +60,15 @@ class _EditRoomPageState extends State { // no room data available // use data from disk (() async { - try { - final diskRoom = - await Room.fromDisk(serverTag: widget.server, id: widget.tag); - initFromRoom(diskRoom); - } catch (_) { - // no room data available - // close screen - rmaster.replace('/'); - } + try { + final diskRoom = + await Room.fromDisk(serverTag: widget.server, id: widget.tag); + initFromRoom(diskRoom); + } catch (_) { + // no room data available + // close screen + rmaster.replace('/'); + } })(); return true; }, @@ -86,22 +86,22 @@ class _EditRoomPageState extends State { super.initState(); Room.listen((_) async { - // rooms changed on disk - // probably this one, - // because it is currently open - // NOTE: might be a different room - // (if a background listener is implemented at some point, - // checking if this room changed might improve performance) - try { - final room = - await Room.fromDisk(serverTag: widget.server, id: widget.tag); + // rooms changed on disk + // probably this one, + // because it is currently open + // NOTE: might be a different room + // (if a background listener is implemented at some point, + // checking if this room changed might improve performance) + try { + final room = + await Room.fromDisk(serverTag: widget.server, id: widget.tag); - initFromRoom(room); + initFromRoom(room); - setState(() { - showSpinner = false; - }); - } catch (_) {} + setState(() { + showSpinner = false; + }); + } catch (_) {} }); WidgetsBinding.instance.addPostFrameCallback((_) => fetchInfo()); @@ -110,225 +110,229 @@ class _EditRoomPageState extends State { @override Widget build(BuildContext context) { final textTheme = Theme.of(context) - .textTheme - .apply(displayColor: Theme.of(context).colorScheme.onSurface); + .textTheme + .apply(displayColor: Theme.of(context).colorScheme.onSurface); double width = MediaQuery.of(context).size.width; double height = MediaQuery.of(context).size.height; double smallest = min(min(width, height), 400); return showSpinner - ? Scaffold( - body: Center( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - Text('Loading', style: textTheme.titleLarge), - ]))) - : Scaffold( - appBar: AppBar( - title: const Text('Edit Room'), - leading: IconButton( - onPressed: () { - // go back - Navigator.of(context).pop(); - }, - icon: const Icon(Icons.arrow_back), - tooltip: "Go back", - ), - ), - body: Center( - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 400), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - IconButton( - icon: SvgPicture.asset( - _ctrIcon.img, - width: smallest * 0.3, - height: smallest * 0.3, - ), - tooltip: 'Change room icon', - onPressed: () { - showDialog( - context: context, - builder: (ctx) => AlertDialog( - title: - const Text('Choose a room Icon'), - actions: const [], - content: SizedBox( - width: smallest * 0.3 * 3, - height: smallest * 0.3 * 3, - child: GridView.count( - crossAxisCount: 3, - children: RoomIcon.list() - .map((icon) { - return GridTile( - child: IconButton( - icon: SvgPicture - .asset( - icon.img, - width: smallest * - 0.3, - height: smallest * - 0.3, - ), - tooltip: icon.text, - onPressed: () { - setState(() { - _ctrIcon = icon; - }); - Navigator.of( - context) - .pop(); - })); - }).toList())), - )); - }, + ? Scaffold( + body: Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + Text('Loading', style: textTheme.titleLarge), + ]))) + : Scaffold( + appBar: AppBar( + title: const Text('Edit Room'), + leading: IconButton( + onPressed: () { + // go back + Navigator.of(context).pop(); + }, + icon: const Icon(Icons.arrow_back), + tooltip: "Go back", + ), + ), + body: SingleChildScrollView(child: Center( + child: Padding( + padding: const EdgeInsets.all(14), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 400), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + IconButton( + icon: SvgPicture.asset( + _ctrIcon.img, + width: smallest * 0.3, + height: smallest * 0.3, ), - Padding( - padding: const EdgeInsets.all(8), - child: TextField( - enabled: false, - controller: _ctrID, - keyboardType: TextInputType.emailAddress, - decoration: const InputDecoration( - prefixIcon: Icon(Icons.fact_check), - labelText: 'Room ID', - hintText: 'Unique room id', - helperText: - 'the room id and server tag allow the room to be identified', - border: OutlineInputBorder(), - ), + tooltip: 'Change room icon', + onPressed: () { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: + const Text('Choose a room Icon'), + actions: const [], + content: SizedBox( + width: smallest * 0.3 * 3, + height: smallest * 0.3 * 3, + child: GridView.count( + crossAxisCount: 3, + children: RoomIcon.list() + .map((icon) { + return GridTile( + child: IconButton( + icon: SvgPicture + .asset( + icon.img, + width: smallest * + 0.3, + height: smallest * + 0.3, + ), + tooltip: icon.text, + onPressed: () { + setState(() { + _ctrIcon = icon; + }); + Navigator.of( + context) + .pop(); + })); + }).toList())), + )); + }, + ), + Padding( + padding: const EdgeInsets.all(8), + child: TextField( + enabled: false, + controller: _ctrID, + keyboardType: TextInputType.emailAddress, + decoration: const InputDecoration( + prefixIcon: Icon(Icons.fact_check), + labelText: 'Room ID', + hintText: 'Unique room id', + helperText: + 'the room id and server tag allow the room to be identified', + border: OutlineInputBorder(), ), ), - Padding( - padding: const EdgeInsets.all(8), - child: TextField( - controller: _ctrName, - keyboardType: TextInputType.name, - decoration: const InputDecoration( - prefixIcon: Icon(Icons.badge), - labelText: 'Room Name', - hintText: 'Give your room a name', - helperText: - 'Easily identify a room with a human readable name', - border: OutlineInputBorder(), - ), + ), + Padding( + padding: const EdgeInsets.all(8), + child: TextField( + controller: _ctrName, + keyboardType: TextInputType.name, + decoration: const InputDecoration( + prefixIcon: Icon(Icons.badge), + labelText: 'Room Name', + hintText: 'Give your room a name', + helperText: + 'Easily identify a room with a human readable name', + border: OutlineInputBorder(), ), ), - Padding( - padding: const EdgeInsets.all(8), - child: TextField( - controller: _ctrDescription, - keyboardType: TextInputType.text, - decoration: const InputDecoration( - prefixIcon: Icon(Icons.dns), - labelText: 'Room Description', - hintText: 'Briefly describe your Room', - helperText: - 'Make it easier for other to know what this room is used for', - border: OutlineInputBorder(), - ), + ), + Padding( + padding: const EdgeInsets.all(8), + child: TextField( + controller: _ctrDescription, + keyboardType: TextInputType.text, + decoration: const InputDecoration( + prefixIcon: Icon(Icons.dns), + labelText: 'Room Description', + hintText: 'Briefly describe your Room', + helperText: + 'Make it easier for other to know what this room is used for', + border: OutlineInputBorder(), ), ), - ], - ) + ), + ], ) - ), - floatingActionButton: FloatingActionButton.extended( - onPressed: () async { - final scaffMgr = ScaffoldMessenger.of(context); - final nav = Navigator.of(context); + ) + ) + ) + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () async { + final scaffMgr = ScaffoldMessenger.of(context); + final nav = Navigator.of(context); - // name may not be empty - if (_ctrName.text.isEmpty) { - final snackBar = SnackBar( - behavior: SnackBarBehavior.floating, - content: const Text('Please specify a room name'), - action: SnackBarAction( - label: 'Ok', - onPressed: () { - scaffMgr.hideCurrentSnackBar(); - }, - ), - ); - - scaffMgr.hideCurrentSnackBar(); - scaffMgr.showSnackBar(snackBar); - - return; - } - - User user; - try { - user = await User.fromDisk(); - } catch (_) { - // user data invalid - // shouldn't happen - return; - } - - Room clone = room!; - clone.name = _ctrName.text; - clone.description = _ctrDescription.text; - clone.icon = _ctrIcon; - - try { - final resp = await postWithCreadentials( - target: user.server, - credentials: user, - path: 'changeRoomMeta', - body: { - 'room': clone.id, - 'server': clone.serverTag, - 'title': clone.name, - 'description': clone.description, - 'icon': clone.icon?.type, - }); - if (resp.res == Result.ok) { - // room was created - // save room - await clone.toDisk(); - nav.pop(); - } else { - // error - final snackBar = SnackBar( - behavior: SnackBarBehavior.floating, - content: Text(errorAsString(resp.body)), - action: SnackBarAction( - label: 'Dismiss', - onPressed: () { - scaffMgr.hideCurrentSnackBar(); - }, - ), - ); - - scaffMgr.hideCurrentSnackBar(); - scaffMgr.showSnackBar(snackBar); - } - } catch (_) { - final snackBar = SnackBar( - behavior: SnackBarBehavior.floating, - content: const Text('Network error'), - action: SnackBarAction( - label: 'Dismiss', - onPressed: () { - scaffMgr.hideCurrentSnackBar(); - }, - ), - ); - - scaffMgr.hideCurrentSnackBar(); - scaffMgr.showSnackBar(snackBar); - } + // name may not be empty + if (_ctrName.text.isEmpty) { + final snackBar = SnackBar( + behavior: SnackBarBehavior.floating, + content: const Text('Please specify a room name'), + action: SnackBarAction( + label: 'Ok', + onPressed: () { + scaffMgr.hideCurrentSnackBar(); }, - label: const Text('Update'), - icon: const Icon(Icons.edit)), - ); + ), + ); + + scaffMgr.hideCurrentSnackBar(); + scaffMgr.showSnackBar(snackBar); + + return; + } + + User user; + try { + user = await User.fromDisk(); + } catch (_) { + // user data invalid + // shouldn't happen + return; + } + + Room clone = room!; + clone.name = _ctrName.text; + clone.description = _ctrDescription.text; + clone.icon = _ctrIcon; + + try { + final resp = await postWithCreadentials( + target: user.server, + credentials: user, + path: 'changeRoomMeta', + body: { + 'room': clone.id, + 'server': clone.serverTag, + 'title': clone.name, + 'description': clone.description, + 'icon': clone.icon?.type, + }); + if (resp.res == Result.ok) { + // room was created + // save room + await clone.toDisk(); + nav.pop(); + } else { + // error + final snackBar = SnackBar( + behavior: SnackBarBehavior.floating, + content: Text(errorAsString(resp.body)), + action: SnackBarAction( + label: 'Dismiss', + onPressed: () { + scaffMgr.hideCurrentSnackBar(); + }, + ), + ); + + scaffMgr.hideCurrentSnackBar(); + scaffMgr.showSnackBar(snackBar); + } + } catch (_) { + final snackBar = SnackBar( + behavior: SnackBarBehavior.floating, + content: const Text('Network error'), + action: SnackBarAction( + label: 'Dismiss', + onPressed: () { + scaffMgr.hideCurrentSnackBar(); + }, + ), + ); + + scaffMgr.hideCurrentSnackBar(); + scaffMgr.showSnackBar(snackBar); + } + }, + label: const Text('Update'), + icon: const Icon(Icons.edit)), + ); } } diff --git a/lib/screens/room/new.dart b/lib/screens/room/new.dart index e01ecd1..f1d9313 100644 --- a/lib/screens/room/new.dart +++ b/lib/screens/room/new.dart @@ -27,225 +27,230 @@ class _NewRoomPageState extends State { @override Widget build(BuildContext context) { final textTheme = Theme.of(context) - .textTheme - .apply(displayColor: Theme.of(context).colorScheme.onSurface); + .textTheme + .apply(displayColor: Theme.of(context).colorScheme.onSurface); double width = MediaQuery.of(context).size.width; double height = MediaQuery.of(context).size.height; double smallest = min(min(width, height), 400); return showSpinner - ? Scaffold( - body: Center( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - Text('Loading', style: textTheme.titleLarge), - ]))) - : Scaffold( - appBar: AppBar( - 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: Center( - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 400), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - IconButton( - icon: SvgPicture.asset( - _ctrIcon.img, - width: smallest * 0.3, - height: smallest * 0.3, - ), - tooltip: 'Change room icon', - onPressed: () { - showDialog( - context: context, - builder: (ctx) => AlertDialog( - title: - const Text('Choose a room Icon'), - actions: const [], - content: SizedBox( - width: smallest * 0.3 * 3, - height: smallest * 0.3 * 3, - child: GridView.count( - crossAxisCount: 3, - children: RoomIcon.list() - .map((icon) { - return GridTile( - child: IconButton( - icon: SvgPicture - .asset( - icon.img, - width: smallest * - 0.3, - height: smallest * - 0.3, - ), - tooltip: icon.text, - onPressed: () { - setState(() { - _ctrIcon = icon; - }); - Navigator.of( - context) - .pop(); - })); - }).toList())), - )); - }, + ? Scaffold( + body: Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + Text('Loading', style: textTheme.titleLarge), + ]))) + : Scaffold( + appBar: AppBar( + 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( + child: Center( + child: Padding( + padding: const EdgeInsets.all(14), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 400), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + IconButton( + icon: SvgPicture.asset( + _ctrIcon.img, + width: smallest * 0.3, + height: smallest * 0.3, ), - Padding( - padding: const EdgeInsets.all(8), - child: TextField( - controller: _ctrID, - keyboardType: TextInputType.emailAddress, - decoration: const InputDecoration( - prefixIcon: Icon(Icons.fact_check), - labelText: 'Room ID', - hintText: 'Unique room id', - helperText: - 'the room id and server tag allow the room to be identified', - border: OutlineInputBorder(), - ), + tooltip: 'Change room icon', + onPressed: () { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: + const Text('Choose a room Icon'), + actions: const [], + content: SizedBox( + width: smallest * 0.3 * 3, + height: smallest * 0.3 * 3, + child: GridView.count( + crossAxisCount: 3, + children: RoomIcon.list() + .map((icon) { + return GridTile( + child: IconButton( + icon: SvgPicture + .asset( + icon.img, + width: smallest * + 0.3, + height: smallest * + 0.3, + ), + tooltip: icon.text, + onPressed: () { + setState(() { + _ctrIcon = icon; + }); + Navigator.of( + context) + .pop(); + })); + }).toList())), + )); + }, + ), + Padding( + padding: const EdgeInsets.all(8), + child: TextField( + controller: _ctrID, + keyboardType: TextInputType.emailAddress, + decoration: const InputDecoration( + prefixIcon: Icon(Icons.fact_check), + labelText: 'Room ID', + hintText: 'Unique room id', + helperText: + 'the room id and server tag allow the room to be identified', + border: OutlineInputBorder(), ), ), - Padding( - padding: const EdgeInsets.all(8), - child: TextField( - controller: _ctrName, - keyboardType: TextInputType.name, - decoration: const InputDecoration( - prefixIcon: Icon(Icons.badge), - labelText: 'Room Name', - hintText: 'Give your room a name', - helperText: - 'Easily identify a room with a human readable name', - border: OutlineInputBorder(), - ), + ), + Padding( + padding: const EdgeInsets.all(8), + child: TextField( + controller: _ctrName, + keyboardType: TextInputType.name, + decoration: const InputDecoration( + prefixIcon: Icon(Icons.badge), + labelText: 'Room Name', + hintText: 'Give your room a name', + helperText: + 'Easily identify a room with a human readable name', + border: OutlineInputBorder(), ), ), - Padding( - padding: const EdgeInsets.all(8), - child: TextField( - controller: _ctrDescription, - keyboardType: TextInputType.text, - decoration: const InputDecoration( - prefixIcon: Icon(Icons.dns), - labelText: 'Room Description', - hintText: 'Briefly describe your Room', - helperText: - 'Make it easier for other to know what this room is used for', - border: OutlineInputBorder(), - ), + ), + Padding( + padding: const EdgeInsets.all(8), + child: TextField( + controller: _ctrDescription, + keyboardType: TextInputType.text, + decoration: const InputDecoration( + prefixIcon: Icon(Icons.dns), + labelText: 'Room Description', + hintText: 'Briefly describe your Room', + helperText: + 'Make it easier for other to know what this room is used for', + border: OutlineInputBorder(), ), ), - Text('Visibility', style: textTheme.labelLarge), - Text('Specify who has access to your room', - style: textTheme.bodySmall), - SegmentedButton( - showSelectedIcon: true, - multiSelectionEnabled: false, - emptySelectionAllowed: false, - segments: RoomVisibility.list().map((vis) { - return ButtonSegment( - value: vis, - label: Text(vis.text), - icon: Icon(vis.icon)); - }).toList(), - onSelectionChanged: ((vset) { - setState(() { - _ctrVis = vset.single; - }); - }), - selected: {_ctrVis}, - selectedIcon: Icon(_ctrVis.icon), - ), - ], - ) + ), + Text('Visibility', style: textTheme.labelLarge), + Text('Specify who has access to your room', + style: textTheme.bodySmall), + SegmentedButton( + showSelectedIcon: true, + multiSelectionEnabled: false, + emptySelectionAllowed: false, + segments: RoomVisibility.list().map((vis) { + return ButtonSegment( + value: vis, + label: Text(vis.text), + icon: Icon(vis.icon)); + }).toList(), + onSelectionChanged: ((vset) { + setState(() { + _ctrVis = vset.single; + }); + }), + selected: {_ctrVis}, + selectedIcon: Icon(_ctrVis.icon), + ), + ], ) - ), - floatingActionButton: FloatingActionButton.extended( - onPressed: () async { - final scaffMgr = ScaffoldMessenger.of(context); - final rmaster = Routemaster.of(context); + ) + ) + ) + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () async { + final scaffMgr = ScaffoldMessenger.of(context); + final rmaster = Routemaster.of(context); - // ID should be at least three characters long - if (_ctrID.text.length < 3) { - showSimpleSnackbar(scaffMgr, - text: _ctrID.text.isEmpty - ? 'Please specify a Room ID' - : 'Room ID has to be at least three characters long', - action: 'OK'); + // ID should be at least three characters long + if (_ctrID.text.length < 3) { + showSimpleSnackbar(scaffMgr, + text: _ctrID.text.isEmpty + ? 'Please specify a Room ID' + : 'Room ID has to be at least three characters long', + action: 'OK'); - return; - } + return; + } - // name may not be empty - if (_ctrName.text.isEmpty) { - showSimpleSnackbar( - scaffMgr, - text: 'Please specify a room name', - action: 'OK' - ); + // name may not be empty + if (_ctrName.text.isEmpty) { + showSimpleSnackbar( + scaffMgr, + text: 'Please specify a room name', + action: 'OK' + ); - return; - } + return; + } - User user; - try { - user = await User.fromDisk(); - } catch (_) { - // user data invalid - // shouldn't happen - return; - } + User user; + try { + user = await User.fromDisk(); + } catch (_) { + // user data invalid + // shouldn't happen + return; + } - final room = Room( - id: _ctrID.text, - serverTag: user.server.tag, - name: _ctrName.text, - description: _ctrDescription.text, - icon: _ctrIcon, - visibility: _ctrVis); + final room = Room( + id: _ctrID.text, + serverTag: user.server.tag, + name: _ctrName.text, + description: _ctrDescription.text, + icon: _ctrIcon, + visibility: _ctrVis); - doNetworkRequest(scaffMgr, - req: (_) => postWithCreadentials( - target: user.server, - credentials: user, - path: 'createRoom', - body: { - 'room': room.id, - 'title': room.name, - 'description': room.description, - 'icon': room.icon?.type, - 'visibility': room.visibility?.type - }), - onOK: (_) async { - // room was created - // save room - await room.toDisk(); - // move to home page - rmaster.replace('/'); - }, - // we manually fetch the user data above - // because we need the serverTag - needUser: false); - }, - label: const Text('Create'), - icon: const Icon(Icons.add)), - ); + doNetworkRequest(scaffMgr, + req: (_) => postWithCreadentials( + target: user.server, + credentials: user, + path: 'createRoom', + body: { + 'room': room.id, + 'title': room.name, + 'description': room.description, + 'icon': room.icon?.type, + 'visibility': room.visibility?.type + }), + onOK: (_) async { + // room was created + // save room + await room.toDisk(); + // move to home page + rmaster.replace('/'); + }, + // we manually fetch the user data above + // because we need the serverTag + needUser: false); + }, + label: const Text('Create'), + icon: const Icon(Icons.add)), + ); } } diff --git a/lib/screens/room/pages/about.dart b/lib/screens/room/pages/about.dart index 50c96db..ef319b2 100644 --- a/lib/screens/room/pages/about.dart +++ b/lib/screens/room/pages/about.dart @@ -21,18 +21,19 @@ class _AboutRoomPageState extends State { @override Widget build(BuildContext context) { final textTheme = Theme.of(context) - .textTheme - .apply(displayColor: Theme.of(context).colorScheme.onSurface); + .textTheme + .apply(displayColor: Theme.of(context).colorScheme.onSurface); double width = MediaQuery.of(context).size.width; double height = MediaQuery.of(context).size.height; double smallest = min(width, height); - return Center( + return SingleChildScrollView( + child:Center( child: Column(children: [ - // room meta display - ...(widget.room != null) - ? [ + // room meta display + ...(widget.room != null) + ? [ Padding( padding: const EdgeInsets.all(14), child: Column( @@ -51,29 +52,29 @@ class _AboutRoomPageState extends State { style: textTheme.bodySmall, ), Text(widget.room?.description ?? '', - style: textTheme.bodyMedium), + style: textTheme.bodyMedium), Padding( - padding: const EdgeInsets.all(8), - child: SegmentedButton( - showSelectedIcon: true, - multiSelectionEnabled: false, - emptySelectionAllowed: false, - segments: RoomVisibility.list().map((vis) { + padding: const EdgeInsets.all(8), + child: SegmentedButton( + showSelectedIcon: true, + multiSelectionEnabled: false, + emptySelectionAllowed: false, + segments: RoomVisibility.list().map((vis) { return ButtonSegment( - value: vis.type, - label: Text(vis.text), - icon: Icon(vis.icon)); - }).toList(), - onSelectionChanged: ((vset) { + value: vis.type, + label: Text(vis.text), + icon: Icon(vis.icon)); + }).toList(), + onSelectionChanged: ((vset) { // check permission // only show confirm dialog when user // is admin, owner or has CHANGE_ADMIN permission if (widget.info == null || - (!(widget.info?.isAdmin ?? false) && - !(widget.info?.isOwner ?? false) && - ((widget.info?.permissions)! & - RoomPermission.ota == - 0))) { + (!(widget.info?.isAdmin ?? false) && + !(widget.info?.isOwner ?? false) && + ((widget.info?.permissions)! & + RoomPermission.ota == + 0))) { // action not permitted // NOTE: no error dialog should be shown // because the action is supposed to be hidden @@ -82,73 +83,73 @@ class _AboutRoomPageState extends State { final vis = RoomVisibility(vset.first); showDialog( - context: context, - builder: (ctx) => AlertDialog( - title: - const Text('Change room visibility'), - content: Text( - 'Do you really want to change the room visibility to: ${vis.text}'), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('Cancel'), - ), - FilledButton( - onPressed: () async { - final scaffMgr = - ScaffoldMessenger.of(context); - final nav = Navigator.of(context); + context: context, + builder: (ctx) => AlertDialog( + title: + const Text('Change room visibility'), + content: Text( + 'Do you really want to change the room visibility to: ${vis.text}'), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Cancel'), + ), + FilledButton( + onPressed: () async { + final scaffMgr = + ScaffoldMessenger.of(context); + final nav = Navigator.of(context); - doNetworkRequest(scaffMgr, - req: (user) => - postWithCreadentials( - path: 'setVisibility', - target: (user?.server)!, - body: { - 'room': - widget.room?.id, - 'server': (widget.room - ?.serverTag)!, - 'visibility': - vset.first - }, - credentials: user!), - onOK: (_) { - Room r = widget.room!; - r.visibility = vis; - r.toDisk(); - }, - after: () { - nav.pop(); - }); + doNetworkRequest(scaffMgr, + req: (user) => + postWithCreadentials( + path: 'setVisibility', + target: (user?.server)!, + body: { + 'room': + widget.room?.id, + 'server': (widget.room + ?.serverTag)!, + 'visibility': + vset.first }, - child: const Text('Ok'), - ) - ], - )); - }), - selected: {(widget.room?.visibility?.type)!}, - selectedIcon: Icon((widget.room?.visibility?.icon)!), - )), + credentials: user!), + onOK: (_) { + Room r = widget.room!; + r.visibility = vis; + r.toDisk(); + }, + after: () { + nav.pop(); + }); + }, + child: const Text('Ok'), + ) + ], + )); + }), + selected: {(widget.room?.visibility?.type)!}, + selectedIcon: Icon((widget.room?.visibility?.icon)!), + )), ], ), ) ] - : [], + : [], - Padding( - padding: const EdgeInsets.all(14), - child: Column( - children: [ - // edit room meta button - ...(widget.info != null && - ((widget.info?.isAdmin ?? false) || - (widget.info?.isOwner ?? false) || - ((widget.info?.permissions)! & - RoomPermission.changeMeta != - 0))) + Padding( + padding: const EdgeInsets.all(14), + child: Column( + children: [ + // edit room meta button + ...(widget.info != null && + ((widget.info?.isAdmin ?? false) || + (widget.info?.isOwner ?? false) || + ((widget.info?.permissions)! & + RoomPermission.changeMeta != + 0))) ? [ ListTile( trailing: const Icon(Icons.chevron_right), @@ -160,123 +161,126 @@ class _AboutRoomPageState extends State { Routemaster.of(context).push( '/r/${widget.room?.serverTag}/${widget.room?.id}/edit'); }, - ), - ] + ), + ] : [], - // open members view - ListTile( - trailing: const Icon(Icons.chevron_right), - title: const Text('Members'), - subtitle: const Text('Show Member list'), - onTap: () { - // open member view screen - Routemaster.of(context).push( - '/r/${widget.room?.serverTag}/${widget.room?.id}/members'); - }, - ), - ...(widget.info != null && - ((widget.info?.isAdmin ?? false) || - (widget.info?.isOwner ?? false) || - ((widget.info?.permissions)! & RoomPermission.ota != - 0))) - ? [ - ListTile( - trailing: const Icon(Icons.chevron_right), - title: const Text('OTA'), - subtitle: const Text('Add and delete OTAs'), - onTap: () { - // show manage ota screen - Routemaster.of(context).push( - '/r/${widget.room?.serverTag}/${widget.room?.id}/ota'); - }, - ), - ListTile( - trailing: const Icon(Icons.chevron_right), - title: const Text('Invites'), - subtitle: const Text('Invite people to this room'), - onTap: () { - // show manage ota screen - Routemaster.of(context).push( - '/r/${widget.room?.serverTag}/${widget.room?.id}/invite'); - }, - ), - ] - : [], - ], - )), - - ...(widget.info != null) - ? [ - Padding( - padding: const EdgeInsets.all(8), - child: FilledButton.tonal( - child: Text(((widget.info?.isOwner)!) - ? 'Delete Room' - : 'Leave Room'), - onPressed: () { - // show confirm dialog - showDialog( - context: context, - builder: (ctx) => AlertDialog( - title: Text(((widget.info?.isOwner)!) - ? 'Delete Room' - : 'Leave Room'), - content: Text( - 'Do you really want to ${((widget.info?.isOwner)!) ? "delete" : "leave"} the room?'), - actions: [ - TextButton( - onPressed: () { - // close popup - Navigator.of(ctx).pop(); - }, - child: const Text('Cancel'), - ), - FilledButton( - onPressed: () async { - // send request - final scaffMgr = - ScaffoldMessenger.of(ctx); - final nav = Navigator.of(ctx); - final rmaster = Routemaster.of(ctx); - - doNetworkRequest( - scaffMgr, - req: (user)=>postWithCreadentials( - path: ((widget.info?.isOwner)!) - ? 'deleteRoom' - : 'leaveRoom', - target: (user?.server)!, - body: { - 'room': widget.room?.id, - 'server': - (widget.room?.serverTag)!, - }, - credentials: user!), - onOK: (_) async { - // try delete room from disk - try { - await widget.room?.removeDisk(); - } catch (_) {} - - // go back home - rmaster.replace('/'); - }, - after: () { - // close popup - nav.pop(); - } - ); - }, - child: Text(((widget.info?.isOwner)!) - ? 'Delete' - : 'Leave'), - ) - ], - )); + // open members view + ListTile( + trailing: const Icon(Icons.chevron_right), + title: const Text('Members'), + subtitle: const Text('Show Member list'), + onTap: () { + // open member view screen + Routemaster.of(context).push( + '/r/${widget.room?.serverTag}/${widget.room?.id}/members'); }, - )) + ), + ...(widget.info != null && + ((widget.info?.isAdmin ?? false) || + (widget.info?.isOwner ?? false) || + ((widget.info?.permissions)! & RoomPermission.ota != + 0))) + ? [ + ListTile( + trailing: const Icon(Icons.chevron_right), + title: const Text('OTA'), + subtitle: const Text('Add and delete OTAs'), + onTap: () { + // show manage ota screen + Routemaster.of(context).push( + '/r/${widget.room?.serverTag}/${widget.room?.id}/ota'); + }, + ), + ListTile( + trailing: const Icon(Icons.chevron_right), + title: const Text('Invites'), + subtitle: const Text('Invite people to this room'), + onTap: () { + // show manage ota screen + Routemaster.of(context).push( + '/r/${widget.room?.serverTag}/${widget.room?.id}/invite'); + }, + ), + ] + : [], + ], + )), + + ...(widget.info != null) + ? [ + Padding( + padding: const EdgeInsets.all(8), + child: FilledButton.tonal( + child: Text(((widget.info?.isOwner)!) + ? 'Delete Room' + : 'Leave Room'), + onPressed: () { + // show confirm dialog + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: Text(((widget.info?.isOwner)!) + ? 'Delete Room' + : 'Leave Room'), + content: Text( + 'Do you really want to ${((widget.info?.isOwner)!) ? "delete" : "leave"} the room?'), + actions: [ + TextButton( + onPressed: () { + // close popup + Navigator.of(ctx).pop(); + }, + child: const Text('Cancel'), + ), + FilledButton( + onPressed: () async { + // send request + final scaffMgr = + ScaffoldMessenger.of(ctx); + final nav = Navigator.of(ctx); + final rmaster = Routemaster.of(ctx); + + doNetworkRequest( + scaffMgr, + req: (user)=>postWithCreadentials( + path: ((widget.info?.isOwner)!) + ? 'deleteRoom' + : 'leaveRoom', + target: (user?.server)!, + body: { + 'room': widget.room?.id, + 'server': + (widget.room?.serverTag)!, + }, + credentials: user!), + onOK: (_) async { + // try delete room from disk + try { + await widget.room?.removeDisk(); + } catch (_) {} + + // go back home + rmaster.replace('/'); + }, + after: () { + // close popup + nav.pop(); + } + ); + }, + child: Text(((widget.info?.isOwner)!) + ? 'Delete' + : 'Leave'), + ) + ], + )); + }, + )) ] - : [], - ])); + : [], + ] + ) + ) + ); } }