13c071b8ca
Because there currently is no way to auto-refresh the lists it will appear as if nothing changed. Switching to a different tab and back again will update the list though
415 lines
25 KiB
Dart
415 lines
25 KiB
Dart
import 'package:flutter/material.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/request.dart';
|
|
import 'package:outbag_app/backend/room.dart';
|
|
import 'package:outbag_app/backend/user.dart';
|
|
import 'dart:math';
|
|
import 'package:outbag_app/tools/fetch_wrapper.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|
|
|
class AboutRoomPage extends StatefulWidget {
|
|
final RoomInfo? info;
|
|
final Room? room;
|
|
|
|
const AboutRoomPage(this.room, this.info, {super.key});
|
|
|
|
@override
|
|
State<StatefulWidget> createState() => _AboutRoomPageState();
|
|
}
|
|
|
|
class _AboutRoomPageState extends State<AboutRoomPage> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final textTheme = Theme.of(context)
|
|
.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 SingleChildScrollView(
|
|
child: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(14),
|
|
child: ConstrainedBox(
|
|
constraints: const BoxConstraints(maxWidth: 600),
|
|
child: Column(children: [
|
|
// room meta display
|
|
...(widget.room != null)
|
|
? [
|
|
Padding(
|
|
padding: const EdgeInsets.all(14),
|
|
child: Column(
|
|
children: [
|
|
SvgPicture.asset(
|
|
(widget.room?.icon?.img)!,
|
|
width: smallest * 0.2,
|
|
height: smallest * 0.2,
|
|
),
|
|
Text(
|
|
widget.room?.name ?? '',
|
|
style: textTheme.displayMedium,
|
|
),
|
|
Text(
|
|
'${widget.room?.id}@${widget.room?.serverTag}',
|
|
style: textTheme.bodySmall,
|
|
),
|
|
Text(
|
|
widget.room?.description ?? '',
|
|
style: textTheme.bodyMedium,
|
|
textAlign: TextAlign.center,
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(8),
|
|
child: SegmentedButton<int>(
|
|
showSelectedIcon: true,
|
|
multiSelectionEnabled: false,
|
|
emptySelectionAllowed: false,
|
|
segments:
|
|
RoomVisibility.list().map((vis) {
|
|
return ButtonSegment<int>(
|
|
value: vis.type,
|
|
label: Text(vis.text(context)),
|
|
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))) {
|
|
// action not permitted
|
|
// NOTE: no error dialog should be shown
|
|
// because the action is supposed to be hidden
|
|
return;
|
|
}
|
|
|
|
final vis =
|
|
RoomVisibility(vset.first);
|
|
showDialog(
|
|
context: context,
|
|
builder: (ctx) => AlertDialog(
|
|
title: Text(AppLocalizations
|
|
.of(context)!
|
|
.changeRoomVisibilityTitle),
|
|
content: Text(AppLocalizations
|
|
.of(context)!
|
|
.changeRoomVisibilitySubtitle(
|
|
vis.text(
|
|
context))),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () {
|
|
context.pop();
|
|
},
|
|
child: Text(
|
|
AppLocalizations.of(
|
|
context)!
|
|
.cancel),
|
|
),
|
|
FilledButton(
|
|
onPressed: () async {
|
|
final scaffMgr =
|
|
ScaffoldMessenger
|
|
.of(context);
|
|
final nav =
|
|
Navigator.of(
|
|
context);
|
|
final user = context
|
|
.read<User>();
|
|
|
|
doNetworkRequest(
|
|
scaffMgr,
|
|
req: () =>
|
|
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();
|
|
});
|
|
},
|
|
child: Text(
|
|
AppLocalizations.of(
|
|
context)!
|
|
.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)))
|
|
? [
|
|
ListTile(
|
|
trailing:
|
|
const Icon(Icons.chevron_right),
|
|
title: Text(
|
|
AppLocalizations.of(context)!
|
|
.editRoomMetadata),
|
|
subtitle: Text(
|
|
AppLocalizations.of(context)!
|
|
.editRoomMetadataSubtitle),
|
|
onTap: () {
|
|
// show edit room screen
|
|
context.goNamed('edit-room', params: {
|
|
'server': (widget.room?.serverTag)!,
|
|
'id': (widget.room?.id)!
|
|
});
|
|
},
|
|
),
|
|
]
|
|
: [],
|
|
// open members view
|
|
ListTile(
|
|
trailing: const Icon(Icons.chevron_right),
|
|
title: Text(AppLocalizations.of(context)!
|
|
.showRoomMembers),
|
|
subtitle: Text(AppLocalizations.of(context)!
|
|
.showRoomMembersSubtitle),
|
|
onTap: () {
|
|
// open member view screen
|
|
context.goNamed('room-members', params: {
|
|
'server': (widget.room?.serverTag)!,
|
|
'id': (widget.room?.id)!
|
|
});
|
|
},
|
|
),
|
|
// edit default member permission
|
|
...(widget.info != null &&
|
|
((widget.info?.isAdmin ?? false) ||
|
|
(widget.info?.isOwner ?? false) ||
|
|
((widget.info?.permissions)! &
|
|
RoomPermission.changeAdmin !=
|
|
0)))
|
|
? [
|
|
ListTile(
|
|
trailing:
|
|
const Icon(Icons.chevron_right),
|
|
title: Text(
|
|
AppLocalizations.of(context)!
|
|
.editRoomPermissions),
|
|
subtitle: Text(
|
|
AppLocalizations.of(context)!
|
|
.editRoomPermissionsSubtitle),
|
|
onTap: () {
|
|
// show checkbox screen
|
|
context.goNamed('room-permissions',
|
|
params: {
|
|
'server':
|
|
(widget.room?.serverTag)!,
|
|
'id': (widget.room?.id)!
|
|
});
|
|
},
|
|
),
|
|
]
|
|
: [],
|
|
...(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: Text(
|
|
AppLocalizations.of(context)!
|
|
.manageRoomOTA),
|
|
subtitle: Text(
|
|
AppLocalizations.of(context)!
|
|
.manageRoomOTASubtitle),
|
|
onTap: () {
|
|
// show manage ota screen
|
|
context.goNamed('room-ota', params: {
|
|
'server': (widget.room?.serverTag)!,
|
|
'id': (widget.room?.id)!
|
|
});
|
|
},
|
|
),
|
|
ListTile(
|
|
trailing:
|
|
const Icon(Icons.chevron_right),
|
|
title: Text(
|
|
AppLocalizations.of(context)!
|
|
.manageRoomInvites),
|
|
subtitle: Text(
|
|
AppLocalizations.of(context)!
|
|
.manageRoomInvitesSubtitle),
|
|
onTap: () {
|
|
// show manage ota screen
|
|
context
|
|
.goNamed('room-invite', params: {
|
|
'server': (widget.room?.serverTag)!,
|
|
'id': (widget.room?.id)!
|
|
});
|
|
},
|
|
),
|
|
]
|
|
: [],
|
|
],
|
|
)),
|
|
|
|
...(widget.info != null)
|
|
? [
|
|
Padding(
|
|
padding: const EdgeInsets.all(8),
|
|
child: FilledButton.tonal(
|
|
child: Text(((widget.info?.isOwner)!)
|
|
? AppLocalizations.of(context)!
|
|
.deleteRoom
|
|
: AppLocalizations.of(context)!
|
|
.leaveRoom),
|
|
onPressed: () {
|
|
// show confirm dialog
|
|
showDialog(
|
|
context: context,
|
|
builder: (ctx) => AlertDialog(
|
|
title: Text(
|
|
((widget.info?.isOwner)!)
|
|
? AppLocalizations.of(
|
|
context)!
|
|
.deleteRoom
|
|
: AppLocalizations.of(
|
|
context)!
|
|
.leaveRoom),
|
|
content: Text(
|
|
((widget.info?.isOwner)!)
|
|
? AppLocalizations.of(
|
|
context)!
|
|
.deleteRoomConfirm
|
|
: AppLocalizations.of(
|
|
context)!
|
|
.leaveRoomConfirm),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () {
|
|
// close popup
|
|
Navigator.of(ctx).pop();
|
|
},
|
|
child: Text(
|
|
AppLocalizations.of(
|
|
context)!
|
|
.cancel),
|
|
),
|
|
FilledButton(
|
|
onPressed: () async {
|
|
// send request
|
|
final scaffMgr =
|
|
ScaffoldMessenger.of(
|
|
ctx);
|
|
final nav =
|
|
Navigator.of(ctx);
|
|
final router =
|
|
GoRouter.of(context);
|
|
final user =
|
|
context.read<User>();
|
|
|
|
doNetworkRequest(scaffMgr,
|
|
req: () =>
|
|
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
|
|
router
|
|
.pushReplacementNamed(
|
|
'home');
|
|
},
|
|
after: () {
|
|
// close popup
|
|
nav.pop();
|
|
});
|
|
},
|
|
child: Text(((widget
|
|
.info?.isOwner)!)
|
|
? AppLocalizations.of(
|
|
context)!
|
|
.deleteRoomShort
|
|
: AppLocalizations.of(
|
|
context)!
|
|
.leaveRoomShort),
|
|
)
|
|
],
|
|
));
|
|
},
|
|
))
|
|
]
|
|
: [],
|
|
])))));
|
|
}
|
|
}
|