mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Highlight selected emoji in picker, correct add more button in menu, fix order of count label on outgoing messages (#1430)
- Highlight selected emoji in picker - Correct add more button in menu - Fix the order of count/key label on outgoing messages - Fix the size padding of emoji in reactions
This commit is contained in:
@@ -136,9 +136,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case (.dismissMediaUploadPreview, .mediaUploadPreview(let roomID, _)):
|
case (.dismissMediaUploadPreview, .mediaUploadPreview(let roomID, _)):
|
||||||
return .room(roomID: roomID)
|
return .room(roomID: roomID)
|
||||||
|
|
||||||
case (.presentEmojiPicker(let itemID), .room(let roomID)):
|
case (.presentEmojiPicker(let itemID, let selectedEmoji), .room(let roomID)):
|
||||||
return .emojiPicker(roomID: roomID, itemID: itemID)
|
return .emojiPicker(roomID: roomID, itemID: itemID, selectedEmojis: selectedEmoji)
|
||||||
case (.dismissEmojiPicker, .emojiPicker(let roomID, _)):
|
case (.dismissEmojiPicker, .emojiPicker(let roomID, _, _)):
|
||||||
return .room(roomID: roomID)
|
return .room(roomID: roomID)
|
||||||
|
|
||||||
case (.presentMessageForwarding(let itemID), .room(let roomID)):
|
case (.presentMessageForwarding(let itemID), .room(let roomID)):
|
||||||
@@ -197,8 +197,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case (.mediaUploadPreview, .dismissMediaUploadPreview, .room):
|
case (.mediaUploadPreview, .dismissMediaUploadPreview, .room):
|
||||||
break
|
break
|
||||||
|
|
||||||
case (.room, .presentEmojiPicker, .emojiPicker(_, let itemID)):
|
case (.room, .presentEmojiPicker, .emojiPicker(_, let itemID, let selectedEmoji)):
|
||||||
presentEmojiPicker(for: itemID)
|
presentEmojiPicker(for: itemID, selectedEmoji: selectedEmoji)
|
||||||
case (.emojiPicker, .dismissEmojiPicker, .room):
|
case (.emojiPicker, .dismissEmojiPicker, .room):
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -303,8 +303,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
stateMachine.tryEvent(.presentMediaUploadPicker(source: source))
|
stateMachine.tryEvent(.presentMediaUploadPicker(source: source))
|
||||||
case .presentMediaUploadPreviewScreen(let url):
|
case .presentMediaUploadPreviewScreen(let url):
|
||||||
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: url))
|
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: url))
|
||||||
case .presentEmojiPicker(let itemID):
|
case .presentEmojiPicker(let itemID, let selectedEmojis):
|
||||||
stateMachine.tryEvent(.presentEmojiPicker(itemID: itemID))
|
stateMachine.tryEvent(.presentEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis))
|
||||||
case .presentLocationPicker:
|
case .presentLocationPicker:
|
||||||
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .picker))
|
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .picker))
|
||||||
case .presentLocationViewer(_, let geoURI, let description):
|
case .presentLocationViewer(_, let geoURI, let description):
|
||||||
@@ -480,9 +480,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentEmojiPicker(for itemID: TimelineItemIdentifier) {
|
private func presentEmojiPicker(for itemID: TimelineItemIdentifier, selectedEmoji: Set<String>) {
|
||||||
let params = EmojiPickerScreenCoordinatorParameters(emojiProvider: emojiProvider,
|
let params = EmojiPickerScreenCoordinatorParameters(emojiProvider: emojiProvider,
|
||||||
itemID: itemID)
|
itemID: itemID, selectedEmojis: selectedEmoji)
|
||||||
let coordinator = EmojiPickerScreenCoordinator(parameters: params)
|
let coordinator = EmojiPickerScreenCoordinator(parameters: params)
|
||||||
coordinator.callback = { [weak self] action in
|
coordinator.callback = { [weak self] action in
|
||||||
switch action {
|
switch action {
|
||||||
@@ -632,7 +632,7 @@ private extension RoomFlowCoordinator {
|
|||||||
case roomDetails(roomID: String, isRoot: Bool)
|
case roomDetails(roomID: String, isRoot: Bool)
|
||||||
case mediaUploadPicker(roomID: String, source: MediaPickerScreenSource)
|
case mediaUploadPicker(roomID: String, source: MediaPickerScreenSource)
|
||||||
case mediaUploadPreview(roomID: String, fileURL: URL)
|
case mediaUploadPreview(roomID: String, fileURL: URL)
|
||||||
case emojiPicker(roomID: String, itemID: TimelineItemIdentifier)
|
case emojiPicker(roomID: String, itemID: TimelineItemIdentifier, selectedEmojis: Set<String>)
|
||||||
case mapNavigator(roomID: String)
|
case mapNavigator(roomID: String)
|
||||||
case roomMemberDetails(roomID: String, member: HashableRoomMemberWrapper)
|
case roomMemberDetails(roomID: String, member: HashableRoomMemberWrapper)
|
||||||
case messageForwarding(roomID: String, itemID: TimelineItemIdentifier)
|
case messageForwarding(roomID: String, itemID: TimelineItemIdentifier)
|
||||||
@@ -659,7 +659,7 @@ private extension RoomFlowCoordinator {
|
|||||||
case presentMediaUploadPreview(fileURL: URL)
|
case presentMediaUploadPreview(fileURL: URL)
|
||||||
case dismissMediaUploadPreview
|
case dismissMediaUploadPreview
|
||||||
|
|
||||||
case presentEmojiPicker(itemID: TimelineItemIdentifier)
|
case presentEmojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set<String>)
|
||||||
case dismissEmojiPicker
|
case dismissEmojiPicker
|
||||||
|
|
||||||
case presentMapNavigator(interactionMode: StaticLocationInteractionMode)
|
case presentMapNavigator(interactionMode: StaticLocationInteractionMode)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import SwiftUI
|
|||||||
struct EmojiPickerScreenCoordinatorParameters {
|
struct EmojiPickerScreenCoordinatorParameters {
|
||||||
let emojiProvider: EmojiProviderProtocol
|
let emojiProvider: EmojiProviderProtocol
|
||||||
let itemID: TimelineItemIdentifier
|
let itemID: TimelineItemIdentifier
|
||||||
|
let selectedEmojis: Set<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EmojiPickerScreenCoordinatorAction {
|
enum EmojiPickerScreenCoordinatorAction {
|
||||||
@@ -52,6 +53,6 @@ final class EmojiPickerScreenCoordinator: CoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func toPresentable() -> AnyView {
|
func toPresentable() -> AnyView {
|
||||||
AnyView(EmojiPickerScreen(context: viewModel.context))
|
AnyView(EmojiPickerScreen(context: viewModel.context, selectedEmojis: parameters.selectedEmojis))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import SwiftUI
|
|||||||
struct EmojiPickerScreen: View {
|
struct EmojiPickerScreen: View {
|
||||||
@ObservedObject var context: EmojiPickerScreenViewModel.Context
|
@ObservedObject var context: EmojiPickerScreenViewModel.Context
|
||||||
|
|
||||||
|
var selectedEmojis = Set<String>()
|
||||||
@State var searchString = ""
|
@State var searchString = ""
|
||||||
@State private var isSearching = false
|
@State private var isSearching = false
|
||||||
|
|
||||||
@@ -39,7 +40,10 @@ struct EmojiPickerScreen: View {
|
|||||||
context.send(viewAction: .emojiTapped(emoji: emoji))
|
context.send(viewAction: .emojiTapped(emoji: emoji))
|
||||||
} label: {
|
} label: {
|
||||||
Text(emoji.value)
|
Text(emoji.value)
|
||||||
|
.padding(9.0)
|
||||||
.font(.compound.headingXL)
|
.font(.compound.headingXL)
|
||||||
|
.background(Circle()
|
||||||
|
.foregroundColor(emojiBackgroundColor(for: emoji.value)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} header: {
|
} header: {
|
||||||
@@ -65,6 +69,14 @@ struct EmojiPickerScreen: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func emojiBackgroundColor(for emoji: String) -> Color {
|
||||||
|
if selectedEmojis.contains(emoji) {
|
||||||
|
return .compound.bgActionPrimaryRest
|
||||||
|
} else {
|
||||||
|
return .clear
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ToolbarContentBuilder
|
@ToolbarContentBuilder
|
||||||
var toolbar: some ToolbarContent {
|
var toolbar: some ToolbarContent {
|
||||||
ToolbarItem(placement: .cancellationAction) {
|
ToolbarItem(placement: .cancellationAction) {
|
||||||
@@ -92,12 +104,12 @@ struct EmojiPickerScreen_Previews: PreviewProvider {
|
|||||||
static let viewModel = EmojiPickerScreenViewModel(emojiProvider: EmojiProvider())
|
static let viewModel = EmojiPickerScreenViewModel(emojiProvider: EmojiProvider())
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
EmojiPickerScreen(context: viewModel.context)
|
EmojiPickerScreen(context: viewModel.context, selectedEmojis: ["😀", "😄"])
|
||||||
.previewDisplayName("Screen")
|
.previewDisplayName("Screen")
|
||||||
|
|
||||||
Text("Timeline view")
|
Text("Timeline view")
|
||||||
.sheet(isPresented: .constant(true)) {
|
.sheet(isPresented: .constant(true)) {
|
||||||
EmojiPickerScreen(context: viewModel.context)
|
EmojiPickerScreen(context: viewModel.context, selectedEmojis: ["😀", "😄"])
|
||||||
}
|
}
|
||||||
.previewDisplayName("Sheet")
|
.previewDisplayName("Sheet")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ enum RoomScreenCoordinatorAction {
|
|||||||
case presentRoomDetails
|
case presentRoomDetails
|
||||||
case presentLocationPicker
|
case presentLocationPicker
|
||||||
case presentLocationViewer(body: String, geoURI: GeoURI, description: String?)
|
case presentLocationViewer(body: String, geoURI: GeoURI, description: String?)
|
||||||
case presentEmojiPicker(itemID: TimelineItemIdentifier)
|
case presentEmojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set<String>)
|
||||||
case presentRoomMemberDetails(member: RoomMemberProxyProtocol)
|
case presentRoomMemberDetails(member: RoomMemberProxyProtocol)
|
||||||
case presentMessageForwarding(itemID: TimelineItemIdentifier)
|
case presentMessageForwarding(itemID: TimelineItemIdentifier)
|
||||||
}
|
}
|
||||||
@@ -67,8 +67,8 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
|||||||
switch action {
|
switch action {
|
||||||
case .displayRoomDetails:
|
case .displayRoomDetails:
|
||||||
actionsSubject.send(.presentRoomDetails)
|
actionsSubject.send(.presentRoomDetails)
|
||||||
case .displayEmojiPicker(let itemID):
|
case .displayEmojiPicker(let itemID, let selectedEmojis):
|
||||||
actionsSubject.send(.presentEmojiPicker(itemID: itemID))
|
actionsSubject.send(.presentEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis))
|
||||||
case .displayReportContent(let itemID, let senderID):
|
case .displayReportContent(let itemID, let senderID):
|
||||||
actionsSubject.send(.presentReportContent(itemID: itemID, senderID: senderID))
|
actionsSubject.send(.presentReportContent(itemID: itemID, senderID: senderID))
|
||||||
case .displayCameraPicker:
|
case .displayCameraPicker:
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import OrderedCollections
|
|||||||
|
|
||||||
enum RoomScreenViewModelAction {
|
enum RoomScreenViewModelAction {
|
||||||
case displayRoomDetails
|
case displayRoomDetails
|
||||||
case displayEmojiPicker(itemID: TimelineItemIdentifier)
|
case displayEmojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set<String>)
|
||||||
case displayReportContent(itemID: TimelineItemIdentifier, senderID: String)
|
case displayReportContent(itemID: TimelineItemIdentifier, senderID: String)
|
||||||
case displayCameraPicker
|
case displayCameraPicker
|
||||||
case displayMediaPicker
|
case displayMediaPicker
|
||||||
|
|||||||
@@ -728,8 +728,13 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
// MARK: - Reactions
|
// MARK: - Reactions
|
||||||
|
|
||||||
private func showEmojiPicker(for itemID: TimelineItemIdentifier) {
|
private func showEmojiPicker(for itemID: TimelineItemIdentifier) {
|
||||||
guard let item = state.timelineViewState.itemsDictionary[itemID.timelineID], item.isReactable else { return }
|
guard let timelineItem = timelineController.timelineItems.first(where: { $0.id == itemID }),
|
||||||
callback?(.displayEmojiPicker(itemID: itemID))
|
timelineItem.isReactable,
|
||||||
|
let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let selectedEmojis = Set(eventTimelineItem.properties.reactions.compactMap { $0.isHighlighted ? $0.key : nil })
|
||||||
|
callback?(.displayEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func showReactionSummary(for itemID: TimelineItemIdentifier, selectedKey: String) {
|
private func showReactionSummary(for itemID: TimelineItemIdentifier, selectedKey: String) {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import SwiftUI
|
|||||||
struct TimelineItemBubbledStylerView<Content: View>: View {
|
struct TimelineItemBubbledStylerView<Content: View>: View {
|
||||||
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
||||||
@Environment(\.timelineGroupStyle) private var timelineGroupStyle
|
@Environment(\.timelineGroupStyle) private var timelineGroupStyle
|
||||||
@Environment(\.layoutDirection) var layoutDirection: LayoutDirection
|
|
||||||
|
|
||||||
let timelineItem: EventBasedTimelineItemProtocol
|
let timelineItem: EventBasedTimelineItemProtocol
|
||||||
@ViewBuilder let content: () -> Content
|
@ViewBuilder let content: () -> Content
|
||||||
@@ -41,11 +40,6 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
|||||||
return 8
|
return 8
|
||||||
}
|
}
|
||||||
|
|
||||||
var reactionsLayoutDirection: LayoutDirection {
|
|
||||||
guard timelineItem.isOutgoing else { return layoutDirection }
|
|
||||||
return layoutDirection == .leftToRight ? .rightToLeft : .leftToRight
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack(alignment: .trailingFirstTextBaseline) {
|
ZStack(alignment: .trailingFirstTextBaseline) {
|
||||||
VStack(alignment: alignment, spacing: -12) {
|
VStack(alignment: alignment, spacing: -12) {
|
||||||
@@ -109,8 +103,8 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
|||||||
if !timelineItem.properties.reactions.isEmpty {
|
if !timelineItem.properties.reactions.isEmpty {
|
||||||
TimelineReactionsView(itemID: timelineItem.id,
|
TimelineReactionsView(itemID: timelineItem.id,
|
||||||
reactions: timelineItem.properties.reactions,
|
reactions: timelineItem.properties.reactions,
|
||||||
|
isLayoutRTL: timelineItem.isOutgoing,
|
||||||
collapsed: context.reactionsCollapsedBinding(for: timelineItem.id))
|
collapsed: context.reactionsCollapsedBinding(for: timelineItem.id))
|
||||||
.environment(\.layoutDirection, reactionsLayoutDirection)
|
|
||||||
// Workaround to stop the message long press stealing the touch from the reaction buttons
|
// Workaround to stop the message long press stealing the touch from the reaction buttons
|
||||||
.onTapGesture { }
|
.onTapGesture { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,11 +22,16 @@ struct TimelineReactionsView: View {
|
|||||||
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
|
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
|
||||||
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
||||||
@Environment(\.layoutDirection) private var layoutDirection: LayoutDirection
|
@Environment(\.layoutDirection) private var layoutDirection: LayoutDirection
|
||||||
@Namespace private var animation
|
|
||||||
|
|
||||||
let itemID: TimelineItemIdentifier
|
let itemID: TimelineItemIdentifier
|
||||||
let reactions: [AggregatedReaction]
|
let reactions: [AggregatedReaction]
|
||||||
|
var isLayoutRTL = false
|
||||||
@Binding var collapsed: Bool
|
@Binding var collapsed: Bool
|
||||||
|
|
||||||
|
var reactionsLayoutDirection: LayoutDirection {
|
||||||
|
guard isLayoutRTL else { return layoutDirection }
|
||||||
|
return layoutDirection == .leftToRight ? .rightToLeft : .leftToRight
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
CollapsibleReactionLayout(itemSpacing: 4, rowSpacing: 4, collapsed: collapsed, rowsBeforeCollapsible: 2) {
|
CollapsibleReactionLayout(itemSpacing: 4, rowSpacing: 4, collapsed: collapsed, rowsBeforeCollapsible: 2) {
|
||||||
@@ -38,6 +43,7 @@ struct TimelineReactionsView: View {
|
|||||||
context.send(viewAction: .reactionSummary(itemID: itemID, key: key))
|
context.send(viewAction: .reactionSummary(itemID: itemID, key: key))
|
||||||
}
|
}
|
||||||
.reactionLayoutItem(.reaction)
|
.reactionLayoutItem(.reaction)
|
||||||
|
.environment(\.layoutDirection, layoutDirection)
|
||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
collapsed.toggle()
|
collapsed.toggle()
|
||||||
@@ -46,6 +52,7 @@ struct TimelineReactionsView: View {
|
|||||||
.transaction { $0.animation = nil }
|
.transaction { $0.animation = nil }
|
||||||
}
|
}
|
||||||
.reactionLayoutItem(.expandCollapse)
|
.reactionLayoutItem(.expandCollapse)
|
||||||
|
.environment(\.layoutDirection, layoutDirection)
|
||||||
Button {
|
Button {
|
||||||
context.send(viewAction: .displayEmojiPicker(itemID: itemID))
|
context.send(viewAction: .displayEmojiPicker(itemID: itemID))
|
||||||
} label: {
|
} label: {
|
||||||
@@ -53,6 +60,7 @@ struct TimelineReactionsView: View {
|
|||||||
}
|
}
|
||||||
.reactionLayoutItem(.addMore)
|
.reactionLayoutItem(.addMore)
|
||||||
}
|
}
|
||||||
|
.environment(\.layoutDirection, reactionsLayoutDirection)
|
||||||
.animation(.easeInOut(duration: 0.1), value: reactions)
|
.animation(.easeInOut(duration: 0.1), value: reactions)
|
||||||
.padding(.leading, 4)
|
.padding(.leading, 4)
|
||||||
}
|
}
|
||||||
@@ -86,10 +94,12 @@ struct TimelineReactionButtonLabel<Content: View>: View {
|
|||||||
|
|
||||||
struct TimelineCollapseButtonLabel: View {
|
struct TimelineCollapseButtonLabel: View {
|
||||||
var collapsed: Bool
|
var collapsed: Bool
|
||||||
|
@ScaledMetric(relativeTo: .subheadline) private var lineHeight = 20
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
TimelineReactionButtonLabel {
|
TimelineReactionButtonLabel {
|
||||||
Text(collapsed ? L10n.screenRoomReactionsShowMore : L10n.screenRoomReactionsShowLess)
|
Text(collapsed ? L10n.screenRoomReactionsShowMore : L10n.screenRoomReactionsShowLess)
|
||||||
|
.frame(height: lineHeight, alignment: .center)
|
||||||
.padding(.vertical, 6)
|
.padding(.vertical, 6)
|
||||||
.padding(.horizontal, 12)
|
.padding(.horizontal, 12)
|
||||||
.font(.compound.bodyMD)
|
.font(.compound.bodyMD)
|
||||||
@@ -102,6 +112,7 @@ struct TimelineReactionButton: View {
|
|||||||
let reaction: AggregatedReaction
|
let reaction: AggregatedReaction
|
||||||
let toggleReaction: (String) -> Void
|
let toggleReaction: (String) -> Void
|
||||||
let showReactionSummary: (String) -> Void
|
let showReactionSummary: (String) -> Void
|
||||||
|
@ScaledMetric(relativeTo: .subheadline) private var lineHeight = 20
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
label
|
label
|
||||||
@@ -116,14 +127,18 @@ struct TimelineReactionButton: View {
|
|||||||
var label: some View {
|
var label: some View {
|
||||||
TimelineReactionButtonLabel(isHighlighted: reaction.isHighlighted) {
|
TimelineReactionButtonLabel(isHighlighted: reaction.isHighlighted) {
|
||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
|
// Designs have bodyMD for the key but practically this makes
|
||||||
|
// emojis too big. bodySM gives a more appropriate size when compared
|
||||||
|
// to the count text and the lineHeight/padding in the designs.
|
||||||
Text(reaction.displayKey)
|
Text(reaction.displayKey)
|
||||||
.font(.compound.bodyMD)
|
.font(.compound.bodySM)
|
||||||
if reaction.count > 1 {
|
if reaction.count > 1 {
|
||||||
Text(String(reaction.count))
|
Text(String(reaction.count))
|
||||||
.font(.compound.bodyMD)
|
.font(.compound.bodyMD)
|
||||||
.foregroundColor(textColor)
|
.foregroundColor(textColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.frame(height: lineHeight, alignment: .center)
|
||||||
.padding(.vertical, 6)
|
.padding(.vertical, 6)
|
||||||
.padding(.horizontal, 12)
|
.padding(.horizontal, 12)
|
||||||
}
|
}
|
||||||
@@ -157,16 +172,16 @@ struct TimelineReactionViewPreviewsContainer: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
TimelineReactionsView(itemID: .init(timelineID: "1"), reactions: [
|
TimelineReactionsView(itemID: .init(timelineID: "1"),
|
||||||
AggregatedReaction.mockReactionWithLongText,
|
reactions: [AggregatedReaction.mockReactionWithLongText,
|
||||||
AggregatedReaction.mockReactionWithLongTextRTL
|
AggregatedReaction.mockReactionWithLongTextRTL],
|
||||||
], collapsed: .constant(true))
|
collapsed: .constant(true))
|
||||||
|
Divider()
|
||||||
TimelineReactionsView(itemID: .init(timelineID: "2"), reactions: Array(AggregatedReaction.mockReactions.prefix(3)), collapsed: .constant(true))
|
TimelineReactionsView(itemID: .init(timelineID: "2"), reactions: Array(AggregatedReaction.mockReactions.prefix(3)), collapsed: .constant(true))
|
||||||
Divider()
|
Divider()
|
||||||
TimelineReactionsView(itemID: .init(timelineID: "3"), reactions: AggregatedReaction.mockReactions, collapsed: $collapseState1)
|
TimelineReactionsView(itemID: .init(timelineID: "3"), reactions: AggregatedReaction.mockReactions, collapsed: $collapseState1)
|
||||||
Divider()
|
Divider()
|
||||||
TimelineReactionsView(itemID: .init(timelineID: "4"), reactions: AggregatedReaction.mockReactions, collapsed: $collapseState2)
|
TimelineReactionsView(itemID: .init(timelineID: "4"), reactions: AggregatedReaction.mockReactions, isLayoutRTL: true, collapsed: $collapseState2)
|
||||||
.environment(\.layoutDirection, .rightToLeft)
|
|
||||||
}
|
}
|
||||||
.background(Color.red)
|
.background(Color.red)
|
||||||
.frame(maxWidth: 250, alignment: .leading)
|
.frame(maxWidth: 250, alignment: .leading)
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ extension RoomTimelineItemProtocol {
|
|||||||
public struct TimelineItemMenu: View {
|
public struct TimelineItemMenu: View {
|
||||||
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
||||||
@Environment(\.dismiss) private var dismiss
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
@ScaledMetric private var addMoreButtonIconSize = 24
|
||||||
|
|
||||||
let item: EventBasedTimelineItemProtocol
|
let item: EventBasedTimelineItemProtocol
|
||||||
let actions: TimelineItemMenuActions
|
let actions: TimelineItemMenuActions
|
||||||
@@ -209,8 +210,12 @@ public struct TimelineItemMenu: View {
|
|||||||
context.send(viewAction: .displayEmojiPicker(itemID: item.id))
|
context.send(viewAction: .displayEmojiPicker(itemID: item.id))
|
||||||
}
|
}
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "plus.circle")
|
Image(asset: Asset.Images.timelineReactionAddMore)
|
||||||
.font(.compound.headingLG)
|
.resizable()
|
||||||
|
.frame(width: addMoreButtonIconSize, height: addMoreButtonIconSize)
|
||||||
|
.frame(maxHeight: .infinity, alignment: .center)
|
||||||
|
.foregroundColor(.compound.iconSecondary)
|
||||||
|
.padding(10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
@@ -224,11 +229,10 @@ public struct TimelineItemMenu: View {
|
|||||||
context.send(viewAction: .toggleReaction(key: emoji, itemID: item.id))
|
context.send(viewAction: .toggleReaction(key: emoji, itemID: item.id))
|
||||||
} label: {
|
} label: {
|
||||||
Text(emoji)
|
Text(emoji)
|
||||||
.padding(8.0)
|
.padding(8)
|
||||||
.font(.compound.headingLG)
|
.font(.compound.headingLG)
|
||||||
.background(Circle()
|
.background(Circle()
|
||||||
.foregroundColor(reactionBackgroundColor(for: emoji)))
|
.foregroundColor(reactionBackgroundColor(for: emoji)))
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:8538909b4eb58f736fb4be966726cdf0c000caf3b9e285f98b97326f8cbb5964
|
oid sha256:be453ffed9fb2bc7d301ad59faa4feba3934cc637c7cac47205bb075e756d4a5
|
||||||
size 297160
|
size 282665
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:359a17ae2ab3c7f11348eeab34bb416097704dedbf6ff95d198fbd420e243a02
|
oid sha256:f6a1f2a37c3f3c889bbc7f7cc197ea7ab7a8dbca114e04f4b924f925bfdbc962
|
||||||
size 297042
|
size 282544
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:57441eaeba880a5cccab827ac5b9817b2a3605a219553ad37bb67ea78b871d3a
|
oid sha256:e5e0398327a1242ad715e12402222129a25616cfe42714a796866ae63d8ec199
|
||||||
size 364717
|
size 351436
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:8b1788c514b01a82938458a571d52550eea9552575a0c85d2b62a0a4bb19fde2
|
oid sha256:20792aab7f279c0aaae66dfd1f75b2698deb927cc2f469019c4780b308c3e80f
|
||||||
size 364426
|
size 351159
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:05d9d894f8c655acd034615af8fc5098bf6adb64b475219d1a58da9eea9697e6
|
oid sha256:1823d5d7ad95177d49e015b65d81b43a7bfbe8806f8051a8808a73c3f70c3101
|
||||||
size 298240
|
size 283737
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:ef52847f31d85009e37e06340fc4ad21317f907be2fbf4a873a43f4b4740d5c6
|
oid sha256:4d36119a386b8e94d2ccd199fa2550baa4c8bfd2e18c4cf61e3c673316386d74
|
||||||
size 298123
|
size 283614
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:af701156aa31a33ba3787cdcf29e9c9d0e96bedc017308c88acedae08c80f12c
|
oid sha256:97ca898098ea034b94adcffb6cf3a45907ef2c4fff2774863b37f354d1882354
|
||||||
size 357151
|
size 344628
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:ea0906e449a16419f404bf56233440193dfc071cac5fb668c711eedca657ed76
|
oid sha256:e812e041b7b9bc8ad82ae0164f618ad8eda9bb322f5c546dc694d4d38941dc65
|
||||||
size 356860
|
size 344351
|
||||||
|
|||||||
Reference in New Issue
Block a user