diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift
index d07f6efb5..7998caf91 100644
--- a/Config/BuildSettings.swift
+++ b/Config/BuildSettings.swift
@@ -15,6 +15,7 @@
//
import Foundation
+import Keys
/// BuildSettings provides settings computed at build time.
/// In future, it may be automatically generated from xcconfig files
@@ -364,4 +365,8 @@ final class BuildSettings: NSObject {
return true
}
+
+ // MARK: - Location Sharing
+
+ static let tileServerMapURL = URL(string: "https://api.maptiler.com/maps/streets/style.json?key=" + RiotKeys().mapTilerAPIKey)!
}
diff --git a/Riot/Assets/en.lproj/InfoPlist.strings b/Riot/Assets/en.lproj/InfoPlist.strings
index e8ac01167..a9513a6ed 100644
--- a/Riot/Assets/en.lproj/InfoPlist.strings
+++ b/Riot/Assets/en.lproj/InfoPlist.strings
@@ -21,4 +21,4 @@
"NSContactsUsageDescription" = "Element will show your contacts so you can invite them to chat.";
"NSCalendarsUsageDescription" = "See your scheduled meetings in the app.";
"NSFaceIDUsageDescription" = "Face ID is used to access your app.";
-"NSLocationWhenInUseUsageDescription" = "Element needs access to your location before being able to share it.";
+"NSLocationWhenInUseUsageDescription" = "When you share your location to people, Element needs access to show them a map.";
diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings
index babe98289..51ed3037c 100644
--- a/Riot/Assets/en.lproj/Vector.strings
+++ b/Riot/Assets/en.lproj/Vector.strings
@@ -66,6 +66,7 @@
"less" = "Less";
"open" = "Open";
"done" = "Done";
+"ok" = "OK";
// Call Bar
"callbar_only_single_active" = "Tap to return to the call (%@)";
@@ -1821,8 +1822,6 @@ Tap the + to start adding people.";
"poll_edit_form_post_failure_subtitle" = "Please try again";
-"poll_edit_form_post_failure_action" = "OK";
-
"poll_timeline_one_vote" = "1 vote";
"poll_timeline_votes_count" = "%lu votes";
@@ -1845,14 +1844,10 @@ Tap the + to start adding people.";
"poll_timeline_vote_not_registered_subtitle" = "Sorry, your vote was not registered, please try again";
-"poll_timeline_vote_not_registered_action" = "OK";
-
"poll_timeline_not_closed_title" = "Failed to end poll";
"poll_timeline_not_closed_subtitle" = "Please try again";
-"poll_timeline_not_closed_action" = "OK";
-
// MARK: - Location sharing
"location_sharing_title" = "Location";
@@ -1861,14 +1856,12 @@ Tap the + to start adding people.";
"location_sharing_share_action" = "Share";
-"location_sharing_loading_map_error_title" = "Failed to load map";
+"location_sharing_loading_map_error_title" = "Element could not load the map. Please try again later.";
-"location_sharing_loading_map_error_message" = "Please try again";
+"location_sharing_locating_user_error_title" = "Element could not access your location. Please try again later.";
-"location_sharing_locating_user_error_title" = "Failed locating user";
+"location_sharing_invalid_authorization_error_title" = "Element does not have permission to access your location. You can enable access in Settings > Location";
-"location_sharing_locating_user_error_message" = "Please try again";
+"location_sharing_invalid_authorization_not_now" = "Not now";
-"location_sharing_invalid_authorization_error_title" = "Failed getting authorization";
-
-"location_sharing_invalid_authorization_error_message" = "Please update your system settings";
+"location_sharing_invalid_authorization_settings" = "Settings";
diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift
index 9fbe34e43..273a1b5be 100644
--- a/Riot/Generated/Strings.swift
+++ b/Riot/Generated/Strings.swift
@@ -2195,27 +2195,23 @@ public class VectorL10n: NSObject {
public static var locationSharingCloseAction: String {
return VectorL10n.tr("Vector", "location_sharing_close_action")
}
- /// Please update your system settings
- public static var locationSharingInvalidAuthorizationErrorMessage: String {
- return VectorL10n.tr("Vector", "location_sharing_invalid_authorization_error_message")
- }
- /// Failed getting authorization
+ /// Element does not have permission to access your location. You can enable access in Settings > Location
public static var locationSharingInvalidAuthorizationErrorTitle: String {
return VectorL10n.tr("Vector", "location_sharing_invalid_authorization_error_title")
}
- /// Please try again
- public static var locationSharingLoadingMapErrorMessage: String {
- return VectorL10n.tr("Vector", "location_sharing_loading_map_error_message")
+ /// Not now
+ public static var locationSharingInvalidAuthorizationNotNow: String {
+ return VectorL10n.tr("Vector", "location_sharing_invalid_authorization_not_now")
}
- /// Failed to load map
+ /// Settings
+ public static var locationSharingInvalidAuthorizationSettings: String {
+ return VectorL10n.tr("Vector", "location_sharing_invalid_authorization_settings")
+ }
+ /// Element could not load the map. Please try again later.
public static var locationSharingLoadingMapErrorTitle: String {
return VectorL10n.tr("Vector", "location_sharing_loading_map_error_title")
}
- /// Please try again
- public static var locationSharingLocatingUserErrorMessage: String {
- return VectorL10n.tr("Vector", "location_sharing_locating_user_error_message")
- }
- /// Failed locating user
+ /// Element could not access your location. Please try again later.
public static var locationSharingLocatingUserErrorTitle: String {
return VectorL10n.tr("Vector", "location_sharing_locating_user_error_title")
}
@@ -2327,6 +2323,10 @@ public class VectorL10n: NSObject {
public static var off: String {
return VectorL10n.tr("Vector", "off")
}
+ /// OK
+ public static var ok: String {
+ return VectorL10n.tr("Vector", "ok")
+ }
/// On
public static var on: String {
return VectorL10n.tr("Vector", "on")
@@ -2479,10 +2479,6 @@ public class VectorL10n: NSObject {
public static var pollEditFormPollQuestionOrTopic: String {
return VectorL10n.tr("Vector", "poll_edit_form_poll_question_or_topic")
}
- /// OK
- public static var pollEditFormPostFailureAction: String {
- return VectorL10n.tr("Vector", "poll_edit_form_post_failure_action")
- }
/// Please try again
public static var pollEditFormPostFailureSubtitle: String {
return VectorL10n.tr("Vector", "poll_edit_form_post_failure_subtitle")
@@ -2495,10 +2491,6 @@ public class VectorL10n: NSObject {
public static var pollEditFormQuestionOrTopic: String {
return VectorL10n.tr("Vector", "poll_edit_form_question_or_topic")
}
- /// OK
- public static var pollTimelineNotClosedAction: String {
- return VectorL10n.tr("Vector", "poll_timeline_not_closed_action")
- }
/// Please try again
public static var pollTimelineNotClosedSubtitle: String {
return VectorL10n.tr("Vector", "poll_timeline_not_closed_subtitle")
@@ -2539,10 +2531,6 @@ public class VectorL10n: NSObject {
public static func pollTimelineTotalVotesNotVoted(_ p1: Int) -> String {
return VectorL10n.tr("Vector", "poll_timeline_total_votes_not_voted", p1)
}
- /// OK
- public static var pollTimelineVoteNotRegisteredAction: String {
- return VectorL10n.tr("Vector", "poll_timeline_vote_not_registered_action")
- }
/// Sorry, your vote was not registered, please try again
public static var pollTimelineVoteNotRegisteredSubtitle: String {
return VectorL10n.tr("Vector", "poll_timeline_vote_not_registered_subtitle")
diff --git a/Riot/Modules/Room/Location/RoomTimelineLocationView.swift b/Riot/Modules/Room/Location/RoomTimelineLocationView.swift
index 75c6da792..4e945e168 100644
--- a/Riot/Modules/Room/Location/RoomTimelineLocationView.swift
+++ b/Riot/Modules/Room/Location/RoomTimelineLocationView.swift
@@ -25,7 +25,6 @@ class RoomTimelineLocationView: UIView, NibLoadable, MGLMapViewDelegate {
static let mapHeight: CGFloat = 300.0
static let mapTilerKey = RiotKeys().mapTilerAPIKey
static let mapZoomLevel = 15.0
- static let mapStyleURLString = URL(string: "https://api.maptiler.com/maps/streets/style.json?key=\(Constants.mapTilerKey)")
static let cellBorderRadius: CGFloat = 1.0
static let cellCornerRadius: CGFloat = 8.0
}
@@ -54,7 +53,7 @@ class RoomTimelineLocationView: UIView, NibLoadable, MGLMapViewDelegate {
override func awakeFromNib() {
super.awakeFromNib()
- mapView = MGLMapView(frame: .zero, styleURL: Constants.mapStyleURLString)
+ mapView = MGLMapView(frame: .zero, styleURL: BuildSettings.tileServerMapURL)
mapView.delegate = self
mapView.logoView.isHidden = true
mapView.attributionButton.isHidden = true
diff --git a/Riot/SupportingFiles/Info.plist b/Riot/SupportingFiles/Info.plist
index 4c4d11e2f..9d95fe929 100644
--- a/Riot/SupportingFiles/Info.plist
+++ b/Riot/SupportingFiles/Info.plist
@@ -66,7 +66,7 @@
NSSiriUsageDescription
Siri is used to perform calls even from the lock screen.
NSLocationWhenInUseUsageDescription
- Element needs access to your location before being able to share it.
+ When you share your location to people, Element needs access to show them a map.
UIBackgroundModes
audio
diff --git a/RiotSwiftUI/Info.plist b/RiotSwiftUI/Info.plist
index a74882893..c72d62e92 100644
--- a/RiotSwiftUI/Info.plist
+++ b/RiotSwiftUI/Info.plist
@@ -21,6 +21,6 @@
CFBundleVersion
$(CURRENT_PROJECT_VERSION)
NSLocationWhenInUseUsageDescription
- Element needs access to your location before being able to share it.
+ When you share your location to people, Element needs access to show them a map.
diff --git a/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/LocationSharingCoordinator.swift b/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/LocationSharingCoordinator.swift
index dc77cd6c3..bcff3fbca 100644
--- a/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/LocationSharingCoordinator.swift
+++ b/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/LocationSharingCoordinator.swift
@@ -56,7 +56,7 @@ final class LocationSharingCoordinator: Coordinator {
matrixItemId: parameters.user.userId,
displayName: parameters.user.displayname)
- let viewModel = LocationSharingViewModel(accessToken: RiotKeys().mapTilerAPIKey, avatarData: avatarData)
+ let viewModel = LocationSharingViewModel(tileServerMapURL: BuildSettings.tileServerMapURL, avatarData: avatarData)
let view = LocationSharingView(context: viewModel.context)
.addDependency(AvatarService.instantiate(mediaManager: parameters.mediaManager))
diff --git a/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingModels.swift b/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingModels.swift
index 88310f4d1..f4ceb2941 100644
--- a/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingModels.swift
+++ b/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingModels.swift
@@ -46,7 +46,7 @@ enum LocationSharingViewModelResult {
@available(iOS 14, *)
struct LocationSharingViewState: BindableState {
- let accessToken: String
+ let tileServerMapURL: URL
let avatarData: AvatarInputProtocol
var shareButtonEnabled: Bool = true
var showLoadingIndicator: Bool = false
@@ -71,6 +71,6 @@ struct ErrorAlertInfo: Identifiable {
let id: AlertType
let title: String
- let message: String
- let callback: (() -> Void)?
+ let primaryButton: (String, (() -> Void)?)
+ let secondaryButton: (String, (() -> Void)?)?
}
diff --git a/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingScreenState.swift b/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingScreenState.swift
index 44699462b..01c77b09d 100644
--- a/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingScreenState.swift
+++ b/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingScreenState.swift
@@ -16,6 +16,7 @@
import Foundation
import SwiftUI
+import Keys
@available(iOS 14.0, *)
enum MockLocationSharingScreenState: MockScreenState, CaseIterable {
@@ -26,7 +27,8 @@ enum MockLocationSharingScreenState: MockScreenState, CaseIterable {
}
var screenView: ([Any], AnyView) {
- let viewModel = LocationSharingViewModel(accessToken: "bDAfUcrMPWTAB1KB38r6",
+ let mapURL = URL(string: "https://api.maptiler.com/maps/streets/style.json?key=" + RiotKeys().mapTilerAPIKey)!
+ let viewModel = LocationSharingViewModel(tileServerMapURL: mapURL,
avatarData: AvatarInput(mxContentUri: "", matrixItemId: "", displayName: "Alice"))
return ([viewModel],
AnyView(LocationSharingView(context: viewModel.context)
diff --git a/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingViewModel.swift b/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingViewModel.swift
index b4b85f29c..b4dda5af3 100644
--- a/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingViewModel.swift
+++ b/RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingViewModel.swift
@@ -30,18 +30,18 @@ class LocationSharingViewModel: LocationSharingViewModelType {
// MARK: Public
- let accessToken: String
+ let tileServerMapURL: URL
let avatarData: AvatarInputProtocol
var completion: ((LocationSharingViewModelResult) -> Void)?
// MARK: - Setup
- init(accessToken: String, avatarData: AvatarInputProtocol) {
- self.accessToken = accessToken
+ init(tileServerMapURL: URL, avatarData: AvatarInputProtocol) {
+ self.tileServerMapURL = tileServerMapURL
self.avatarData = avatarData
- super.init(initialViewState: LocationSharingViewState(accessToken: accessToken, avatarData: avatarData))
+ super.init(initialViewState: LocationSharingViewState(tileServerMapURL: tileServerMapURL, avatarData: avatarData))
state.errorSubject.sink { [weak self] error in
guard let self = self else { return }
@@ -69,26 +69,26 @@ class LocationSharingViewModel: LocationSharingViewModelType {
switch action {
case .error(let error, let completion):
- let alertCallback: () -> Void = {
- completion?(.cancel)
- }
-
switch error {
case .failedLoadingMap:
state.bindings.alertInfo = ErrorAlertInfo(id: .mapLoadingError,
title: VectorL10n.locationSharingLoadingMapErrorTitle,
- message: VectorL10n.locationSharingLoadingMapErrorMessage,
- callback: alertCallback)
+ primaryButton: (VectorL10n.ok, { completion?(.cancel) }),
+ secondaryButton: nil)
case .failedLocatingUser:
state.bindings.alertInfo = ErrorAlertInfo(id: .userLocatingError,
title: VectorL10n.locationSharingLocatingUserErrorTitle,
- message: VectorL10n.locationSharingLocatingUserErrorMessage,
- callback: alertCallback)
+ primaryButton: (VectorL10n.ok, { completion?(.cancel) }),
+ secondaryButton: nil)
case .invalidLocationAuthorization:
state.bindings.alertInfo = ErrorAlertInfo(id: .authorizationError,
title: VectorL10n.locationSharingInvalidAuthorizationErrorTitle,
- message: VectorL10n.locationSharingInvalidAuthorizationErrorMessage,
- callback: alertCallback)
+ primaryButton: (VectorL10n.locationSharingInvalidAuthorizationNotNow, { completion?(.cancel) }),
+ secondaryButton: (VectorL10n.locationSharingInvalidAuthorizationSettings, {
+ if let applicationSettingsURL = URL(string:UIApplication.openSettingsURLString) {
+ UIApplication.shared.open(applicationSettingsURL)
+ }
+ }))
default:
break
}
@@ -103,8 +103,8 @@ class LocationSharingViewModel: LocationSharingViewModelType {
if error != nil {
state.bindings.alertInfo = ErrorAlertInfo(id: .locationSharingError,
title: VectorL10n.locationSharingInvalidAuthorizationErrorTitle,
- message: VectorL10n.locationSharingInvalidAuthorizationErrorMessage,
- callback: nil)
+ primaryButton: (VectorL10n.ok, nil),
+ secondaryButton: nil)
}
}
}
diff --git a/RiotSwiftUI/Modules/Room/LocationSharing/Test/Unit/LocationSharingViewModelTests.swift b/RiotSwiftUI/Modules/Room/LocationSharing/Test/Unit/LocationSharingViewModelTests.swift
index 702b336be..dc51dd83e 100644
--- a/RiotSwiftUI/Modules/Room/LocationSharing/Test/Unit/LocationSharingViewModelTests.swift
+++ b/RiotSwiftUI/Modules/Room/LocationSharing/Test/Unit/LocationSharingViewModelTests.swift
@@ -26,7 +26,7 @@ class LocationSharingViewModelTests: XCTestCase {
var cancellables = Set()
override func setUpWithError() throws {
- context = viewModel.context
+
}
func testInitialState() {
diff --git a/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingMapView.swift b/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingMapView.swift
index aa515338d..edbeb4298 100644
--- a/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingMapView.swift
+++ b/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingMapView.swift
@@ -22,18 +22,15 @@ import Mapbox
struct LocationSharingMapView: UIViewRepresentable {
private struct Constants {
static let mapZoomLevel = 15.0
- static let mapStyleURLString = "https://api.maptiler.com/maps/streets/style.json?key="
}
- let accessToken: String
+ let tileServerMapURL: URL
let avatarData: AvatarInputProtocol
let errorSubject: PassthroughSubject
@Binding var userLocation: CLLocationCoordinate2D?
func makeUIView(context: Context) -> some UIView {
- let url = URL(string: Constants.mapStyleURLString + accessToken)
-
- let mapView = MGLMapView(frame: .zero, styleURL: url)
+ let mapView = MGLMapView(frame: .zero, styleURL: tileServerMapURL)
mapView.delegate = context.coordinator
mapView.logoView.isHidden = true
diff --git a/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift b/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift
index f760c7dc3..caa4e5846 100644
--- a/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift
+++ b/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift
@@ -32,7 +32,7 @@ struct LocationSharingView: View {
var body: some View {
NavigationView {
- LocationSharingMapView(accessToken: context.viewState.accessToken,
+ LocationSharingMapView(tileServerMapURL: context.viewState.tileServerMapURL,
avatarData: context.viewState.avatarData,
errorSubject: context.viewState.errorSubject,
userLocation: $context.userLocation)
@@ -57,10 +57,20 @@ struct LocationSharingView: View {
.navigationBarTitleDisplayMode(.inline)
.ignoresSafeArea()
.alert(item: $context.alertInfo) { info in
- Alert(title: Text(info.title), message: Text(info.message), dismissButton:
- .default(Text(VectorL10n.pollTimelineVoteNotRegisteredAction)) {
- info.callback?()
- })
+ if let secondaryButton = info.secondaryButton {
+ return Alert(title: Text(info.title),
+ primaryButton: .default(Text(info.primaryButton.0)) {
+ info.primaryButton.1?()
+ },
+ secondaryButton: .default(Text(secondaryButton.0)) {
+ secondaryButton.1?()
+ })
+ } else {
+ return Alert(title: Text(info.title),
+ dismissButton: .default(Text(info.primaryButton.0)) {
+ info.primaryButton.1?()
+ })
+ }
}
}
.accentColor(theme.colors.accent)
diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift
index 9e81488a5..57f3a63a3 100644
--- a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift
+++ b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift
@@ -87,7 +87,7 @@ struct PollEditForm: View {
.alert(isPresented: $viewModel.showsFailureAlert) {
Alert(title: Text(VectorL10n.pollEditFormPostFailureTitle),
message: Text(VectorL10n.pollEditFormPostFailureSubtitle),
- dismissButton: .default(Text(VectorL10n.pollEditFormPostFailureAction)))
+ dismissButton: .default(Text(VectorL10n.ok)))
}
.frame(minHeight: proxy.size.height) // Make the VStack fill the ScrollView's parent
.toolbar {
diff --git a/RiotSwiftUI/Modules/Room/PollTimeline/View/PollTimelineView.swift b/RiotSwiftUI/Modules/Room/PollTimeline/View/PollTimelineView.swift
index 22a94bb68..70efcc067 100644
--- a/RiotSwiftUI/Modules/Room/PollTimeline/View/PollTimelineView.swift
+++ b/RiotSwiftUI/Modules/Room/PollTimeline/View/PollTimelineView.swift
@@ -50,7 +50,7 @@ struct PollTimelineView: View {
.alert(isPresented: $viewModel.showsClosingFailureAlert) {
Alert(title: Text(VectorL10n.pollTimelineNotClosedTitle),
message: Text(VectorL10n.pollTimelineNotClosedSubtitle),
- dismissButton: .default(Text(VectorL10n.pollTimelineNotClosedAction)))
+ dismissButton: .default(Text(VectorL10n.ok)))
}
}
.disabled(poll.closed)
@@ -62,7 +62,7 @@ struct PollTimelineView: View {
.alert(isPresented: $viewModel.showsAnsweringFailureAlert) {
Alert(title: Text(VectorL10n.pollTimelineVoteNotRegisteredTitle),
message: Text(VectorL10n.pollTimelineVoteNotRegisteredSubtitle),
- dismissButton: .default(Text(VectorL10n.pollTimelineVoteNotRegisteredAction)))
+ dismissButton: .default(Text(VectorL10n.ok)))
}
}
.padding([.horizontal, .top], 2.0)