Bug fixes (see description)

- Fixed bug where switching room pages
  (list,products,categories,about),
  would result an unknown error,
  due to setState being called on a widget that isn't mounted.
  This was solved by surrounding the setState function,
  with a condition to check if the widget is mounted

- Fixed bug where room members weren't recognized as admins
  This was caused by a typedifference between the server and the app
  (The server now returns booleans,
  where as before a ==1 comparison was
  needed)
- Fixed bug where successfully closing the admin/kick member dialog,
  would crash the application.
  This was caused by popping the same context twice.
  We are now using two navigator (the outer and the inner one)
This commit is contained in:
Jakob Meier 2023-04-05 08:49:46 +02:00
parent 89c0b069e1
commit 5b398eb2ae
No known key found for this signature in database
GPG key ID: 66BDC7E6A01A6152
5 changed files with 113 additions and 63 deletions

View file

@ -319,15 +319,14 @@ class RoomMember {
final String id;
final String serverTag;
final bool isAdmin;
final bool isInvitePending;
const RoomMember(
{required this.id, required this.serverTag, required this.isAdmin});
{required this.id, required this.serverTag, required this.isAdmin, this.isInvitePending=false});
factory RoomMember.fromJSON(dynamic json) {
return RoomMember(
id: json['name'],
serverTag: json['server'],
isAdmin: json['admin'] == 1);
id: json['name'], serverTag: json['server'], isAdmin: json['admin'], isInvitePending: json['confirmed']);
}
String get humanReadableName {

View file

@ -96,8 +96,8 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
return Scaffold(
appBar: AppBar(
title: Text(
AppLocalizations.of(context)!.roomMembersTitle(list.length)),
title:
Text(AppLocalizations.of(context)!.roomMembersTitle(list.length)),
//actions: [
// // NOTE: Maybe add a search icon
// // and general search functionality here
@ -166,29 +166,46 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
leading: const Icon(
Icons.supervisor_account),
title: Text(item.isAdmin
? AppLocalizations.of(context)!.removeAdminTitle
: AppLocalizations.of(context)!.makeAdminTitle),
? AppLocalizations.of(
context)!
.removeAdminTitle
: AppLocalizations.of(
context)!
.makeAdminTitle),
subtitle: Text(item.isAdmin
? AppLocalizations.of(context)!.removeAdminSubtitle
: AppLocalizations.of(context)!.makeAdminSubtitle),
? AppLocalizations.of(
context)!
.removeAdminSubtitle
: AppLocalizations.of(
context)!
.makeAdminSubtitle),
onTap: () {
// make user admin
showDialog(
context: context,
builder:
(context) =>
(ctx) =>
AlertDialog(
icon: const Icon(
Icons
.supervisor_account),
title: Text(item
.isAdmin
? AppLocalizations.of(context)!.removeAdminTitle
: AppLocalizations.of(context)!.makeAdminTitle),
title: Text(item.isAdmin
? AppLocalizations.of(
context)!
.removeAdminTitle
: AppLocalizations.of(
context)!
.makeAdminTitle),
content: Text(item
.isAdmin
? AppLocalizations.of(context)!.removeAdminConfirm(item.humanReadableName)
: AppLocalizations.of(context)!.makeAdminConfirm(item.humanReadableName)),
? AppLocalizations.of(
context)!
.removeAdminConfirm(item
.humanReadableName)
: AppLocalizations.of(
context)!
.makeAdminConfirm(
item.humanReadableName)),
actions: [
TextButton(
onPressed:
@ -196,10 +213,12 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
// close popup
// NOTE: cancel only closes the dialog
// whilst OK closes both
Navigator.of(context)
Navigator.of(ctx)
.pop();
},
child: Text(AppLocalizations.of(context)!.cancel),
child: Text(
AppLocalizations.of(context)!
.cancel),
),
FilledButton(
onPressed:
@ -208,6 +227,8 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
final scaffMgr =
ScaffoldMessenger.of(context);
final nav =
Navigator.of(ctx);
final nav2 =
Navigator.of(context);
final user =
context.read<User>();
@ -228,10 +249,13 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
after: () {
// close popup
nav.pop();
nav.pop();
// close bottom sheet
nav2.pop();
});
},
child: Text(AppLocalizations.of(context)!.ok),
child: Text(
AppLocalizations.of(context)!
.ok),
)
],
));
@ -249,8 +273,14 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
ListTile(
leading: const Icon(
Icons.person_remove),
title: Text(AppLocalizations.of(context)!.kickUserTitle),
subtitle: Text(AppLocalizations.of(context)!.kickUserSubtitle),
title: Text(
AppLocalizations.of(
context)!
.kickUserTitle),
subtitle: Text(
AppLocalizations.of(
context)!
.kickUserSubtitle),
onTap: () {
// remove user from room
showDialog(
@ -261,10 +291,13 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
icon: const Icon(
Icons
.person_remove),
title: Text(
AppLocalizations.of(context)!.kickUserTitle),
content: Text(
AppLocalizations.of(context)!.kichUserConfirm(item.humanReadableName)),
title: Text(AppLocalizations.of(
context)!
.kickUserTitle),
content: Text(AppLocalizations.of(
context)!
.kichUserConfirm(
item.humanReadableName)),
actions: [
TextButton(
onPressed:
@ -277,7 +310,8 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
.pop();
},
child: Text(
AppLocalizations.of(context)!.cancel),
AppLocalizations.of(context)!
.cancel),
),
FilledButton(
onPressed:
@ -287,6 +321,8 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
ScaffoldMessenger.of(ctx);
final nav =
Navigator.of(ctx);
final nav2 =
Navigator.of(context);
final user =
context.read<User>();
@ -305,11 +341,13 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
after: () {
// close popup
nav.pop();
nav.pop();
// close bottom sheet
nav2.pop();
});
},
child: Text(
AppLocalizations.of(context)!.ok),
AppLocalizations.of(context)!
.ok),
)
],
));
@ -321,7 +359,8 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
),
),
FilledButton(
child: Text(AppLocalizations.of(context)!.close),
child: Text(
AppLocalizations.of(context)!.close),
onPressed: () {
Navigator.of(context).pop();
},

View file

@ -45,9 +45,12 @@ class _RoomCategoriesPageState extends State<RoomCategoriesPage> {
final resp = json['data']
.map<RoomCategory>((raw) => RoomCategory.fromJSON(raw))
.toList();
if (mounted) {
setState(() {
list = resp;
});
}
});
}
@ -72,9 +75,7 @@ class _RoomCategoriesPageState extends State<RoomCategoriesPage> {
RoomPermission.editRoomContent !=
0))
? ReorderableDragStartListener(
index: index,
child: const Icon(Icons.drag_handle)
)
index: index, child: const Icon(Icons.drag_handle))
: null,
title: Text(item.name),
onTap: () {
@ -201,11 +202,9 @@ class _RoomCategoriesPageState extends State<RoomCategoriesPage> {
},
itemCount: list.length,
onReorder: (int oldIndex, int newIndex) {
if (!((widget.info?.isAdmin ?? false) ||
(widget.info?.isOwner ?? false) ||
((widget.info?.permissions)! &
RoomPermission.editRoomContent !=
((widget.info?.permissions)! & RoomPermission.editRoomContent !=
0))) {
// user is not allowed to edit or delete categories
return;
@ -235,9 +234,9 @@ class _RoomCategoriesPageState extends State<RoomCategoriesPage> {
),
floatingActionButton: ((widget.info?.isAdmin ?? false) ||
(widget.info?.isOwner ?? false) ||
((widget.info?.permissions)! &
RoomPermission.editRoomContent !=
0))?FloatingActionButton.extended(
((widget.info?.permissions)! & RoomPermission.editRoomContent !=
0))
? FloatingActionButton.extended(
icon: const Icon(Icons.add),
label: Text(AppLocalizations.of(context)!.newCategoryShort),
tooltip: AppLocalizations.of(context)!.newCategoryLong,
@ -248,7 +247,8 @@ class _RoomCategoriesPageState extends State<RoomCategoriesPage> {
'id': widget.room!.id,
});
},
):null,
)
: null,
);
}
}

