hide the forward action on live location shares (#6091)

Live location shares have no message event content, so forwarding always failed silently. Exclude them from `isForwardable` matching polls logic
This commit is contained in:
Ghazi Tozri
2026-09-01 15:23:20 +02:00
committed by GitHub
parent 53df7dd24d
commit b4a36ad465
3 changed files with 93 additions and 1 deletions
+4
View File
@@ -56,6 +56,7 @@
05FF0CD80EDAB3A7C0D4700A /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; };
0638CBDE3098B1C3F23AFCFA /* MXLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111B698739E3410E2CDB7144 /* MXLog.swift */; };
065EAB39F3F3AB4F6BD2A362 /* AppLockSetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DD166C3625EE426203FA29 /* AppLockSetupTests.swift */; };
0668BECCF11E8EE6936CDF16 /* TimelineItemMenuActionProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C98C243A90369929D669873D /* TimelineItemMenuActionProviderTests.swift */; };
066A1E9B94723EE9F3038044 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.swift */; };
06B55882911B4BF5B14E9851 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 227AC5D71A4CE43512062243 /* URL.swift */; };
06D17F7813AA931FF18FD5D0 /* SDKListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE5CD2993048222B64C45006 /* SDKListener.swift */; };
@@ -2924,6 +2925,7 @@
C90514BE9B8ACCBCF0AD2489 /* ComposerToolbarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarViewModel.swift; sourceTree = "<group>"; };
C95ADE8D9527523572532219 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = hu; path = hu.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
C97F8963B14EB0AF3940DDBF /* NotificationSettingsEditScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenRoomCell.swift; sourceTree = "<group>"; };
C98C243A90369929D669873D /* TimelineItemMenuActionProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenuActionProviderTests.swift; sourceTree = "<group>"; };
C99FDEEB71173C4C6FA2734C /* UserSessionFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionFlowCoordinator.swift; sourceTree = "<group>"; };
C9AC2CC94FA06F728883B694 /* KnockRequestsListScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListScreenViewModelTests.swift; sourceTree = "<group>"; };
C9E535B3388755B65C34CD10 /* UnsupportedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineView.swift; sourceTree = "<group>"; };
@@ -5275,6 +5277,7 @@
6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.swift */,
2CEBCB9676FCD1D0F13188DD /* StringTests.swift */,
9AA3AF94A06D319BB37E52DA /* TimelineItemFactoryTests.swift */,
C98C243A90369929D669873D /* TimelineItemMenuActionProviderTests.swift */,
ED0AD0C652385F69FA90FAF5 /* TimelineMediaPreviewDataSourceTests.swift */,
5C1F000589F2CEE6B03ECFAB /* TimelineMediaPreviewViewModelTests.swift */,
F968FDB68F9D4CB9010FED70 /* TimelineStateTests.swift */,
@@ -8372,6 +8375,7 @@
1FEC0A4EC6E6DF693C16B32A /* StringTests.swift in Sources */,
E75CE800B3E64D0F7F8E228D /* TemplateScreenViewModelTests.swift in Sources */,
0D4EB2ABAA5FE8CB10FDBCB8 /* TimelineItemFactoryTests.swift in Sources */,
0668BECCF11E8EE6936CDF16 /* TimelineItemMenuActionProviderTests.swift in Sources */,
C02DE5F62C81FB9E173C3D2F /* TimelineMediaPreviewDataSourceTests.swift in Sources */,
F6BF52CB027393EE03CEC523 /* TimelineMediaPreviewViewModelTests.swift in Sources */,
75E55A763FE8BA64FB8513E4 /* TimelineStateTests.swift in Sources */,
@@ -28,7 +28,7 @@ nonisolated extension EventBasedTimelineItemProtocol {
}
var isForwardable: Bool {
isRemoteMessage && !(self is PollRoomTimelineItem)
isRemoteMessage && !(self is PollRoomTimelineItem) && !(self is LiveLocationRoomTimelineItem)
}
var isRemoteMessage: Bool {
@@ -0,0 +1,88 @@
//
// Copyright 2026 Element Creations Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
@testable import ElementX
import Testing
struct TimelineItemMenuActionProviderTests {
@Test
func liveLocationShareIsNotForwardable() throws {
let item = makeLiveLocationItem(isLive: true)
let actions = try #require(makeActions(for: item))
let hasForward = actions.actions.contains(where: \.isForward)
#expect(!hasForward)
}
@Test
func endedLiveLocationShareIsNotForwardable() throws {
let item = makeLiveLocationItem(isLive: false)
let actions = try #require(makeActions(for: item))
let hasForward = actions.actions.contains(where: \.isForward)
#expect(!hasForward)
}
@Test
func pollIsNotForwardable() throws {
let item = PollRoomTimelineItem.mock(poll: .emptyDisclosed)
let actions = try #require(makeActions(for: item))
let hasForward = actions.actions.contains(where: \.isForward)
#expect(!hasForward)
}
@Test
func textMessageIsForwardable() throws {
let item = TextRoomTimelineItem(id: .randomEvent,
timestamp: .mock,
isOutgoing: false,
isEditable: false,
canBeRepliedTo: true,
sender: .init(id: "@alice:matrix.org"),
content: .init(body: "Hello"))
let actions = try #require(makeActions(for: item))
let hasForward = actions.actions.contains(where: \.isForward)
#expect(hasForward)
}
// MARK: - Helpers
private func makeLiveLocationItem(isLive: Bool) -> LiveLocationRoomTimelineItem {
.init(id: .randomEvent,
timestamp: .mock,
isOutgoing: false,
isEditable: false,
canBeRepliedTo: true,
sender: .init(id: "@alice:matrix.org"),
content: .init(isLive: isLive, timeoutDate: .mock, lastGeoURI: nil))
}
private func makeActions(for item: RoomTimelineItemProtocol) -> TimelineItemMenuActions? {
TimelineItemMenuActionProvider(timelineItem: item,
canCurrentUserSendMessage: true,
canCurrentUserRedactSelf: true,
canCurrentUserRedactOthers: false,
canCurrentUserPin: true,
pinnedEventIDs: [],
isViewSourceEnabled: true,
areThreadsEnabled: true,
timelineKind: .live,
emojiProvider: EmojiProvider(appSettings: .volatile()))
.makeActions()
}
}
private extension TimelineItemMenuAction {
var isForward: Bool {
if case .forward = self {
return true
}
return false
}
}