mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
prevent replies to LLS timeline items, and live location sharing in threads
This commit is contained in:
@@ -705,7 +705,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
stateMachine.tryEvent(.presentEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis),
|
||||
userInfo: EventUserInfo(animated: animated, timelineController: timelineController))
|
||||
case .presentLocationPicker:
|
||||
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .picker),
|
||||
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .picker(shouldShowLiveLocationOption: true)),
|
||||
userInfo: EventUserInfo(animated: animated, timelineController: timelineController))
|
||||
case .presentPollForm(let mode):
|
||||
stateMachine.tryEvent(.presentPollForm(mode: mode),
|
||||
@@ -814,7 +814,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
stateMachine.tryEvent(.presentMediaUploadPreview(mediaURLs: mediaURLs),
|
||||
userInfo: EventUserInfo(animated: animated, timelineController: timelineController))
|
||||
case .presentLocationPicker:
|
||||
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .picker),
|
||||
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .picker(shouldShowLiveLocationOption: false)),
|
||||
userInfo: EventUserInfo(animated: animated, timelineController: timelineController))
|
||||
case .presentLiveLocationViewer(let sender, let initialLiveLocationShare):
|
||||
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .viewLive(sender: sender, initialLiveLocationShare: initialLiveLocationShare)),
|
||||
@@ -1167,7 +1167,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
timelineController: TimelineControllerProtocol,
|
||||
animated: Bool) {
|
||||
let stackCoordinator = NavigationStackCoordinator()
|
||||
|
||||
|
||||
let params = LocationSharingScreenCoordinatorParameters(interactionMode: interactionMode,
|
||||
mapURLBuilder: flowParameters.appSettings.mapTilerConfiguration,
|
||||
roomProxy: roomProxy,
|
||||
|
||||
@@ -224,7 +224,7 @@ extension RoomFlowCoordinator {
|
||||
case (.mediaEventsTimeline, .presentMessageForwarding(forwardingItem: let forwardingItem)):
|
||||
return .messageForwarding(forwardingItem: forwardingItem, previousState: fromState)
|
||||
|
||||
case (.room, .presentMapNavigator(_)):
|
||||
case (.room, .presentMapNavigator):
|
||||
return .mapNavigator(previousState: fromState)
|
||||
|
||||
case (.room, .presentPollForm):
|
||||
@@ -271,7 +271,7 @@ extension RoomFlowCoordinator {
|
||||
case (.thread, .presentMessageForwarding(let forwardingItem)):
|
||||
return .messageForwarding(forwardingItem: forwardingItem, previousState: fromState)
|
||||
|
||||
case (.thread, .presentMapNavigator(_)):
|
||||
case (.thread, .presentMapNavigator):
|
||||
return .mapNavigator(previousState: fromState)
|
||||
|
||||
case (.thread, .presentPollForm):
|
||||
|
||||
@@ -25,9 +25,21 @@ enum LocationSharingScreenViewModelAction {
|
||||
}
|
||||
|
||||
enum LocationSharingInteractionMode: Hashable {
|
||||
case picker
|
||||
case picker(shouldShowLiveLocationOption: Bool)
|
||||
case viewStatic(StaticLocationData)
|
||||
case viewLive(sender: TimelineItemSender?, initialLiveLocationShare: LiveLocationShare?)
|
||||
|
||||
var isPicker: Bool {
|
||||
if case .picker = self { return true }
|
||||
return false
|
||||
}
|
||||
|
||||
var shouldShowLiveLocationOption: Bool {
|
||||
if case .picker(let shouldShowLiveLocationOption) = self {
|
||||
return shouldShowLiveLocationOption
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
struct LocationSharingScreenViewState: BindableState {
|
||||
|
||||
@@ -46,7 +46,7 @@ class LocationSharingScreenViewModel: LocationSharingScreenViewModelType, Locati
|
||||
self.analytics = analytics
|
||||
self.userIndicatorController = userIndicatorController
|
||||
self.notificationCenter = notificationCenter
|
||||
|
||||
|
||||
super.init(initialViewState: .init(interactionMode: interactionMode,
|
||||
mapURLBuilder: mapURLBuilder,
|
||||
ownUserID: roomProxy.ownUserID),
|
||||
@@ -332,17 +332,20 @@ class LocationSharingScreenViewModel: LocationSharingScreenViewModelType, Locati
|
||||
extension LocationSharingScreenViewModel {
|
||||
enum MockType {
|
||||
case picker
|
||||
case pickerWithoutLiveLocationOption
|
||||
case staticSenderLocation
|
||||
case staticPinLocation
|
||||
case viewLive
|
||||
case viewLiveEmpty
|
||||
}
|
||||
|
||||
|
||||
static func mock(type: MockType,
|
||||
senderID: String = "@dan:matrix.org") -> LocationSharingScreenViewModel {
|
||||
let interactionMode: LocationSharingInteractionMode = switch type {
|
||||
case .picker:
|
||||
.picker
|
||||
.picker(shouldShowLiveLocationOption: true)
|
||||
case .pickerWithoutLiveLocationOption:
|
||||
.picker(shouldShowLiveLocationOption: false)
|
||||
case .staticPinLocation:
|
||||
.viewStatic(.init(sender: .init(id: senderID),
|
||||
geoURI: .init(latitude: 41.9027835,
|
||||
|
||||
@@ -11,7 +11,14 @@ import SwiftUI
|
||||
struct LocationPickerSheet: View {
|
||||
@Bindable var context: LocationSharingScreenViewModel.Context
|
||||
@State private var height: CGFloat = .zero
|
||||
|
||||
|
||||
/// Fixes an iOS 26 sheet issue
|
||||
/// if the content doesn't meet a certain size
|
||||
/// additional insets are added.
|
||||
private var additionalHeight: CGFloat {
|
||||
context.viewState.interactionMode.shouldShowLiveLocationOption ? 0 : 28
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
Text(L10n.screenSharingLocationOptionSheetTitle)
|
||||
@@ -34,12 +41,14 @@ struct LocationPickerSheet: View {
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
context.send(viewAction: .startLiveLocation)
|
||||
} label: {
|
||||
LocationPickerLabel(text: L10n.actionShareLiveLocation,
|
||||
icon: \.locationPinSolid,
|
||||
iconColor: .compound.iconAccentPrimary)
|
||||
if context.viewState.interactionMode.shouldShowLiveLocationOption {
|
||||
Button {
|
||||
context.send(viewAction: .startLiveLocation)
|
||||
} label: {
|
||||
LocationPickerLabel(text: L10n.actionShareLiveLocation,
|
||||
icon: \.locationPinSolid,
|
||||
iconColor: .compound.iconAccentPrimary)
|
||||
}
|
||||
}
|
||||
}
|
||||
.readHeight($height)
|
||||
@@ -47,7 +56,7 @@ struct LocationPickerSheet: View {
|
||||
.presentationBackground(.compound.bgCanvasDefault)
|
||||
.presentationBackgroundInteraction(.enabled)
|
||||
.presentationDragIndicator(.hidden)
|
||||
.presentationDetents([.height(height)])
|
||||
.presentationDetents([.height(height + additionalHeight)])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ struct LocationSharingScreen: View {
|
||||
private var mainContent: some View {
|
||||
mapView
|
||||
.ignoresSafeArea(edges: .bottom)
|
||||
.track(screen: context.viewState.interactionMode == .picker ? .LocationSend : .LocationView)
|
||||
.track(screen: context.viewState.interactionMode.isPicker ? .LocationSend : .LocationView)
|
||||
.navigationTitle(L10n.screenViewLocationTitle)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar { toolbar }
|
||||
@@ -71,7 +71,7 @@ struct LocationSharingScreen: View {
|
||||
}
|
||||
|
||||
private var mapSafeAreaEdges: Edge.Set {
|
||||
context.viewState.interactionMode == .picker ? .horizontal : [.horizontal, .bottom]
|
||||
context.viewState.interactionMode.isPicker ? .horizontal : [.horizontal, .bottom]
|
||||
}
|
||||
|
||||
@ToolbarContentBuilder
|
||||
@@ -126,19 +126,26 @@ struct LocationSharingScreen: View {
|
||||
|
||||
struct LocationSharingScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = LocationSharingScreenViewModel.mock(type: .staticSenderLocation)
|
||||
|
||||
|
||||
static let withoutLiveSharingViewModel = LocationSharingScreenViewModel.mock(type: .pickerWithoutLiveLocationOption)
|
||||
|
||||
static let pinViewModel = LocationSharingScreenViewModel.mock(type: .staticPinLocation)
|
||||
|
||||
|
||||
static let pickerViewModel = LocationSharingScreenViewModel.mock(type: .picker)
|
||||
|
||||
|
||||
static let liveLocationViewModel = LocationSharingScreenViewModel.mock(type: .viewLive)
|
||||
|
||||
|
||||
static var previews: some View {
|
||||
ElementNavigationStack {
|
||||
LocationSharingScreen(context: pickerViewModel.context)
|
||||
}
|
||||
.previewDisplayName("Picker")
|
||||
|
||||
|
||||
ElementNavigationStack {
|
||||
LocationSharingScreen(context: withoutLiveSharingViewModel.context)
|
||||
}
|
||||
.previewDisplayName("Picker without live location sharing")
|
||||
|
||||
ElementNavigationStack {
|
||||
LocationSharingScreen(context: viewModel.context)
|
||||
}
|
||||
|
||||
@@ -440,7 +440,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
timestamp: eventItemProxy.timestamp,
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: eventItemProxy.isEditable,
|
||||
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
|
||||
// Workaround until https://github.com/matrix-org/matrix-rust-sdk/pull/6563 is merged.
|
||||
canBeRepliedTo: false,
|
||||
sender: eventItemProxy.sender,
|
||||
content: .init(from: liveLocationContent, timestamp: eventItemProxy.timestamp),
|
||||
properties: .init(replyDetails: buildTimelineItemReplyDetails(messageLikeContent.inReplyTo),
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:64737509400fe27cdb017b8f66cffe8c0807f958827cff84a9ce5484db0ca3fc
|
||||
size 80109
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:64737509400fe27cdb017b8f66cffe8c0807f958827cff84a9ce5484db0ca3fc
|
||||
size 80109
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:08e72ae0c7d34108690371b29952267b1ac06bb62f203515f3c5e4143efd2ca8
|
||||
size 38511
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:08e72ae0c7d34108690371b29952267b1ac06bb62f203515f3c5e4143efd2ca8
|
||||
size 38511
|
||||
@@ -402,7 +402,7 @@ struct LocationSharingScreenViewModelTests {
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
mediaProvider: MediaProviderMock(configuration: .init()))
|
||||
|
||||
|
||||
// Initially no annotations and no map center since sender and share are both nil.
|
||||
#expect(context.viewState.annotations.isEmpty)
|
||||
#expect(context.mapCenterLocation == nil)
|
||||
@@ -428,7 +428,7 @@ struct LocationSharingScreenViewModelTests {
|
||||
private mutating func setupViewModel(liveLocationManagerConfiguration: LiveLocationManagerMock.Configuration = .init(),
|
||||
members: [RoomMemberProxyMock] = .allMembersAsAdmin) {
|
||||
timelineProxy = TimelineProxyMock(.init())
|
||||
viewModel = LocationSharingScreenViewModel(interactionMode: .picker,
|
||||
viewModel = LocationSharingScreenViewModel(interactionMode: .picker(shouldShowLiveLocationOption: true),
|
||||
mapURLBuilder: ServiceLocator.shared.settings.mapTilerConfiguration,
|
||||
roomProxy: JoinedRoomProxyMock(.init(members: members)),
|
||||
timelineController: MockTimelineController(timelineProxy: timelineProxy),
|
||||
@@ -438,11 +438,11 @@ struct LocationSharingScreenViewModelTests {
|
||||
mediaProvider: MediaProviderMock(configuration: .init()))
|
||||
viewModel.state.bindings.isLocationAuthorized = true
|
||||
}
|
||||
|
||||
|
||||
private mutating func setupViewModel(liveLocationManagerMock: LiveLocationManagerMock,
|
||||
members: [RoomMemberProxyMock] = .allMembersAsAdmin) {
|
||||
timelineProxy = TimelineProxyMock(.init())
|
||||
viewModel = LocationSharingScreenViewModel(interactionMode: .picker,
|
||||
viewModel = LocationSharingScreenViewModel(interactionMode: .picker(shouldShowLiveLocationOption: true),
|
||||
mapURLBuilder: ServiceLocator.shared.settings.mapTilerConfiguration,
|
||||
roomProxy: JoinedRoomProxyMock(.init(members: members)),
|
||||
timelineController: MockTimelineController(timelineProxy: timelineProxy),
|
||||
|
||||
Reference in New Issue
Block a user