Skip to content

Commit

Permalink
compose_box: Replace compose box with a banner when cannot post in a …
Browse files Browse the repository at this point in the history
…channel

Fixes: #674
  • Loading branch information
sm-sayedi committed Aug 15, 2024
1 parent 962302f commit 2a44121
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 79 deletions.
4 changes: 4 additions & 0 deletions assets/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@
"@errorBannerDeactivatedDmLabel": {
"description": "Label text for error banner when sending a message to one or multiple deactivated users."
},
"errorBannerCannotPostInChannelLabel": "You do not have permission to post in this channel.",
"@errorBannerCannotPostInChannelLabel": {
"description": "Label text for error banner when sending a message in a channel with no posting permission."
},
"composeBoxAttachFilesTooltip": "Attach files",
"@composeBoxAttachFilesTooltip": {
"description": "Tooltip for compose box icon to attach a file to the message."
Expand Down
34 changes: 25 additions & 9 deletions lib/widgets/compose_box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -999,8 +999,21 @@ class _StreamComposeBoxState extends State<_StreamComposeBox> implements Compose
super.dispose();
}

Widget? _errorBanner(BuildContext context) {
final store = PerAccountStoreWidget.of(context);
final selfUser = store.users[store.selfUserId]!;
final channel = store.streams[widget.narrow.streamId]!;
return channel.hasPostingPermission(selfUser, realmWaitingPeriodThreshold: store.realmWaitingPeriodThreshold)
? null : _ErrorBanner(label: ZulipLocalizations.of(context).errorBannerCannotPostInChannelLabel);
}

@override
Widget build(BuildContext context) {
final errorBanner = _errorBanner(context);
if (errorBanner != null) {
return _ComposeBoxContainer(child: errorBanner);
}

return _ComposeBoxLayout(
contentController: _contentController,
contentFocusNode: _contentFocusNode,
Expand Down Expand Up @@ -1072,16 +1085,19 @@ class _FixedDestinationComposeBoxState extends State<_FixedDestinationComposeBox
}

Widget? _errorBanner(BuildContext context) {
if (widget.narrow case DmNarrow(:final otherRecipientIds)) {
final store = PerAccountStoreWidget.of(context);
final hasDeactivatedUser = otherRecipientIds.any((id) =>
!(store.users[id]?.isActive ?? true));
if (hasDeactivatedUser) {
return _ErrorBanner(label: ZulipLocalizations.of(context)
.errorBannerDeactivatedDmLabel);
}
final store = PerAccountStoreWidget.of(context);
switch (widget.narrow) {
case TopicNarrow():
final selfUser = store.users[store.selfUserId]!;
final channel = store.streams[(widget.narrow as TopicNarrow).streamId]!;
return channel.hasPostingPermission(selfUser, realmWaitingPeriodThreshold: store.realmWaitingPeriodThreshold)
? null : _ErrorBanner(label: ZulipLocalizations.of(context).errorBannerCannotPostInChannelLabel);
case DmNarrow(:final otherRecipientIds):
final hasDeactivatedUser = otherRecipientIds.any((id) =>
!(store.users[id]?.isActive ?? true));
return hasDeactivatedUser ? _ErrorBanner(label: ZulipLocalizations.of(context)
.errorBannerDeactivatedDmLabel) : null;
}
return null;
}

@override
Expand Down
2 changes: 1 addition & 1 deletion test/widgets/action_sheet_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Future<void> setupToMessageActionSheet(WidgetTester tester, {

await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
final store = await testBinding.globalStore.perAccount(eg.selfAccount.id);
await store.addUser(eg.user(userId: message.senderId));
await store.addUsers([eg.selfUser, eg.user(userId: message.senderId)]);
if (message is StreamMessage) {
final stream = eg.stream(streamId: message.streamId);
await store.addStream(stream);
Expand Down
2 changes: 2 additions & 0 deletions test/widgets/autocomplete_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,12 @@ Future<Finder> setupToTopicInput(WidgetTester tester, {
addTearDown(testBinding.reset);
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
final store = await testBinding.globalStore.perAccount(eg.selfAccount.id);
await store.addUser(eg.selfUser);
final connection = store.connection as FakeApiConnection;

// prepare message list data
final stream = eg.stream();
await store.addStream(stream);
final message = eg.streamMessage(stream: stream, sender: eg.selfUser);
connection.prepare(json: GetMessagesResult(
anchor: message.id,
Expand Down
Loading

0 comments on commit 2a44121

Please sign in to comment.