View file

@ -58,12 +58,14 @@ class _ShoppingListPageState extends State<ShoppingListPage> {
// TODO: cache items
if (mounted) {
setState(() {
list = l;
cart = c;
sortAll();
});
}
});
}
@ -125,11 +127,14 @@ class _ShoppingListPageState extends State<ShoppingListPage> {
for (int i = 0; i < resp.length; i++) {
map[resp[i].id] = i;
}
if (mounted) {
setState(() {
weights = map;
categories = resp;
sortAll();
});
}
});
}
@ -149,9 +154,11 @@ class _ShoppingListPageState extends State<ShoppingListPage> {
.map<RoomProduct>((raw) => RoomProduct.fromJSON(raw))
.toList();
if (mounted) {
setState(() {
products = resp;
});
}
});
}
@ -352,7 +359,9 @@ class ShoppingListItem extends StatelessWidget {
enabled: !inCart,
title: Text(name),
subtitle: Text(description),
trailing: CategoryChip(category: category,),
trailing: CategoryChip(
category: category,
),
onTap: () {
if (onTap != null) {
onTap!();
@ -396,7 +405,8 @@ class ShoppingListItemInfo extends StatelessWidget {
selected: item.category,
enabled: false),
ProductPicker(
label:AppLocalizations.of(context)!.selectLinkedProductLabel,
label:
AppLocalizations.of(context)!.selectLinkedProductLabel,
help: AppLocalizations.of(context)!.selectLinkedProductHelp,
products: products,
selected: item.link,

View file

@ -37,9 +37,11 @@ class _RoomProductsPageState extends State<RoomProductsPage> {
// TODO: cache products
if (mounted) {
setState(() {
products = resp;
});
}
});
}