Improvements to state items (#478)

- Remove context menu (and fix long press when there are no items).
- Add membership change tests.
- Fix new/old name incorrect ordering.
- Fix message grouping when it comes before/after a state item from the same user.
- Only show reactions picker for items that can be reacted to.
This commit is contained in:
Doug
2023-01-23 10:01:45 +00:00
committed by GitHub
parent e6d0cbec50
commit 9f865cf5c9
8 changed files with 155 additions and 15 deletions
@@ -37,6 +37,12 @@ enum TimelineItemProxy {
guard case let .event(selfEventItemProxy) = self, case let .event(previousEventItemProxy) = previousItemProxy else {
return false
}
// State events aren't rendered as messages so shouldn't be grouped.
if selfEventItemProxy.isRoomState || previousEventItemProxy.isRoomState {
return false
}
// can be improved by adding a date threshold
return previousEventItemProxy.reactions.isEmpty && selfEventItemProxy.sender == previousEventItemProxy.sender
}
@@ -83,6 +89,10 @@ struct EventTimelineItemProxy: CustomDebugStringConvertible {
content.asMessage() != nil
}
var isRoomState: Bool {
content.kind().isRoomState
}
var content: TimelineItemContent {
item.content()
}
@@ -116,3 +126,14 @@ struct EventTimelineItemProxy: CustomDebugStringConvertible {
item.fmtDebug()
}
}
extension TimelineItemContentKind {
var isRoomState: Bool {
switch self {
case .state, .roomMembership:
return true
default:
return false
}
}
}
@@ -87,7 +87,7 @@ struct RoomStateEventStringBuilder {
switch (displayNameChanged, avatarChanged, memberIsYou) {
case (true, false, false):
if let displayName, let previousDisplayName {
return ElementL10n.noticeDisplayNameChangedFrom(member, displayName, previousDisplayName)
return ElementL10n.noticeDisplayNameChangedFrom(member, previousDisplayName, displayName)
} else if let displayName {
return ElementL10n.noticeDisplayNameSet(member, displayName)
} else if let previousDisplayName {
@@ -100,7 +100,7 @@ struct RoomStateEventStringBuilder {
return ElementL10n.noticeAvatarUrlChanged(displayName ?? member)
case (true, false, true):
if let displayName, let previousDisplayName {
return ElementL10n.noticeDisplayNameChangedFromByYou(displayName, previousDisplayName)
return ElementL10n.noticeDisplayNameChangedFromByYou(previousDisplayName, displayName)
} else if let displayName {
return ElementL10n.noticeDisplayNameSetByYou(displayName)
} else if let previousDisplayName {
@@ -68,6 +68,18 @@ enum RoomTimelineViewProvider: Identifiable, Hashable {
return item.id
}
}
/// Whether or not it is possible to send a reaction to this timeline item.
var isReactable: Bool {
switch self {
case .text, .image, .video, .file, .emote, .notice, .sticker:
return true
case .redacted, .encrypted, .unsupported, .state: // Event based items that aren't reactable
return false
case .timelineStart, .separator, .readMarker, .paginationIndicator: // Virtual items are never reactable
return false
}
}
}
extension RoomTimelineViewProvider: View {