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:
parent
89c0b069e1
commit
5b398eb2ae
5 changed files with 113 additions and 63 deletions
|
@ -319,15 +319,14 @@ class RoomMember {
|
||||||
final String id;
|
final String id;
|
||||||
final String serverTag;
|
final String serverTag;
|
||||||
final bool isAdmin;
|
final bool isAdmin;
|
||||||
|
final bool isInvitePending;
|
||||||
|
|
||||||
const RoomMember(
|
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) {
|
factory RoomMember.fromJSON(dynamic json) {
|
||||||
return RoomMember(
|
return RoomMember(
|
||||||
id: json['name'],
|
id: json['name'], serverTag: json['server'], isAdmin: json['admin'], isInvitePending: json['confirmed']);
|
||||||
serverTag: json['server'],
|
|
||||||
isAdmin: json['admin'] == 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String get humanReadableName {
|
String get humanReadableName {
|
||||||
|
|
|
@ -96,8 +96,8 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(
|
title:
|
||||||
AppLocalizations.of(context)!.roomMembersTitle(list.length)),
|
Text(AppLocalizations.of(context)!.roomMembersTitle(list.length)),
|
||||||
//actions: [
|
//actions: [
|
||||||
// // NOTE: Maybe add a search icon
|
// // NOTE: Maybe add a search icon
|
||||||
// // and general search functionality here
|
// // and general search functionality here
|
||||||
|
@ -166,29 +166,46 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
|
||||||
leading: const Icon(
|
leading: const Icon(
|
||||||
Icons.supervisor_account),
|
Icons.supervisor_account),
|
||||||
title: Text(item.isAdmin
|
title: Text(item.isAdmin
|
||||||
? AppLocalizations.of(context)!.removeAdminTitle
|
? AppLocalizations.of(
|
||||||
: AppLocalizations.of(context)!.makeAdminTitle),
|
context)!
|
||||||
|
.removeAdminTitle
|
||||||
|
: AppLocalizations.of(
|
||||||
|
context)!
|
||||||
|
.makeAdminTitle),
|
||||||
subtitle: Text(item.isAdmin
|
subtitle: Text(item.isAdmin
|
||||||
? AppLocalizations.of(context)!.removeAdminSubtitle
|
? AppLocalizations.of(
|
||||||
: AppLocalizations.of(context)!.makeAdminSubtitle),
|
context)!
|
||||||
|
.removeAdminSubtitle
|
||||||
|
: AppLocalizations.of(
|
||||||
|
context)!
|
||||||
|
.makeAdminSubtitle),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// make user admin
|
// make user admin
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder:
|
builder:
|
||||||
(context) =>
|
(ctx) =>
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons
|
Icons
|
||||||
.supervisor_account),
|
.supervisor_account),
|
||||||
title: Text(item
|
title: Text(item.isAdmin
|
||||||
.isAdmin
|
? AppLocalizations.of(
|
||||||
? AppLocalizations.of(context)!.removeAdminTitle
|
context)!
|
||||||
: AppLocalizations.of(context)!.makeAdminTitle),
|
.removeAdminTitle
|
||||||
|
: AppLocalizations.of(
|
||||||
|
context)!
|
||||||
|
.makeAdminTitle),
|
||||||
content: Text(item
|
content: Text(item
|
||||||
.isAdmin
|
.isAdmin
|
||||||
? AppLocalizations.of(context)!.removeAdminConfirm(item.humanReadableName)
|
? AppLocalizations.of(
|
||||||
: AppLocalizations.of(context)!.makeAdminConfirm(item.humanReadableName)),
|
context)!
|
||||||
|
.removeAdminConfirm(item
|
||||||
|
.humanReadableName)
|
||||||
|
: AppLocalizations.of(
|
||||||
|
context)!
|
||||||
|
.makeAdminConfirm(
|
||||||
|
item.humanReadableName)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed:
|
onPressed:
|
||||||
|
@ -196,10 +213,12 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
|
||||||
// close popup
|
// close popup
|
||||||
// NOTE: cancel only closes the dialog
|
// NOTE: cancel only closes the dialog
|
||||||
// whilst OK closes both
|
// whilst OK closes both
|
||||||
Navigator.of(context)
|
Navigator.of(ctx)
|
||||||
.pop();
|
.pop();
|
||||||
},
|
},
|
||||||
child: Text(AppLocalizations.of(context)!.cancel),
|
child: Text(
|
||||||
|
AppLocalizations.of(context)!
|
||||||
|
.cancel),
|
||||||
),
|
),
|
||||||
FilledButton(
|
FilledButton(
|
||||||
onPressed:
|
onPressed:
|
||||||
|
@ -208,6 +227,8 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
|
||||||
final scaffMgr =
|
final scaffMgr =
|
||||||
ScaffoldMessenger.of(context);
|
ScaffoldMessenger.of(context);
|
||||||
final nav =
|
final nav =
|
||||||
|
Navigator.of(ctx);
|
||||||
|
final nav2 =
|
||||||
Navigator.of(context);
|
Navigator.of(context);
|
||||||
final user =
|
final user =
|
||||||
context.read<User>();
|
context.read<User>();
|
||||||
|
@ -228,10 +249,13 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
|
||||||
after: () {
|
after: () {
|
||||||
// close popup
|
// close popup
|
||||||
nav.pop();
|
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(
|
ListTile(
|
||||||
leading: const Icon(
|
leading: const Icon(
|
||||||
Icons.person_remove),
|
Icons.person_remove),
|
||||||
title: Text(AppLocalizations.of(context)!.kickUserTitle),
|
title: Text(
|
||||||
subtitle: Text(AppLocalizations.of(context)!.kickUserSubtitle),
|
AppLocalizations.of(
|
||||||
|
context)!
|
||||||
|
.kickUserTitle),
|
||||||
|
subtitle: Text(
|
||||||
|
AppLocalizations.of(
|
||||||
|
context)!
|
||||||
|
.kickUserSubtitle),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// remove user from room
|
// remove user from room
|
||||||
showDialog(
|
showDialog(
|
||||||
|
@ -261,10 +291,13 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons
|
Icons
|
||||||
.person_remove),
|
.person_remove),
|
||||||
title: Text(
|
title: Text(AppLocalizations.of(
|
||||||
AppLocalizations.of(context)!.kickUserTitle),
|
context)!
|
||||||
content: Text(
|
.kickUserTitle),
|
||||||
AppLocalizations.of(context)!.kichUserConfirm(item.humanReadableName)),
|
content: Text(AppLocalizations.of(
|
||||||
|
context)!
|
||||||
|
.kichUserConfirm(
|
||||||
|
item.humanReadableName)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed:
|
onPressed:
|
||||||
|
@ -277,7 +310,8 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
|
||||||
.pop();
|
.pop();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
AppLocalizations.of(context)!.cancel),
|
AppLocalizations.of(context)!
|
||||||
|
.cancel),
|
||||||
),
|
),
|
||||||
FilledButton(
|
FilledButton(
|
||||||
onPressed:
|
onPressed:
|
||||||
|
@ -287,6 +321,8 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
|
||||||
ScaffoldMessenger.of(ctx);
|
ScaffoldMessenger.of(ctx);
|
||||||
final nav =
|
final nav =
|
||||||
Navigator.of(ctx);
|
Navigator.of(ctx);
|
||||||
|
final nav2 =
|
||||||
|
Navigator.of(context);
|
||||||
final user =
|
final user =
|
||||||
context.read<User>();
|
context.read<User>();
|
||||||
|
|
||||||
|
@ -305,11 +341,13 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
|
||||||
after: () {
|
after: () {
|
||||||
// close popup
|
// close popup
|
||||||
nav.pop();
|
nav.pop();
|
||||||
nav.pop();
|
// close bottom sheet
|
||||||
|
nav2.pop();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
AppLocalizations.of(context)!.ok),
|
AppLocalizations.of(context)!
|
||||||
|
.ok),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
|
@ -321,7 +359,8 @@ class _ManageRoomMembersPageState extends State<ManageRoomMembersPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FilledButton(
|
FilledButton(
|
||||||
child: Text(AppLocalizations.of(context)!.close),
|
child: Text(
|
||||||
|
AppLocalizations.of(context)!.close),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
|
|
|
@ -45,9 +45,12 @@ class _RoomCategoriesPageState extends State<RoomCategoriesPage> {
|
||||||
final resp = json['data']
|
final resp = json['data']
|
||||||
.map<RoomCategory>((raw) => RoomCategory.fromJSON(raw))
|
.map<RoomCategory>((raw) => RoomCategory.fromJSON(raw))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
list = resp;
|
list = resp;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,9 +75,7 @@ class _RoomCategoriesPageState extends State<RoomCategoriesPage> {
|
||||||
RoomPermission.editRoomContent !=
|
RoomPermission.editRoomContent !=
|
||||||
0))
|
0))
|
||||||
? ReorderableDragStartListener(
|
? ReorderableDragStartListener(
|
||||||
index: index,
|
index: index, child: const Icon(Icons.drag_handle))
|
||||||
child: const Icon(Icons.drag_handle)
|
|
||||||
)
|
|
||||||
: null,
|
: null,
|
||||||
title: Text(item.name),
|
title: Text(item.name),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
@ -201,11 +202,9 @@ class _RoomCategoriesPageState extends State<RoomCategoriesPage> {
|
||||||
},
|
},
|
||||||
itemCount: list.length,
|
itemCount: list.length,
|
||||||
onReorder: (int oldIndex, int newIndex) {
|
onReorder: (int oldIndex, int newIndex) {
|
||||||
|
|
||||||
if (!((widget.info?.isAdmin ?? false) ||
|
if (!((widget.info?.isAdmin ?? false) ||
|
||||||
(widget.info?.isOwner ?? false) ||
|
(widget.info?.isOwner ?? false) ||
|
||||||
((widget.info?.permissions)! &
|
((widget.info?.permissions)! & RoomPermission.editRoomContent !=
|
||||||
RoomPermission.editRoomContent !=
|
|
||||||
0))) {
|
0))) {
|
||||||
// user is not allowed to edit or delete categories
|
// user is not allowed to edit or delete categories
|
||||||
return;
|
return;
|
||||||
|
@ -235,9 +234,9 @@ class _RoomCategoriesPageState extends State<RoomCategoriesPage> {
|
||||||
),
|
),
|
||||||
floatingActionButton: ((widget.info?.isAdmin ?? false) ||
|
floatingActionButton: ((widget.info?.isAdmin ?? false) ||
|
||||||
(widget.info?.isOwner ?? false) ||
|
(widget.info?.isOwner ?? false) ||
|
||||||
((widget.info?.permissions)! &
|
((widget.info?.permissions)! & RoomPermission.editRoomContent !=
|
||||||
RoomPermission.editRoomContent !=
|
0))
|
||||||
0))?FloatingActionButton.extended(
|
? FloatingActionButton.extended(
|
||||||
icon: const Icon(Icons.add),
|
icon: const Icon(Icons.add),
|
||||||
label: Text(AppLocalizations.of(context)!.newCategoryShort),
|
label: Text(AppLocalizations.of(context)!.newCategoryShort),
|
||||||
tooltip: AppLocalizations.of(context)!.newCategoryLong,
|
tooltip: AppLocalizations.of(context)!.newCategoryLong,
|
||||||
|
@ -248,7 +247,8 @@ class _RoomCategoriesPageState extends State<RoomCategoriesPage> {
|
||||||
'id': widget.room!.id,
|
'id': widget.room!.id,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
):null,
|
)
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,12 +58,14 @@ class _ShoppingListPageState extends State<ShoppingListPage> {
|
||||||
|
|
||||||
// TODO: cache items
|
// TODO: cache items
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
list = l;
|
list = l;
|
||||||
cart = c;
|
cart = c;
|
||||||
|
|
||||||
sortAll();
|
sortAll();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,11 +127,14 @@ class _ShoppingListPageState extends State<ShoppingListPage> {
|
||||||
for (int i = 0; i < resp.length; i++) {
|
for (int i = 0; i < resp.length; i++) {
|
||||||
map[resp[i].id] = i;
|
map[resp[i].id] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
weights = map;
|
weights = map;
|
||||||
categories = resp;
|
categories = resp;
|
||||||
sortAll();
|
sortAll();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,9 +154,11 @@ class _ShoppingListPageState extends State<ShoppingListPage> {
|
||||||
.map<RoomProduct>((raw) => RoomProduct.fromJSON(raw))
|
.map<RoomProduct>((raw) => RoomProduct.fromJSON(raw))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
products = resp;
|
products = resp;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +359,9 @@ class ShoppingListItem extends StatelessWidget {
|
||||||
enabled: !inCart,
|
enabled: !inCart,
|
||||||
title: Text(name),
|
title: Text(name),
|
||||||
subtitle: Text(description),
|
subtitle: Text(description),
|
||||||
trailing: CategoryChip(category: category,),
|
trailing: CategoryChip(
|
||||||
|
category: category,
|
||||||
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (onTap != null) {
|
if (onTap != null) {
|
||||||
onTap!();
|
onTap!();
|
||||||
|
@ -396,8 +405,9 @@ class ShoppingListItemInfo extends StatelessWidget {
|
||||||
selected: item.category,
|
selected: item.category,
|
||||||
enabled: false),
|
enabled: false),
|
||||||
ProductPicker(
|
ProductPicker(
|
||||||
label:AppLocalizations.of(context)!.selectLinkedProductLabel,
|
label:
|
||||||
help:AppLocalizations.of(context)!.selectLinkedProductHelp,
|
AppLocalizations.of(context)!.selectLinkedProductLabel,
|
||||||
|
help: AppLocalizations.of(context)!.selectLinkedProductHelp,
|
||||||
products: products,
|
products: products,
|
||||||
selected: item.link,
|
selected: item.link,
|
||||||
enabled: false)
|
enabled: false)
|
||||||
|
|
|
@ -37,9 +37,11 @@ class _RoomProductsPageState extends State<RoomProductsPage> {
|
||||||
|
|
||||||
// TODO: cache products
|
// TODO: cache products
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
products = resp;
|
products = resp;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue