diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index f20fbeeff..ee765f274 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -120,7 +120,7 @@ final class BuildSettings: NSObject { // This baseURL is used to generate permalinks within the app (E.g. timeline message permalinks). // Optional String that when set is used as permalink base, when nil matrix.to format is used. // Example value would be "https://www.example.com", note there is no trailing '/'. - static let clientPermalinkBaseUrl: String? = nil + static let clientPermalinkBaseUrl: String? = "" // MARK: - VoIP static var allowVoIPUsage: Bool { @@ -362,7 +362,7 @@ final class BuildSettings: NSObject { // MARK: - Message static let messageDetailsAllowShare: Bool = false - static let messageDetailsAllowPermalink: Bool = false + static let messageDetailsAllowPermalink: Bool = true static let messageDetailsAllowViewSource: Bool = false static let messageDetailsAllowSave: Bool = false static let messageDetailsAllowCopyMedia: Bool = false @@ -375,8 +375,8 @@ final class BuildSettings: NSObject { static let authScreenShowRegister = false static let authScreenShowPhoneNumber = false static let authScreenShowForgotPassword = false - static let authScreenShowCustomServerOptions = false - static let authScreenShowTestServerOptions = false + static let authScreenShowCustomServerOptions = true + static let authScreenShowTestServerOptions = true // MARK: - Authentication Options static let authEnableRefreshTokens = false diff --git a/Config/CommonConfiguration.swift b/Config/CommonConfiguration.swift index 67275c353..e9238183b 100644 --- a/Config/CommonConfiguration.swift +++ b/Config/CommonConfiguration.swift @@ -82,7 +82,7 @@ class CommonConfiguration: NSObject, Configurable { // Pass threading option to the SDK sdkOptions.enableThreads = RiotSettings.shared.enableThreads - sdkOptions.clientPermalinkBaseUrl = BuildSettings.clientPermalinkBaseUrl + sdkOptions.clientPermalinkBaseUrl = ServerURLHelper.shared.httpsPermalink() sdkOptions.authEnableRefreshTokens = BuildSettings.authEnableRefreshTokens diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index fa3f74200..1199b88a1 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -175,6 +175,7 @@ "room_participants_action_start_new_chat" = "Starte neuen Chat"; "room_participants_action_start_video_call" = "Starte Video-Anruf"; "room_participants_action_mention" = "Erwähnen"; +"room_participants_action_permalink" = "Nutzer teilen"; // Chat "room_jump_to_first_unread" = "Zur ersten ungelesenen Nachricht"; "room_new_message_notification" = "%d neue Nachricht"; @@ -196,7 +197,7 @@ "room_event_action_quote" = "Zitieren"; "room_event_action_more" = "Mehr"; "room_event_action_share" = "Teilen"; -"room_event_action_permalink" = "Permalink"; +"room_event_action_permalink" = "Nachricht teilen"; "room_event_action_view_source" = "Zeige Quelltext"; "room_event_action_report" = "Inhalt melden"; "room_event_action_report_prompt_reason" = "Grund fürs Melden dieses Inhalts"; @@ -1442,6 +1443,7 @@ "room_details_integrations" = "Integrationen"; "room_details_search" = "Raum durchsuchen"; +"room_details_permalink" = "Raum teilen"; "room_multiple_typing_notification" = "%@ und andere"; "room_accessibility_video_call" = "Videoanruf"; "room_message_replying_to" = "%@ anworten"; diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 2ea773dae..a0836fe41 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -321,6 +321,7 @@ Tap the + to start adding people."; "room_participants_action_start_voice_call" = "Start voice call"; "room_participants_action_start_video_call" = "Start video call"; "room_participants_action_mention" = "Mention"; +"room_participants_action_permalink" = "Share user"; "room_participants_action_security_status_verified" = "Verified"; "room_participants_action_security_status_verify" = "Verify"; "room_participants_action_security_status_complete_security" = "Complete security"; @@ -784,6 +785,7 @@ Tap the + to start adding people."; "room_details_people" = "Members"; "room_details_files" = "Uploads"; "room_details_search" = "Search room"; +"room_details_permalink" = "Share room"; "room_details_integrations" = "Integrations"; "room_details_settings" = "Settings"; "room_details_photo" = "Room Photo"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 68edcd1be..2f5af5ca9 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -3363,6 +3363,10 @@ public class VectorL10n: NSObject { public static var roomDetailsPeople: String { return VectorL10n.tr("Vector", "room_details_people") } + /// Share room + public static var roomDetailsPermalink: String { + return VectorL10n.tr("Vector", "room_details_permalink") + } /// Room Photo public static var roomDetailsPhoto: String { return VectorL10n.tr("Vector", "room_details_photo") @@ -3775,6 +3779,10 @@ public class VectorL10n: NSObject { public static var roomParticipantsActionMention: String { return VectorL10n.tr("Vector", "room_participants_action_mention") } + /// Share user + public static var roomParticipantsActionPermalink: String { + return VectorL10n.tr("Vector", "room_participants_action_permalink") + } /// Remove from this room public static var roomParticipantsActionRemove: String { return VectorL10n.tr("Vector", "room_participants_action_remove") diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 614eb3951..644253b66 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -2011,9 +2011,9 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; if (@available(iOS 14.0, *)) { NSMutableArray* actions = [[NSMutableArray alloc] init]; - for (NSString *key in BuildSettings.serverConfigPreSelections) { - [actions addObject:[UIAction actionWithTitle:key image:nil identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - [self setHomeServerTextFieldText:BuildSettings.serverConfigPreSelections[key]]; + for (ServerSetting* setting in ServerURLHelper.shared.serverSettings) { + [actions addObject:[UIAction actionWithTitle:setting.name image:nil identifier:nil handler:^(__kindof UIAction* _Nonnull action) { + [self setHomeServerTextFieldText:setting]; }]]; } diff --git a/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m index 3465c136b..6c9fdc9da 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m @@ -442,17 +442,24 @@ } } -- (void)setHomeServerTextFieldText:(NSString *)homeServerUrl +- (void)setHomeServerTextFieldText:(ServerSetting *)serverSetting { - if (!homeServerUrl.length) - { - // Force refresh with default value - homeServerUrl = _defaultHomeServerUrl; + NSString *serverUrl; + NSUInteger index = [ServerURLHelper.shared.serverSettings indexOfObject:serverSetting]; + if (index != NSNotFound) { + ServerURLHelper.shared.selectedIndex = index; + serverUrl = serverSetting.serverUrl; + + MXSDKOptions *option = MXSDKOptions.sharedInstance; + + option.clientPermalinkBaseUrl = [ServerURLHelper.shared httpsPermalink]; + } else { + serverUrl = @""; } - _homeServerTextField.text = homeServerUrl; + _homeServerTextField.text = serverUrl; - if (!mxRestClient || ![mxRestClient.homeserver isEqualToString:homeServerUrl]) + if (!mxRestClient || ![mxRestClient.homeserver isEqualToString:serverUrl]) { [self updateRESTClient]; diff --git a/Riot/Modules/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.h b/Riot/Modules/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.h index 269c279e1..80843ee4a 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.h +++ b/Riot/Modules/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.h @@ -41,7 +41,8 @@ typedef enum : NSUInteger MXKRoomMemberDetailsActionStartVideoCall, MXKRoomMemberDetailsActionMention, MXKRoomMemberDetailsActionSecurity, - MXKRoomMemberDetailsActionSecurityInformation + MXKRoomMemberDetailsActionSecurityInformation, + MXKRoomMemberDetailsActionPermalink } MXKRoomMemberDetailsAction; diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 20b1c95d5..aaed67c01 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -664,6 +664,11 @@ // Add mention option [otherActionsArray addObject:@(MXKRoomMemberDetailsActionMention)]; } + + if (BwiBuildSettings.bwiAllowUserPermalink) + { + [otherActionsArray addObject:@(MXKRoomMemberDetailsActionPermalink)]; + } } if (self.mxRoom.summary.isEncrypted) @@ -821,6 +826,9 @@ case MXKRoomMemberDetailsActionMention: title = [VectorL10n roomParticipantsActionMention]; break; + case MXKRoomMemberDetailsActionPermalink: + title = [VectorL10n roomParticipantsActionPermalink]; + break; default: break; } @@ -1276,6 +1284,11 @@ [self presentViewController:currentAlert animated:YES completion:nil]; break; } + case MXKRoomMemberDetailsActionPermalink: + { + [self createPermalink]; + break; + } default: { [super onActionButtonPressed:sender]; @@ -1305,6 +1318,21 @@ return numOtherAdmins > 0 ? FALSE : TRUE; } +- (void) createPermalink { + NSString *permalink = [MXTools permalinkToUserWithUserId:self.mxRoomMember.userId]; + NSURL *url = [NSURL URLWithString:permalink]; + + if (url) + { + MXKPasteboardManager.shared.pasteboard.URL = url; + [self.view vc_toastWithMessage:VectorL10n.roomEventCopyLinkInfo + image:[UIImage imageNamed:@"link_icon"] + duration:2.0 + position:ToastPositionBottom + additionalMargin:0]; + } +} + - (void)showAlertChangePowerLevelNotAllowed { __weak typeof(self) weakSelf = self; diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift index f5f603a30..3cc108208 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift @@ -26,6 +26,7 @@ enum RoomInfoListTarget: Equatable { case uploads case integrations case search + case permalink case notifications var tabIndex: UInt? { @@ -49,4 +50,5 @@ enum RoomInfoListViewAction { case navigate(target: RoomInfoListTarget) case leave case cancel + case permalink } diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift index 5d6fc3f50..486380b2e 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift @@ -18,6 +18,7 @@ */ import UIKit +import MatrixSDK final class RoomInfoListViewController: UIViewController { @@ -204,6 +205,10 @@ final class RoomInfoListViewController: UIViewController { let rowSearch = Row(type: .default, icon: Asset.Images.searchIcon.image, text: VectorL10n.roomDetailsSearch, accessoryType: .disclosureIndicator) { self.viewModel.process(viewAction: .navigate(target: .search)) } + + let rowPermalink = Row(type: .default, icon: nil, text: VectorL10n.roomDetailsPermalink, accessoryType: .none) { + self.viewModel.process(viewAction: .permalink) + } let rowIntegrations = Row(type: .default, icon: Asset.Images.integrationsIcon.image, text: VectorL10n.roomDetailsIntegrations, accessoryType: .disclosureIndicator) { self.viewModel.process(viewAction: .navigate(target: .integrations)) @@ -222,7 +227,14 @@ final class RoomInfoListViewController: UIViewController { } rows.append(rowMembers) rows.append(rowUploads) - rows.append(rowSearch) + + if BwiBuildSettings.bwiShowRoomSearch { + rows.append(rowSearch) + } + + if BwiBuildSettings.bwiAllowRoomPermalink { + rows.append(rowPermalink) + } let sectionSettings = Section(header: VectorL10n.roomInfoListSectionOther, rows: rows, @@ -296,6 +308,8 @@ final class RoomInfoListViewController: UIViewController { self.renderLoaded(viewData: viewData) case .error(let error): self.render(error: error) + case .permalinkCreated: + self.renderToast() } } @@ -313,6 +327,10 @@ final class RoomInfoListViewController: UIViewController { self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) } + private func renderToast() { + self.view.vc_toast(message: VectorL10n.roomEventCopyLinkInfo, image: UIImage(named: "link_icon"), duration: 2.0, position: .bottom, additionalMargin: 0) + } + private func doNotLeaveUIAlertController() -> UIAlertController { let title = VectorL10n.roomParticipantsLeavePromptTitle let message = NSLocalizedString("room_participants_cant_leave_prompt_message", tableName: "Vector", comment: "") diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewModel.swift b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewModel.swift index 37d846ec7..a421d124c 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewModel.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewModel.swift @@ -75,6 +75,8 @@ final class RoomInfoListViewModel: NSObject, RoomInfoListViewModelType { self.leave() case .cancel: self.coordinatorDelegate?.roomInfoListViewModelDidCancel(self) + case .permalink: + self.createPermalink() } } @@ -183,4 +185,12 @@ final class RoomInfoListViewModel: NSObject, RoomInfoListViewModelType { private func update(viewState: RoomInfoListViewState) { self.viewDelegate?.roomInfoListViewModel(self, didUpdateViewState: viewState) } + + private func createPermalink() { + if let permalink = MXTools.permalink(toRoom: self.room.roomId), let url = URL(string: permalink) { + MXKPasteboardManager.shared.pasteboard.url = url + self.viewDelegate?.roomInfoListViewModel(self, didUpdateViewState: .permalinkCreated) + } + + } } diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewState.swift b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewState.swift index 789340ee8..8f7aa7c29 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewState.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewState.swift @@ -23,4 +23,5 @@ enum RoomInfoListViewState { case loading case loaded(viewData: RoomInfoListViewData) case error(Error) + case permalinkCreated } diff --git a/Riot/Utils/Tools.m b/Riot/Utils/Tools.m index f5cde39c4..5f87b1796 100644 --- a/Riot/Utils/Tools.m +++ b/Riot/Utils/Tools.m @@ -93,6 +93,10 @@ } } } + + if ([url.host isEqualToString:[ServerURLHelper.shared permalink]]) { + isUniversalLink = YES; + } return isUniversalLink; } diff --git a/bwi/BwiBuildSettings.swift b/bwi/BwiBuildSettings.swift index d441b3eab..a7f62e621 100644 --- a/bwi/BwiBuildSettings.swift +++ b/bwi/BwiBuildSettings.swift @@ -41,4 +41,10 @@ final class BwiBuildSettings: NSObject { static let flavor = "" static let showBwiSplashScreen: Bool = false + + static let bwiShowRoomSearch: Bool = false + + static let bwiAllowRoomPermalink: Bool = true + + static let bwiAllowUserPermalink: Bool = true } diff --git a/bwi/ServerURLs/ServerURLs.swift b/bwi/ServerURLs/ServerSetting.swift similarity index 64% rename from bwi/ServerURLs/ServerURLs.swift rename to bwi/ServerURLs/ServerSetting.swift index ac8d1bdb4..2cb548dc8 100644 --- a/bwi/ServerURLs/ServerURLs.swift +++ b/bwi/ServerURLs/ServerSetting.swift @@ -17,8 +17,20 @@ import Foundation -struct ServerURLs { +@objcMembers class ServerSetting : NSObject { + var name: String var serverUrl: String var pusherUrl: String var flavor: String + var permalink: String + + init(name:String, serverUrl:String, pusherUrl:String, flavor:String, permalink:String) { + self.name = name + self.serverUrl = serverUrl + self.pusherUrl = pusherUrl + self.flavor = flavor + self.permalink = permalink + + super.init() + } } diff --git a/bwi/ServerURLs/ServerURLHelper.swift b/bwi/ServerURLs/ServerURLHelper.swift index 1a22d8f17..ca2012e97 100644 --- a/bwi/ServerURLs/ServerURLHelper.swift +++ b/bwi/ServerURLs/ServerURLHelper.swift @@ -24,8 +24,19 @@ import Foundation private let serverUrlKey = "serverURL" private let pusherUrlKey = "pusherURL" private let flavorUrlKey = "flavor" + private let nameKey = "name" + private let permalinkKey = "permalink" - var serverURLs = Array() + var serverSettings = Array() + + var selectedIndex: Int { + get { + return UserDefaults.standard.integer(forKey: "Bwi_Server_Url_Helper_Index") + } + set(newSelectedIndex) { + UserDefaults.standard.set(newSelectedIndex, forKey: "Bwi_Server_Url_Helper_Index") + } + } private func loadURLs() { if let path = Bundle.main.path(forResource: "serverurls", ofType: "json") { @@ -36,11 +47,14 @@ import Foundation for urlSet in urls { if let dict = urlSet as? Dictionary { - if let server = dict[serverUrlKey], let pusher = dict[pusherUrlKey], let flavor = dict[flavorUrlKey] { - serverURLs.append(ServerURLs(serverUrl: server, pusherUrl: pusher, flavor: flavor)) + if let server = dict[serverUrlKey], + let pusher = dict[pusherUrlKey], + let flavor = dict[flavorUrlKey], + let name = dict[nameKey], + let permalink = dict[permalinkKey] { + serverSettings.append(ServerSetting(name:name, serverUrl: server, pusherUrl: pusher, flavor: flavor, permalink:permalink)) } } - } } } catch { @@ -55,24 +69,48 @@ import Foundation } func serverUrl() -> String? { - if serverURLs.count > 0 { - return serverURLs[0].serverUrl + if serverSettings.indices.contains(selectedIndex) { + return serverSettings[selectedIndex].serverUrl } else { return nil } } func pusherUrl() -> String? { - if serverURLs.count > 0 { - return serverURLs[0].pusherUrl + if serverSettings.indices.contains(selectedIndex) { + return serverSettings[selectedIndex].pusherUrl } else { return nil } } func flavor() -> String? { - if serverURLs.count > 0 { - return serverURLs[0].flavor + if serverSettings.indices.contains(selectedIndex) { + return serverSettings[selectedIndex].flavor + } else { + return nil + } + } + + func name() -> String? { + if serverSettings.indices.contains(selectedIndex) { + return serverSettings[selectedIndex].name + } else { + return nil + } + } + + func permalink() -> String? { + if serverSettings.indices.contains(selectedIndex) { + return serverSettings[selectedIndex].permalink + } else { + return nil + } + } + + func httpsPermalink() -> String? { + if serverSettings.indices.contains(selectedIndex) { + return "https://" + serverSettings[selectedIndex].permalink } else { return nil }