Skip to content

Commit

Permalink
wip starring messages
Browse files Browse the repository at this point in the history
  • Loading branch information
sirpengi committed Dec 1, 2023
1 parent 681d129 commit ab95751
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 39 deletions.
8 changes: 8 additions & 0 deletions assets/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,18 @@
"@actionSheetOptionShare": {
"description": "Label for share button on action sheet."
},
"actionSheetOptionStarMessage": "Star message",
"@actionSheetOptionStarMessage": {
"description": "Label for star button on action sheet."
},
"actionSheetOptionQuoteAndReply": "Quote and reply",
"@actionSheetOptionQuoteAndReply": {
"description": "Label for Quote and reply button on action sheet."
},
"actionSheetOptionUnstarMessage": "Unstar message",
"@actionSheetOptionUnstarMessage": {
"description": "Label for unstar button on action sheet."
},
"errorCouldNotFetchMessageSource": "Could not fetch message source",
"@errorCouldNotFetchMessageSource": {
"description": "Error message when the source of a message could not be fetched."
Expand Down
3 changes: 3 additions & 0 deletions lib/api/model/initial_snapshot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class InitialSnapshot {

final UnreadMessagesSnapshot unreadMsgs;

final Set<int> starredMessages;

final List<ZulipStream> streams;

// Servers pre-5.0 don't have `user_settings`, and instead provide whatever
Expand Down Expand Up @@ -86,6 +88,7 @@ class InitialSnapshot {
required this.recentPrivateConversations,
required this.subscriptions,
required this.unreadMsgs,
required this.starredMessages,
required this.streams,
required this.userSettings,
required this.realmDefaultExternalAccounts,
Expand Down
4 changes: 4 additions & 0 deletions lib/api/model/initial_snapshot.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions lib/widgets/action_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void showMessageActionSheet({required BuildContext context, required Message mes
messageListContext: context,
),
CopyButton(message: message, messageListContext: context),
StarButton(message: message, messageListContext: context),
]);
});
}
Expand Down Expand Up @@ -262,3 +263,32 @@ class CopyButton extends MessageActionSheetMenuItemButton {
data: ClipboardData(text: rawContent));
};
}

class StarButton extends MessageActionSheetMenuItemButton {
StarButton({
super.key,
required super.message,
required super.messageListContext,
});

@override get icon => Icons.star;

@override
String label(ZulipLocalizations zulipLocalizations) {
return message.flags.contains(MessageFlag.starred)
? zulipLocalizations.actionSheetOptionUnstarMessage
: zulipLocalizations.actionSheetOptionStarMessage;
}

@override get onPressed => (BuildContext context) async {
final connection = PerAccountStoreWidget.of(messageListContext).connection;
if (message.flags.contains(MessageFlag.starred)) {
updateMessageFlags(connection, messages: [message.id],
op: UpdateMessageFlagsOp.remove, flag: MessageFlag.starred);
} else {
updateMessageFlags(connection, messages: [message.id],
op: UpdateMessageFlagsOp.add, flag: MessageFlag.starred);
}
Navigator.of(context).pop();
};
}
95 changes: 56 additions & 39 deletions lib/widgets/message_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -777,52 +777,69 @@ class MessageWithPossibleSender extends StatelessWidget {
behavior: HitTestBehavior.translucent,
onLongPress: () => showMessageActionSheet(context: context, message: message),
// TODO clean up this layout, by less precisely imitating web
child: Padding(
padding: const EdgeInsets.only(top: 2, bottom: 3, left: 8, right: 8),
child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
item.showSender
? Padding(
padding: const EdgeInsets.fromLTRB(3, 6, 11, 0),
child: GestureDetector(
onTap: () => Navigator.push(context,
ProfilePage.buildRoute(context: context,
userId: message.senderId)),
child: Avatar(size: 35, borderRadius: 4,
userId: message.senderId)))
: const SizedBox(width: 3 + 35 + 11),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
child: Column(
children: [
const SizedBox(height: 2),
if (item.showSender)
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (item.showSender) ...[
const SizedBox(height: 3),
GestureDetector(
onTap: () => Navigator.push(context,
ProfilePage.buildRoute(context: context,
userId: message.senderId)),
child: Text(message.senderFullName, // TODO get from user data
style: const TextStyle(fontWeight: FontWeight.bold))),
const SizedBox(height: 4),
],
MessageContent(message: message, content: item.content),
])),
Container(
width: 80,
padding: const EdgeInsets.only(top: 4, right: 16 - 8),
alignment: Alignment.topRight,
child: Text(time, style: _kMessageTimestampStyle)),
])));
Flexible(
fit: FlexFit.loose,
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 6, 0, 0),
child: GestureDetector(
onTap: () => Navigator.push(context,
ProfilePage.buildRoute(context: context,
userId: message.senderId)),
child: Row(
children: [
Avatar(size: 32, borderRadius: 3, userId: message.senderId),
const SizedBox(width: 8),
Text(message.senderFullName, // TODO get from user data
style: const TextStyle(
fontFamily: 'Source Sans 3',
fontSize: 18,
height: (22 / 18),
).merge(weightVariableTextStyle(context, wght: 600, wghtIfPlatformRequestsBold: 900)),
overflow: TextOverflow.ellipsis),
])))),
Padding(
padding: const EdgeInsets.only(right: 16),
child: Text(time,
style: TextStyle(
color: _kMessageTimestampColor,
fontFamily: 'Source Sans 3',
fontSize: 17,
height: (22 / 17),
fontFeatures: const [FontFeature.enable('c2sc'), FontFeature.enable('smcp')],
).merge(weightVariableTextStyle(context)))),
]),
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const SizedBox(width: 16),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: MessageContent(message: message, content: item.content))),
SizedBox(width: 16,
child: Column(
children: [
if (message.flags.contains(MessageFlag.starred))
const Icon(size: 16, Icons.star),
])),
]
),
]
));
}
}

// TODO web seems to ignore locale in formatting time, but we could do better
final _kMessageTimestampFormat = DateFormat('h:mm aa', 'en_US');

// TODO this seems to come out lighter than on web
final _kMessageTimestampStyle = TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
color: const HSLColor.fromAHSL(0.4, 0, 0, 0.2).toColor());
final _kMessageTimestampColor = const HSLColor.fromAHSL(1, 0, 0, 0.5).toColor();

Future<void> markNarrowAsRead(BuildContext context, Narrow narrow) async {
final store = PerAccountStoreWidget.of(context);
Expand Down
2 changes: 2 additions & 0 deletions test/example_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ InitialSnapshot initialSnapshot({
List<RecentDmConversation>? recentPrivateConversations,
List<Subscription>? subscriptions,
UnreadMessagesSnapshot? unreadMsgs,
Set<int>? starredMessages,
List<ZulipStream>? streams,
UserSettings? userSettings,
Map<String, RealmDefaultExternalAccount>? realmDefaultExternalAccounts,
Expand All @@ -438,6 +439,7 @@ InitialSnapshot initialSnapshot({
recentPrivateConversations: recentPrivateConversations ?? [],
subscriptions: subscriptions ?? [], // TODO add subscriptions to default
unreadMsgs: unreadMsgs ?? _unreadMsgs(),
starredMessages: starredMessages ?? {},
streams: streams ?? [], // TODO add streams to default
userSettings: userSettings, // TODO add userSettings to default
realmDefaultExternalAccounts: realmDefaultExternalAccounts ?? {},
Expand Down

0 comments on commit ab95751

Please sign in to comment.