-
Notifications
You must be signed in to change notification settings - Fork 350
action_sheet: Offer "Mark channel as read" in channel action sheet #1317
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ import 'dart:async'; | |
|
|
||
| import 'package:flutter/material.dart'; | ||
|
|
||
| import '../api/exception.dart'; | ||
| import '../api/model/model.dart'; | ||
| import '../api/model/narrow.dart'; | ||
| import '../api/route/messages.dart'; | ||
|
|
@@ -32,9 +33,13 @@ abstract final class ZulipAction { | |
| return; | ||
| } catch (e) { | ||
| if (!context.mounted) return; | ||
| final message = switch (e) { | ||
| ZulipApiException() => zulipLocalizations.errorServerMessage(e.message), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: "in ZulipAction" is redundant — that's an abstract final class that's just synonymous with this file The methods are all statics and there's no such thing as an instance of ZulipAction (that's what "abstract final" means), so "in ZulipAction" wouldn't mean a whole lot anyway. |
||
| _ => e.toString(), // TODO(#741): extract user-facing message better | ||
| }; | ||
| showErrorDialog(context: context, | ||
| title: zulipLocalizations.errorMarkAsReadFailedTitle, | ||
| message: e.toString()); // TODO(#741): extract user-facing message better | ||
| message: message); | ||
| return; | ||
| } | ||
| } | ||
|
|
@@ -189,9 +194,14 @@ abstract final class ZulipAction { | |
| } | ||
| } catch (e) { | ||
| if (!context.mounted) return false; | ||
| final zulipLocalizations = ZulipLocalizations.of(context); | ||
| final message = switch (e) { | ||
| ZulipApiException() => zulipLocalizations.errorServerMessage(e.message), | ||
| _ => e.toString(), // TODO(#741): extract user-facing message better | ||
| }; | ||
| showErrorDialog(context: context, | ||
| title: onFailedTitle, | ||
| message: e.toString()); // TODO(#741): extract user-facing message better | ||
| message: message); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -370,36 +370,54 @@ class MessageListAppBarTitle extends StatelessWidget { | |
| case ChannelNarrow(:var streamId): | ||
| final store = PerAccountStoreWidget.of(context); | ||
| final stream = store.streams[streamId]; | ||
| return _buildStreamRow(context, stream: stream); | ||
|
|
||
| case TopicNarrow(:var streamId, :var topic): | ||
| final store = PerAccountStoreWidget.of(context); | ||
| final stream = store.streams[streamId]; | ||
| final alignment = willCenterTitle | ||
| ? Alignment.center | ||
| : AlignmentDirectional.centerStart; | ||
| return SizedBox( | ||
| width: double.infinity, | ||
| child: GestureDetector( | ||
| behavior: HitTestBehavior.translucent, | ||
| onLongPress: () { | ||
| final someMessage = MessageListPage.ancestorOf(context) | ||
| .model?.messages.firstOrNull; | ||
| // If someMessage is null, the topic action sheet won't have a | ||
| // resolve/unresolve button. That seems OK; in that case we're | ||
| // either still fetching messages (and the user can reopen the | ||
| // sheet after that finishes) or there aren't any messages to | ||
| // act on anyway. | ||
| assert(someMessage == null || narrow.containsMessage(someMessage)); | ||
| showTopicActionSheet(context, | ||
| channelId: streamId, | ||
| topic: topic, | ||
| someMessageIdInTopic: someMessage?.id); | ||
| showChannelActionSheet(context, channelId: streamId); | ||
| }, | ||
| child: Column( | ||
| crossAxisAlignment: willCenterTitle ? CrossAxisAlignment.center | ||
| : CrossAxisAlignment.start, | ||
| children: [ | ||
| _buildStreamRow(context, stream: stream), | ||
| _buildTopicRow(context, stream: stream, topic: topic), | ||
| ]))); | ||
| child: Align(alignment: alignment, | ||
| child: _buildStreamRow(context, stream: stream)))); | ||
|
|
||
| case TopicNarrow(:var streamId, :var topic): | ||
| final store = PerAccountStoreWidget.of(context); | ||
| final stream = store.streams[streamId]; | ||
| final alignment = willCenterTitle | ||
| ? Alignment.center | ||
| : AlignmentDirectional.centerStart; | ||
| return Column( | ||
| crossAxisAlignment: CrossAxisAlignment.stretch, | ||
| children: [ | ||
| GestureDetector( | ||
| behavior: HitTestBehavior.translucent, | ||
| onLongPress: () { | ||
| showChannelActionSheet(context, channelId: streamId); | ||
| }, | ||
| child: Align(alignment: alignment, | ||
| child: _buildStreamRow(context, stream: stream))), | ||
| GestureDetector( | ||
| behavior: HitTestBehavior.translucent, | ||
| onLongPress: () { | ||
| final someMessage = MessageListPage.ancestorOf(context) | ||
| .model?.messages.firstOrNull; | ||
| // If someMessage is null, the topic action sheet won't have a | ||
| // resolve/unresolve button. That seems OK; in that case we're | ||
| // either still fetching messages (and the user can reopen the | ||
| // sheet after that finishes) or there aren't any messages to | ||
| // act on anyway. | ||
| assert(someMessage == null || narrow.containsMessage(someMessage)); | ||
| showTopicActionSheet(context, | ||
| channelId: streamId, | ||
| topic: topic, | ||
| someMessageIdInTopic: someMessage?.id); | ||
| }, | ||
| child: Align(alignment: alignment, | ||
| child: _buildTopicRow(context, stream: stream, topic: topic))), | ||
| ]); | ||
|
Comment on lines
+419
to
+420
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cool, good formatting fix |
||
|
|
||
| case DmNarrow(:var otherRecipientIds): | ||
| final store = PerAccountStoreWidget.of(context); | ||
|
|
@@ -1061,6 +1079,7 @@ class StreamMessageRecipientHeader extends StatelessWidget { | |
| onTap: () => Navigator.push(context, | ||
| MessageListPage.buildRoute(context: context, | ||
| narrow: ChannelNarrow(message.streamId))), | ||
| onLongPress: () => showChannelActionSheet(context, channelId: message.streamId), | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs test coverage.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've noticed an existing bug with the gesture handling here. I filed it as #1368; no need to fix it in this PR (but feel free to claim the issue if you'd like to work on it as a followup). |
||
| child: Row( | ||
| crossAxisAlignment: CrossAxisAlignment.center, | ||
| children: [ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc for
showTopicActionSheetsays it needs a PageRoot ancestor. From the use ofPageRoot.contextOfit looks like the same is true here, so this doc should say so too.