vector-im/element-ios/issues/5298 - Various tweaks following code review.

This commit is contained in:
Stefan Ceriu
2022-01-04 14:12:24 +02:00
committed by Stefan Ceriu
parent 0bac754ad9
commit 7161b99d1c
26 changed files with 248 additions and 211 deletions

View File

@@ -23,13 +23,6 @@ import Keys
final class BuildSettings: NSObject {
// MARK: - Bundle Settings
static var bundleDisplayName: String {
guard let bundleDisplayName = Bundle.app.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String else {
fatalError("CFBundleDisplayName should be defined")
}
return bundleDisplayName
}
static var applicationGroupIdentifier: String {
guard let applicationGroupIdentifier = Bundle.app.object(forInfoDictionaryKey: "applicationGroupIdentifier") as? String else {
fatalError("applicationGroupIdentifier should be defined")

View File

@@ -950,7 +950,7 @@ Tap the + to start adding people.";
// Analytics
"analytics_prompt_title" = "Help improve %@";
"analytics_prompt_message_new_user" = "Help us identify issues and improve Element by sharing anonymous usage data. To understand how people use multiple devices, well generate a random identifier, shared by your devices.";
"analytics_prompt_message_new_user" = "Help us identify issues and improve %@ by sharing anonymous usage data. To understand how people use multiple devices, well generate a random identifier, shared by your devices.";
"analytics_prompt_message_upgrade" = "You previously consented to share anonymous usage data with us. Now, to help understand how people use multiple devices, well generate a random identifier, shared by your devices.";
/* Note: The placeholder is for the contents of analytics_prompt_terms_link_new_user */
"analytics_prompt_terms_new_user" = "You can read all our terms %@.";
@@ -1752,7 +1752,7 @@ Tap the + to start adding people.";
"spaces_coming_soon_title" = "Coming soon";
"spaces_add_rooms_coming_soon_title" = "Adding rooms coming soon";
"spaces_invites_coming_soon_title" = "Invites coming soon";
"spaces_coming_soon_detail" = "This feature hasnt been implemented here, but its on the way. For now, you can do that with Element on your computer.";
"spaces_coming_soon_detail" = "This feature hasnt been implemented here, but its on the way. For now, you can do that with %@ on your computer.";
"space_participants_action_remove" = "Remove from this space";
"space_participants_action_ban" = "Ban from this space";
"space_home_show_all_rooms" = "Show all rooms";
@@ -1856,11 +1856,11 @@ Tap the + to start adding people.";
"location_sharing_share_action" = "Share";
"location_sharing_loading_map_error_title" = "Element could not load the map. Please try again later.";
"location_sharing_loading_map_error_title" = "%@ could not load the map. Please try again later.";
"location_sharing_locating_user_error_title" = "Element could not access your location. Please try again later.";
"location_sharing_locating_user_error_title" = "%@ could not access your location. Please try again later.";
"location_sharing_invalid_authorization_error_title" = "Element does not have permission to access your location. You can enable access in Settings > Location";
"location_sharing_invalid_authorization_error_title" = "%@ does not have permission to access your location. You can enable access in Settings > Location";
"location_sharing_invalid_authorization_not_now" = "Not now";

View File

@@ -35,9 +35,9 @@ public class VectorL10n: NSObject {
public static func activeCallDetails(_ p1: String) -> String {
return VectorL10n.tr("Vector", "active_call_details", p1)
}
/// Help us identify issues and improve Element by sharing anonymous usage data. To understand how people use multiple devices, well generate a random identifier, shared by your devices.
public static var analyticsPromptMessageNewUser: String {
return VectorL10n.tr("Vector", "analytics_prompt_message_new_user")
/// Help us identify issues and improve %@ by sharing anonymous usage data. To understand how people use multiple devices, well generate a random identifier, shared by your devices.
public static func analyticsPromptMessageNewUser(_ p1: String) -> String {
return VectorL10n.tr("Vector", "analytics_prompt_message_new_user", p1)
}
/// You previously consented to share anonymous usage data with us. Now, to help understand how people use multiple devices, well generate a random identifier, shared by your devices.
public static var analyticsPromptMessageUpgrade: String {
@@ -2195,9 +2195,9 @@ public class VectorL10n: NSObject {
public static var locationSharingCloseAction: String {
return VectorL10n.tr("Vector", "location_sharing_close_action")
}
/// 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")
/// %@ does not have permission to access your location. You can enable access in Settings > Location
public static func locationSharingInvalidAuthorizationErrorTitle(_ p1: String) -> String {
return VectorL10n.tr("Vector", "location_sharing_invalid_authorization_error_title", p1)
}
/// Not now
public static var locationSharingInvalidAuthorizationNotNow: String {
@@ -2207,13 +2207,13 @@ public class VectorL10n: NSObject {
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")
/// %@ could not load the map. Please try again later.
public static func locationSharingLoadingMapErrorTitle(_ p1: String) -> String {
return VectorL10n.tr("Vector", "location_sharing_loading_map_error_title", p1)
}
/// 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")
/// %@ could not access your location. Please try again later.
public static func locationSharingLocatingUserErrorTitle(_ p1: String) -> String {
return VectorL10n.tr("Vector", "location_sharing_locating_user_error_title", p1)
}
/// Open in Apple Maps
public static var locationSharingOpenAppleMaps: String {
@@ -5155,9 +5155,9 @@ public class VectorL10n: NSObject {
public static var spacesAddRoomsComingSoonTitle: String {
return VectorL10n.tr("Vector", "spaces_add_rooms_coming_soon_title")
}
/// This feature hasnt been implemented here, but its on the way. For now, you can do that with Element on your computer.
public static var spacesComingSoonDetail: String {
return VectorL10n.tr("Vector", "spaces_coming_soon_detail")
/// This feature hasnt been implemented here, but its on the way. For now, you can do that with %@ on your computer.
public static func spacesComingSoonDetail(_ p1: String) -> String {
return VectorL10n.tr("Vector", "spaces_coming_soon_detail", p1)
}
/// Coming soon
public static var spacesComingSoonTitle: String {

View File

@@ -19,17 +19,14 @@ import Foundation
/// Used to handle the application information
@objcMembers
final class AppInfo: NSObject {
// MARK: - Constants
/// Current application information
static var current: AppInfo {
let appDisplayName = BuildSettings.bundleDisplayName
let buildInfo: BuildInfo = BuildInfo()
return AppInfo(displayName: appDisplayName,
return AppInfo(displayName: self.bundleDisplayName,
appVersion: AppVersion.current,
buildInfo: buildInfo)
buildInfo: BuildInfo())
}
// MARK: - Properties
@@ -52,4 +49,11 @@ final class AppInfo: NSObject {
self.appVersion = appVersion
self.buildInfo = buildInfo
}
private static var bundleDisplayName: String {
guard let bundleDisplayName = Bundle.app.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String else {
fatalError("CFBundleDisplayName should be defined")
}
return bundleDisplayName
}
}

View File

@@ -55,7 +55,7 @@ class FindYourContactsFooterView: UIView, NibLoadable, Themable {
button.layer.cornerRadius = 8
titleLabel.text = VectorL10n.findYourContactsTitle
messageLabel.text = VectorL10n.findYourContactsMessage(BuildSettings.bundleDisplayName)
messageLabel.text = VectorL10n.findYourContactsMessage(AppInfo.current.displayName)
button.setTitle(VectorL10n.findYourContactsButtonTitle, for: .normal)
footerLabel.text = VectorL10n.findYourContactsFooter
}

View File

@@ -61,7 +61,7 @@ final class InviteFriendsPresenter: NSObject {
private func buildShareText(with userId: String) -> String {
let userMatrixToLink: String = MXTools.permalinkToUser(withUserId: userId)
return VectorL10n.inviteFriendsShareText(BuildSettings.bundleDisplayName, userMatrixToLink)
return VectorL10n.inviteFriendsShareText(AppInfo.current.displayName, userMatrixToLink)
}
private func present(_ viewController: UIViewController, animated: Bool) {

View File

@@ -19,8 +19,10 @@ import Reusable
import Mapbox
import Keys
class RoomTimelineLocationView: UIView, NibLoadable, MGLMapViewDelegate {
class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegate {
// MARK: - Constants
private struct Constants {
static let mapHeight: CGFloat = 300.0
static let mapTilerKey = RiotKeys().mapTilerAPIKey
@@ -29,8 +31,8 @@ class RoomTimelineLocationView: UIView, NibLoadable, MGLMapViewDelegate {
static let cellCornerRadius: CGFloat = 8.0
}
// MARK: Properties
// MARK: - Private
// MARK: - Properties
// MARK: Private
@IBOutlet private var descriptionContainerView: UIView!
@IBOutlet private var descriptionLabel: UILabel!
@@ -38,7 +40,7 @@ class RoomTimelineLocationView: UIView, NibLoadable, MGLMapViewDelegate {
private var mapView: MGLMapView!
private var annotationView: LocationUserMarkerView?
// MARK: - Public
// MARK: Public
var locationDescription: String? {
get {
@@ -67,9 +69,6 @@ class RoomTimelineLocationView: UIView, NibLoadable, MGLMapViewDelegate {
clipsToBounds = true
layer.borderWidth = Constants.cellBorderRadius
layer.cornerRadius = Constants.cellCornerRadius
NotificationCenter.default.addObserver(self, selector: #selector(updateTheme), name: .themeServiceDidChangeTheme, object: nil)
updateTheme()
}
// MARK: - Public
@@ -99,17 +98,17 @@ class RoomTimelineLocationView: UIView, NibLoadable, MGLMapViewDelegate {
mapView.addAnnotation(pointAnnotation)
}
// MARK: - Themable
func update(theme: Theme) {
descriptionLabel.textColor = theme.colors.primaryContent
descriptionLabel.font = theme.fonts.footnote
layer.borderColor = theme.colors.quinaryContent.cgColor
}
// MARK: - MGLMapViewDelegate
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
return annotationView
}
// MARK: - Private
@objc private func updateTheme() {
descriptionLabel.textColor = ThemeService.shared().theme.colors.primaryContent
descriptionLabel.font = ThemeService.shared().theme.fonts.footnote
layer.borderColor = ThemeService.shared().theme.colors.quinaryContent.cgColor
}
}

View File

@@ -30,9 +30,6 @@ final class RoomCoordinator: NSObject, RoomCoordinatorProtocol {
private let activityIndicatorPresenter: ActivityIndicatorPresenterType
private var selectedEventId: String?
private var pollEditFormCoordinator: PollEditFormCoordinator?
private var locationSharingCoordinator: LocationSharingCoordinator?
private var roomDataSourceManager: MXKRoomDataSourceManager {
return MXKRoomDataSourceManager.sharedManager(forMatrixSession: self.parameters.session)
}
@@ -199,6 +196,56 @@ final class RoomCoordinator: NSObject, RoomCoordinatorProtocol {
completion?()
}
private func startLocationCoordinatorWithEvent(_ event: MXEvent? = nil, bubbleData: MXKRoomBubbleCellDataStoring? = nil) {
guard #available(iOS 14.0, *) else {
return
}
guard let navigationRouter = self.navigationRouter,
let mediaManager = mxSession?.mediaManager,
let user = mxSession?.myUser else {
MXLog.error("[RoomCoordinator] Invalid location sharing coordinator parameters. Returning.")
return
}
var avatarData: AvatarInputProtocol
if event != nil, let bubbleData = bubbleData {
avatarData = AvatarInput(mxContentUri: bubbleData.senderAvatarUrl,
matrixItemId: bubbleData.senderId,
displayName: bubbleData.senderDisplayName)
} else {
avatarData = AvatarInput(mxContentUri: user.avatarUrl,
matrixItemId: user.userId,
displayName: user.displayname)
}
var location: CLLocationCoordinate2D?
if let locationContent = event?.location {
location = CLLocationCoordinate2D(latitude: locationContent.latitude, longitude: locationContent.longitude)
}
let parameters = LocationSharingCoordinatorParameters(roomDataSource: roomViewController.roomDataSource,
mediaManager: mediaManager,
avatarData: avatarData,
location: location)
let coordinator = LocationSharingCoordinator(parameters: parameters)
coordinator.completion = { [weak self, weak coordinator] in
guard let self = self, let coordinator = coordinator else {
return
}
self.navigationRouter?.dismissModule(animated: true, completion: nil)
self.remove(childCoordinator: coordinator)
}
add(childCoordinator: coordinator)
navigationRouter.present(coordinator, animated: true)
coordinator.start()
}
}
// MARK: - RoomIdentifiable
@@ -262,10 +309,22 @@ extension RoomCoordinator: RoomViewControllerDelegate {
return
}
let parameters = PollEditFormCoordinatorParameters(navigationRouter: self.navigationRouter, room: roomViewController.roomDataSource.room)
pollEditFormCoordinator = PollEditFormCoordinator(parameters: parameters)
let parameters = PollEditFormCoordinatorParameters(room: roomViewController.roomDataSource.room)
let coordinator = PollEditFormCoordinator(parameters: parameters)
pollEditFormCoordinator?.start()
coordinator.completion = { [weak self, weak coordinator] in
guard let self = self, let coordinator = coordinator else {
return
}
self.navigationRouter?.dismissModule(animated: true, completion: nil)
self.remove(childCoordinator: coordinator)
}
add(childCoordinator: coordinator)
navigationRouter?.present(coordinator, animated: true)
coordinator.start()
}
func roomViewControllerDidRequestLocationSharingFormPresentation(_ roomViewController: RoomViewController) {
@@ -291,45 +350,4 @@ extension RoomCoordinator: RoomViewControllerDelegate {
PollTimelineProvider.shared.pollTimelineCoordinatorForEventIdentifier(eventIdentifier)?.endPoll()
}
// MARK: - Private
private func startLocationCoordinatorWithEvent(_ event: MXEvent? = nil, bubbleData: MXKRoomBubbleCellDataStoring? = nil) {
guard #available(iOS 14.0, *) else {
return
}
guard let navigationRouter = self.navigationRouter,
let mediaManager = mxSession?.mediaManager,
let user = mxSession?.myUser else {
MXLog.error("[RoomCoordinator] Invalid location sharing coordinator parameters. Returning.")
return
}
var avatarData: AvatarInputProtocol
if event != nil, let bubbleData = bubbleData {
avatarData = AvatarInput(mxContentUri: bubbleData.senderAvatarUrl,
matrixItemId: bubbleData.senderId,
displayName: bubbleData.senderDisplayName)
} else {
avatarData = AvatarInput(mxContentUri: user.avatarUrl,
matrixItemId: user.userId,
displayName: user.displayname)
}
var location: CLLocationCoordinate2D?
if let locationContent = event?.location {
location = CLLocationCoordinate2D(latitude: locationContent.latitude, longitude: locationContent.longitude)
}
let parameters = LocationSharingCoordinatorParameters(navigationRouter: navigationRouter,
roomDataSource: roomViewController.roomDataSource,
mediaManager: mediaManager,
avatarData: avatarData,
location: location)
locationSharingCoordinator = LocationSharingCoordinator(parameters: parameters)
locationSharingCoordinator?.start()
}
}

View File

@@ -32,6 +32,7 @@ class LocationBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable
return
}
locationView.update(theme: ThemeService.shared().theme)
locationView.locationDescription = locationContent.locationDescription
let location = CLLocationCoordinate2D(latitude: locationContent.latitude, longitude: locationContent.longitude)

View File

@@ -154,7 +154,7 @@ final class SpaceMemberListViewController: RoomParticipantsViewController {
// MARK: - Actions
@objc private func onAddParticipantButtonPressed() {
self.errorPresenter.presentError(from: self, title: VectorL10n.spacesInvitesComingSoonTitle, message: VectorL10n.spacesComingSoonDetail, animated: true, handler: nil)
self.errorPresenter.presentError(from: self, title: VectorL10n.spacesInvitesComingSoonTitle, message: VectorL10n.spacesComingSoonDetail(AppInfo.current.displayName), animated: true, handler: nil)
}
private func cancelButtonAction() {
@@ -184,11 +184,11 @@ final class SpaceMemberListViewController: RoomParticipantsViewController {
override func roomMemberDetailsViewController(_ roomMemberDetailsViewController: MXKRoomMemberDetailsViewController!, startChatWithMemberId matrixId: String!, completion: (() -> Void)!) {
completion()
self.errorPresenter.presentError(from: self, title: VectorL10n.spacesComingSoonTitle, message: VectorL10n.spacesComingSoonDetail, animated: true, handler: nil)
self.errorPresenter.presentError(from: self, title: VectorL10n.spacesComingSoonTitle, message: VectorL10n.spacesComingSoonDetail(AppInfo.current.displayName), animated: true, handler: nil)
}
override func roomMemberDetailsViewController(_ roomMemberDetailsViewController: MXKRoomMemberDetailsViewController!, placeVoipCallWithMemberId matrixId: String!, andVideo isVideoCall: Bool) {
self.errorPresenter.presentError(from: self, title: VectorL10n.spacesComingSoonTitle, message: VectorL10n.spacesComingSoonDetail, animated: true, handler: nil)
self.errorPresenter.presentError(from: self, title: VectorL10n.spacesComingSoonTitle, message: VectorL10n.spacesComingSoonDetail(AppInfo.current.displayName), animated: true, handler: nil)
}
}

View File

@@ -225,7 +225,7 @@ final class SpaceExploreRoomViewController: UIViewController {
}
@objc private func addRoomAction(semder: UIView) {
self.errorPresenter.presentError(from: self, title: VectorL10n.spacesAddRoomsComingSoonTitle, message: VectorL10n.spacesComingSoonDetail, animated: true, handler: nil)
self.errorPresenter.presentError(from: self, title: VectorL10n.spacesAddRoomsComingSoonTitle, message: VectorL10n.spacesComingSoonDetail(AppInfo.current.displayName), animated: true, handler: nil)
}
// MARK: - UISearchBarDelegate

View File

@@ -50,7 +50,7 @@ final class InviteFriendsHeaderView: UIView, NibLoadable, Themable {
override func awakeFromNib() {
super.awakeFromNib()
button.setTitle(VectorL10n.inviteFriendsAction(BuildSettings.bundleDisplayName), for: .normal)
button.setTitle(VectorL10n.inviteFriendsAction(AppInfo.current.displayName), for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
button.layer.cornerRadius = 8
button.layer.borderWidth = 2

View File

@@ -489,15 +489,20 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
@available(iOS 14.0, *)
private func presentAnalyticsPrompt(with session: MXSession) {
let parameters = AnalyticsPromptCoordinatorParameters(session: session, navigationRouter: navigationRouter)
let parameters = AnalyticsPromptCoordinatorParameters(session: session)
let coordinator = AnalyticsPromptCoordinator(parameters: parameters)
coordinator.completion = { [weak self, weak coordinator] in
guard let self = self, let coordinator = coordinator else { return }
self.navigationRouter.dismissModule(animated: true, completion: nil)
self.remove(childCoordinator: coordinator)
}
coordinator.start()
add(childCoordinator: coordinator)
navigationRouter.present(coordinator, animated: true)
coordinator.start()
}
// MARK: UserSessions management

View File

@@ -27,4 +27,6 @@ INFOPLIST_FILE = RiotSwiftUI/Info.plist
SKIP_INSTALL = YES
SWIFT_OBJC_BRIDGING_HEADER = $(SRCROOT)/$(PRODUCT_NAME)/RiotSwiftUI-Bridging-Header.h
SWIFT_OBJC_INTERFACE_HEADER_NAME = GeneratedInterface-Swift.h

View File

@@ -66,7 +66,7 @@ extension AnalyticsPromptType {
var message: String {
switch self {
case .newUser:
return VectorL10n.analyticsPromptMessageNewUser
return VectorL10n.analyticsPromptMessageNewUser(AppInfo.current.displayName)
case .upgrade:
return VectorL10n.analyticsPromptMessageUpgrade
}

View File

@@ -21,11 +21,9 @@ import SwiftUI
struct AnalyticsPromptCoordinatorParameters {
/// The session to use if analytics are enabled.
let session: MXSession
/// The navigation router used to display the prompt.
let navigationRouter: NavigationRouterType
}
final class AnalyticsPromptCoordinator: Coordinator {
final class AnalyticsPromptCoordinator: Coordinator, Presentable {
// MARK: - Properties
@@ -78,8 +76,6 @@ final class AnalyticsPromptCoordinator: Coordinator {
MXLog.debug("[AnalyticsPromptCoordinator] did start.")
parameters.navigationRouter.present(toPresentable(), animated: true)
analyticsPromptViewModel.completion = { [weak self] result in
MXLog.debug("[AnalyticsPromptCoordinator] AnalyticsPromptViewModel did complete with result: \(result).")
@@ -88,11 +84,9 @@ final class AnalyticsPromptCoordinator: Coordinator {
switch result {
case .enable:
Analytics.shared.optIn(with: self.parameters.session)
self.parameters.navigationRouter.dismissModule(animated: true, completion: nil)
self.completion?()
case .disable:
Analytics.shared.optOut()
self.parameters.navigationRouter.dismissModule(animated: true, completion: nil)
self.completion?()
}
}

View File

@@ -20,14 +20,13 @@ import SwiftUI
import Keys
struct LocationSharingCoordinatorParameters {
let navigationRouter: NavigationRouterType
let roomDataSource: MXKRoomDataSource
let mediaManager: MXMediaManager
let avatarData: AvatarInputProtocol
let location: CLLocationCoordinate2D?
}
final class LocationSharingCoordinator: Coordinator {
final class LocationSharingCoordinator: Coordinator, Presentable {
// MARK: - Properties
@@ -44,9 +43,10 @@ final class LocationSharingCoordinator: Coordinator {
// MARK: Public
// Must be used only internally
var childCoordinators: [Coordinator] = []
var completion: (() -> Void)?
// MARK: - Setup
@available(iOS 14.0, *)
@@ -70,14 +70,12 @@ final class LocationSharingCoordinator: Coordinator {
return
}
parameters.navigationRouter.present(locationSharingHostingController, animated: true)
locationSharingViewModel.completion = { [weak self] result in
guard let self = self else { return }
switch result {
case .cancel:
self.parameters.navigationRouter.dismissModule(animated: true, completion: nil)
self.completion?()
case .share(let latitude, let longitude):
if let location = self.parameters.location {
self.showActivityControllerForLocation(location)
@@ -91,8 +89,8 @@ final class LocationSharingCoordinator: Coordinator {
description: nil) { [weak self] _ in
guard let self = self else { return }
self.parameters.navigationRouter.dismissModule(animated: true, completion: nil)
self.locationSharingViewModel.dispatch(action: .stopLoading(nil))
self.completion?()
} failure: { [weak self] error in
guard let self = self else { return }
@@ -104,85 +102,19 @@ final class LocationSharingCoordinator: Coordinator {
}
}
func showActivityControllerForLocation(_ location: CLLocationCoordinate2D) {
let vc = UIActivityViewController(activityItems: activityItems(location: location),
// MARK: - Presentable
func toPresentable() -> UIViewController {
return locationSharingHostingController
}
// MARK: - Private
private func showActivityControllerForLocation(_ location: CLLocationCoordinate2D) {
let vc = UIActivityViewController(activityItems: [ShareToMapsAppActivity.urlForMapsAppType(.apple, location: location)],
applicationActivities: [ShareToMapsAppActivity(type: .apple, location: location),
ShareToMapsAppActivity(type: .google, location: location)])
locationSharingHostingController.present(vc, animated: true)
}
func activityItems(location: CLLocationCoordinate2D) -> [Any] {
var items = [Any]()
// Make the share sheet show a pretty location thumbnail
if let url = NSURL(string: "https://maps.apple.com?ll=\(location.latitude),\(location.longitude)") {
items.append(url)
}
return items
}
}
extension UIActivity.ActivityType {
static let shareToMapsApp = UIActivity.ActivityType("Element.ShareToMapsApp")
}
class ShareToMapsAppActivity: UIActivity {
enum MapsAppType {
case apple
case google
}
let type: MapsAppType
let location: CLLocationCoordinate2D
private override init() {
fatalError()
}
init(type: MapsAppType, location: CLLocationCoordinate2D) {
self.type = type
self.location = location
}
override var activityTitle: String? {
switch type {
case .apple:
return VectorL10n.locationSharingOpenAppleMaps
case .google:
return VectorL10n.locationSharingOpenGoogleMaps
}
}
var activityCategory: UIActivity.Category {
return .action
}
override var activityType: UIActivity.ActivityType {
return .shareToMapsApp
}
override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
return true
}
override func prepare(withActivityItems activityItems: [Any]) {
var url: URL?
switch type {
case .apple:
url = URL(string: "https://maps.apple.com?ll=\(location.latitude),\(location.longitude)&q=Pin")
case .google:
url = URL(string: "https://www.google.com/maps/search/?api=1&query=\(location.latitude),\(location.longitude)")
}
guard let url = url else {
activityDidFinish(false)
return
}
UIApplication.shared.open(url, options: [:]) { [weak self] result in
self?.activityDidFinish(result)
}
}
}

View File

@@ -0,0 +1,78 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
extension UIActivity.ActivityType {
static let shareToMapsApp = UIActivity.ActivityType("Element.ShareToMapsApp")
}
class ShareToMapsAppActivity: UIActivity {
enum MapsAppType {
case apple
case google
}
let type: MapsAppType
let location: CLLocationCoordinate2D
private override init() {
fatalError()
}
init(type: MapsAppType, location: CLLocationCoordinate2D) {
self.type = type
self.location = location
}
static func urlForMapsAppType(_ type: MapsAppType, location: CLLocationCoordinate2D) -> URL {
switch type {
case .apple:
return URL(string: "https://maps.apple.com?ll=\(location.latitude),\(location.longitude)&q=Pin")!
case .google:
return URL(string: "https://www.google.com/maps/search/?api=1&query=\(location.latitude),\(location.longitude)")!
}
}
override var activityTitle: String? {
switch type {
case .apple:
return VectorL10n.locationSharingOpenAppleMaps
case .google:
return VectorL10n.locationSharingOpenGoogleMaps
}
}
var activityCategory: UIActivity.Category {
return .action
}
override var activityType: UIActivity.ActivityType {
return .shareToMapsApp
}
override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
return true
}
override func prepare(withActivityItems activityItems: [Any]) {
let url = Self.urlForMapsAppType(type, location: location)
UIApplication.shared.open(url, options: [:]) { [weak self] result in
self?.activityDidFinish(result)
}
}
}

View File

@@ -73,17 +73,17 @@ class LocationSharingViewModel: LocationSharingViewModelType {
switch error {
case .failedLoadingMap:
state.bindings.alertInfo = ErrorAlertInfo(id: .mapLoadingError,
title: VectorL10n.locationSharingLoadingMapErrorTitle,
title: VectorL10n.locationSharingLoadingMapErrorTitle(AppInfo.current.displayName) ,
primaryButton: (VectorL10n.ok, { completion?(.cancel) }),
secondaryButton: nil)
case .failedLocatingUser:
state.bindings.alertInfo = ErrorAlertInfo(id: .userLocatingError,
title: VectorL10n.locationSharingLocatingUserErrorTitle,
title: VectorL10n.locationSharingLocatingUserErrorTitle(AppInfo.current.displayName),
primaryButton: (VectorL10n.ok, { completion?(.cancel) }),
secondaryButton: nil)
case .invalidLocationAuthorization:
state.bindings.alertInfo = ErrorAlertInfo(id: .authorizationError,
title: VectorL10n.locationSharingInvalidAuthorizationErrorTitle,
title: VectorL10n.locationSharingInvalidAuthorizationErrorTitle(AppInfo.current.displayName),
primaryButton: (VectorL10n.locationSharingInvalidAuthorizationNotNow, { completion?(.cancel) }),
secondaryButton: (VectorL10n.locationSharingInvalidAuthorizationSettings, {
if let applicationSettingsURL = URL(string:UIApplication.openSettingsURLString) {
@@ -101,7 +101,7 @@ class LocationSharingViewModel: LocationSharingViewModelType {
if error != nil {
state.bindings.alertInfo = ErrorAlertInfo(id: .locationSharingError,
title: VectorL10n.locationSharingInvalidAuthorizationErrorTitle,
title: VectorL10n.locationSharingInvalidAuthorizationErrorTitle(AppInfo.current.displayName),
primaryButton: (VectorL10n.ok, nil),
secondaryButton: nil)
}

View File

@@ -21,11 +21,10 @@ import UIKit
import SwiftUI
struct PollEditFormCoordinatorParameters {
let navigationRouter: NavigationRouterType?
let room: MXRoom
}
final class PollEditFormCoordinator: Coordinator {
final class PollEditFormCoordinator: Coordinator, Presentable {
// MARK: - Properties
@@ -42,9 +41,10 @@ final class PollEditFormCoordinator: Coordinator {
// MARK: Public
// Must be used only internally
var childCoordinators: [Coordinator] = []
var completion: (() -> Void)?
// MARK: - Setup
@available(iOS 14.0, *)
@@ -65,13 +65,11 @@ final class PollEditFormCoordinator: Coordinator {
return
}
parameters.navigationRouter?.present(pollEditFormHostingController, animated: true)
pollEditFormViewModel.completion = { [weak self] result in
guard let self = self else { return }
switch result {
case .cancel:
self.parameters.navigationRouter?.dismissModule(animated: true, completion: nil)
self.completion?()
case .create(let question, let answerOptions):
var options = [MXEventContentPollStartAnswerOption]()
for answerOption in answerOptions {
@@ -88,8 +86,8 @@ final class PollEditFormCoordinator: Coordinator {
self.parameters.room.sendPollStart(withContent: pollStartContent, localEcho: nil) { [weak self] result in
guard let self = self else { return }
self.parameters.navigationRouter?.dismissModule(animated: true, completion: nil)
self.pollEditFormViewModel.dispatch(action: .stopLoading(nil))
self.completion?()
} failure: { [weak self] error in
guard let self = self else { return }
@@ -99,4 +97,10 @@ final class PollEditFormCoordinator: Coordinator {
}
}
}
// MARK: - Private
func toPresentable() -> UIViewController {
return pollEditFormHostingController
}
}

View File

@@ -27,7 +27,7 @@ struct PollTimelineCoordinatorParameters {
}
@available(iOS 14.0, *)
final class PollTimelineCoordinator: Coordinator, PollAggregatorDelegate {
final class PollTimelineCoordinator: Coordinator, Presentable, PollAggregatorDelegate {
// MARK: - Properties

View File

@@ -26,7 +26,7 @@ protocol UserSuggestionCoordinatorDelegate: AnyObject {
}
@available(iOS 14.0, *)
final class UserSuggestionCoordinator: Coordinator {
final class UserSuggestionCoordinator: Coordinator, Presentable {
// MARK: - Properties

View File

@@ -20,7 +20,7 @@ struct TemplateUserProfileCoordinatorParameters {
let session: MXSession
}
final class TemplateUserProfileCoordinator: Coordinator {
final class TemplateUserProfileCoordinator: Coordinator, Presentable {
// MARK: - Properties

View File

@@ -19,7 +19,7 @@
import UIKit
@objcMembers
final class TemplateRoomsCoordinator: Coordinator {
final class TemplateRoomsCoordinator: Coordinator, Presentable {
// MARK: - Properties

View File

@@ -0,0 +1,5 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "BuildInfo.h"

View File

@@ -39,6 +39,8 @@ targets:
- "**/MatrixSDK/**"
- "**/Coordinator/**"
- "**/Test/**"
- path: ../Riot/Managers/AppInfo/
- path: ../Riot/Categories/Bundle.swift
- path: ../Riot/Generated/Strings.swift
- path: ../Riot/Generated/Images.swift
- path: ../Riot/Managers/Theme/ThemeIdentifier.swift