Automatic discovery of the sliding sync proxy. (#535)
* Automatic discovery of the sliding sync proxy. * Handle homeserver detection from a MXID. * Update sliding sync info link, SDK and bump patch. Add a migration on the new version. The change in restoration token format requires the user to sign in again, but this will fail with the existing device ID.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@@ -91,6 +91,7 @@
|
||||
24A75F72EEB7561B82D726FD /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2141693488CE5446BB391964 /* Date.swift */; };
|
||||
24BDDD09A90B8BFE3793F3AA /* ClientProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */; };
|
||||
25618589E0DE0F1E95FC7B5C /* EmojiProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */; };
|
||||
274CE3C986841D15FD530BF5 /* ShimmerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97CE98208321C4D66E363612 /* ShimmerModifier.swift */; };
|
||||
2797C9D9BA642370F1C85D78 /* Untranslated.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = F75DF9500D69A3AAF8339E69 /* Untranslated.stringsdict */; };
|
||||
27E9263DA75E266690A37EB1 /* PermalinkBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FB31A32C93D94930B253FBF /* PermalinkBuilderTests.swift */; };
|
||||
282A5F3375DDC774AE09B0C3 /* TracingConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */; };
|
||||
@@ -293,7 +294,6 @@
|
||||
8F2FAA98457750D9D664136F /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 997C7385E1A07E061D7E2100 /* GZIP */; };
|
||||
90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; };
|
||||
90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; };
|
||||
916D6679298D6F900071EF0B /* ShimmerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916D6678298D6F900071EF0B /* ShimmerModifier.swift */; };
|
||||
91DFCB641FBA03EE2DA0189E /* FilePreviewScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB27E1BE894F9F9F0134372 /* FilePreviewScreen.swift */; };
|
||||
9219640F4D980CFC5FE855AD /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 536E72DCBEEC4A1FE66CFDCE /* target.yml */; };
|
||||
92B95779840CD749117B3615 /* EmojiMartStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38AE3617D7619EF30CDD229 /* EmojiMartStore.swift */; };
|
||||
@@ -709,7 +709,7 @@
|
||||
47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxyProtocol.swift; sourceTree = "<group>"; };
|
||||
471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
475EB595D7527E9A8A14043E /* uz */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uz; path = uz.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
478BE8591BD13E908EF70C0C /* DesignKit */ = {isa = PBXFileReference; lastKnownFileType = folder; path = DesignKit; sourceTree = SOURCE_ROOT; };
|
||||
478BE8591BD13E908EF70C0C /* DesignKit */ = {isa = PBXFileReference; lastKnownFileType = folder; name = DesignKit; path = DesignKit; sourceTree = SOURCE_ROOT; };
|
||||
4798B3B7A1E8AE3901CEE8C6 /* FramePreferenceKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FramePreferenceKey.swift; sourceTree = "<group>"; };
|
||||
47EBB5D698CE9A25BB553A2D /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
|
||||
48CE6BF18E542B32FA52CE06 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = fa; path = fa.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
@@ -842,7 +842,7 @@
|
||||
8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineProvider.swift; sourceTree = "<group>"; };
|
||||
8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = "<group>"; };
|
||||
8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = "<group>"; };
|
||||
8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = "<group>"; };
|
||||
8EC57A32ABC80D774CC663DB /* SettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenUITests.swift; sourceTree = "<group>"; };
|
||||
8ED2D2F6A137A95EA50413BE /* UserNotificationControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationControllerProtocol.swift; sourceTree = "<group>"; };
|
||||
8F7D42E66E939B709C1EC390 /* MockRoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomSummaryProvider.swift; sourceTree = "<group>"; };
|
||||
@@ -851,7 +851,6 @@
|
||||
9010EE0CC913D095887EF36E /* OIDCService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCService.swift; sourceTree = "<group>"; };
|
||||
9080CDD3881D0D1B2F280A7C /* MockUserNotificationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockUserNotificationController.swift; sourceTree = "<group>"; };
|
||||
90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
916D6678298D6F900071EF0B /* ShimmerModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShimmerModifier.swift; sourceTree = "<group>"; };
|
||||
91FB6F5ECCF51ECE98ACFEEC /* RoomDetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsViewModel.swift; sourceTree = "<group>"; };
|
||||
9238D3A3A00F45E841FE4EFF /* DebugScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugScreen.swift; sourceTree = "<group>"; };
|
||||
92FCD9116ADDE820E4E30F92 /* UIKitBackgroundTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitBackgroundTask.swift; sourceTree = "<group>"; };
|
||||
@@ -864,6 +863,7 @@
|
||||
96C4762F8D6112E43117DB2F /* CustomStringConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomStringConvertible.swift; sourceTree = "<group>"; };
|
||||
9772C1D2223108EB3131AEE4 /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
97755C01C3971474EFAD5367 /* AuthenticationIconImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationIconImage.swift; sourceTree = "<group>"; };
|
||||
97CE98208321C4D66E363612 /* ShimmerModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShimmerModifier.swift; sourceTree = "<group>"; };
|
||||
97F893DBB5F88D746C6DCDE5 /* ku */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ku; path = ku.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
98273EE22BC18E85C645329C /* bn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bn; path = bn.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
9873076F224E4CE09D8BD47D /* TemplateScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenUITests.swift; sourceTree = "<group>"; };
|
||||
@@ -1065,7 +1065,7 @@
|
||||
EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsViewModelTests.swift; sourceTree = "<group>"; };
|
||||
ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomCell.swift; sourceTree = "<group>"; };
|
||||
ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
||||
ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = "<group>"; };
|
||||
ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = "<group>"; };
|
||||
ED983D4DCA5AFA6E1ED96099 /* StateRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionViewModelTests.swift; sourceTree = "<group>"; };
|
||||
EDB6E40BAD4504D899FAAC9A /* TemplateViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateViewModel.swift; sourceTree = "<group>"; };
|
||||
@@ -2389,8 +2389,8 @@
|
||||
E2DA161C142B7AB8CC40F752 /* Animation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
916D6678298D6F900071EF0B /* ShimmerModifier.swift */,
|
||||
EF1593DD87F974F8509BB619 /* ElementAnimations.swift */,
|
||||
97CE98208321C4D66E363612 /* ShimmerModifier.swift */,
|
||||
);
|
||||
path = Animation;
|
||||
sourceTree = "<group>";
|
||||
@@ -3261,6 +3261,7 @@
|
||||
DBAA69CC2CE4D44BC8E20105 /* SettingsScreenModels.swift in Sources */,
|
||||
EEC499F9AC7DD6D18760F81D /* SettingsScreenViewModel.swift in Sources */,
|
||||
50C59870BEB1F29C60252FD4 /* SettingsScreenViewModelProtocol.swift in Sources */,
|
||||
274CE3C986841D15FD530BF5 /* ShimmerModifier.swift in Sources */,
|
||||
6E6E0AAF6C44C0B117EBBE5A /* SlidingSyncViewProxy.swift in Sources */,
|
||||
2276870A19F34B3FFFDA690F /* SoftLogoutCoordinator.swift in Sources */,
|
||||
214C6B416609E58CCBF6DCEE /* SoftLogoutModels.swift in Sources */,
|
||||
@@ -3315,7 +3316,6 @@
|
||||
E1F446C6B78A3A0FEA15079C /* UnsupportedRoomTimelineView.swift in Sources */,
|
||||
7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */,
|
||||
87BD4F95F9D603C309837378 /* UserNotification.swift in Sources */,
|
||||
916D6679298D6F900071EF0B /* ShimmerModifier.swift in Sources */,
|
||||
E3291AD16D7A5CB14781819C /* UserNotificationCenterProtocol.swift in Sources */,
|
||||
5D9F0695DC6C0057F85C12B6 /* UserNotificationController.swift in Sources */,
|
||||
D79F0F852C6A4255D5E616D2 /* UserNotificationControllerProtocol.swift in Sources */,
|
||||
@@ -3720,7 +3720,7 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)";
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
MARKETING_VERSION = 1.0.19;
|
||||
MARKETING_VERSION = 1.0.20;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -3792,7 +3792,7 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)";
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
MARKETING_VERSION = 1.0.19;
|
||||
MARKETING_VERSION = 1.0.20;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@@ -4020,7 +4020,7 @@
|
||||
repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift";
|
||||
requirement = {
|
||||
kind = exactVersion;
|
||||
version = "1.0.37-alpha";
|
||||
version = "1.0.38-alpha";
|
||||
};
|
||||
};
|
||||
96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */ = {
|
||||
|
||||
@@ -86,8 +86,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/matrix-org/matrix-rust-components-swift",
|
||||
"state" : {
|
||||
"revision" : "79ead18b0db04f898d5ba9ce1a0b609a518f44ec",
|
||||
"version" : "1.0.37-alpha"
|
||||
"revision" : "986c400f8d4d0f9d467370f98d70b6b742e90e18",
|
||||
"version" : "1.0.38-alpha"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
"session_verification_start" = "Start";
|
||||
|
||||
"server_selection_server_footer" = "You can only connect to an existing server";
|
||||
"server_selection_sliding_sync_alert_title" = "Server not supported";
|
||||
"server_selection_sliding_sync_alert_message" = "This server currently doesn’t support sliding sync.";
|
||||
|
||||
"login_mobile_device" = "Mobile";
|
||||
"login_tablet_device" = "Tablet";
|
||||
|
||||
@@ -136,9 +136,10 @@ class AppCoordinator: AppCoordinatorProtocol {
|
||||
private func performMigrationsIfNecessary(from oldVersion: Version, to newVersion: Version) {
|
||||
guard oldVersion != newVersion else { return }
|
||||
|
||||
if oldVersion < Version(1, 0, 17) {
|
||||
// Version 1.0.17 hardcoded a new sliding sync proxy for matrix.org
|
||||
// Force a sign out for the user to log in with the new proxy.
|
||||
if oldVersion < Version(1, 0, 20) {
|
||||
// Version 1.0.20 introduced a new format for restoration tokens.
|
||||
// Remove user data to prevent conflict in the crypto store
|
||||
// with the newly generated device ID when signing in again.
|
||||
MXLog.warning("Clearing user data for hardcoded proxy.")
|
||||
wipeUserData()
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ final class AppSettings: ObservableObject {
|
||||
case timelineStyle
|
||||
case enableAnalytics
|
||||
case isIdentifiedForAnalytics
|
||||
case slidingSyncProxyBaseURLString
|
||||
case enableInAppNotifications
|
||||
case pusherProfileTag
|
||||
}
|
||||
@@ -62,7 +61,12 @@ final class AppSettings: ObservableObject {
|
||||
|
||||
/// An override of the homeserver's Sliding Sync proxy URL. This allows development against servers
|
||||
/// that don't yet have an officially trusted proxy configured in their well-known.
|
||||
let slidingSyncProxyURL = URL(staticString: "https://slidingsync.lab.matrix.org")
|
||||
let slidingSyncProxyURL: URL? = nil
|
||||
|
||||
// MARK: - Authentication
|
||||
|
||||
/// The URL that is opened when tapping the Learn more button on the sliding sync alert during authentication.
|
||||
let slidingSyncLearnMoreURL = URL(staticString: "https://github.com/matrix-org/sliding-sync/blob/main/docs/Landing.md")
|
||||
|
||||
// MARK: - Notifications
|
||||
|
||||
|
||||
@@ -128,6 +128,10 @@ extension ElementL10n {
|
||||
public static let screenshotDetectedTitle = ElementL10n.tr("Untranslated", "screenshot_detected_title")
|
||||
/// You can only connect to an existing server
|
||||
public static let serverSelectionServerFooter = ElementL10n.tr("Untranslated", "server_selection_server_footer")
|
||||
/// This server currently doesn’t support sliding sync.
|
||||
public static let serverSelectionSlidingSyncAlertMessage = ElementL10n.tr("Untranslated", "server_selection_sliding_sync_alert_message")
|
||||
/// Server not supported
|
||||
public static let serverSelectionSlidingSyncAlertTitle = ElementL10n.tr("Untranslated", "server_selection_sliding_sync_alert_title")
|
||||
/// Looks like you’re using a new device. Verify it’s you to access your encrypted messages.
|
||||
public static let sessionVerificationBannerMessage = ElementL10n.tr("Untranslated", "session_verification_banner_message")
|
||||
/// Access your message history
|
||||
|
||||
@@ -38,7 +38,12 @@ struct AlertInfo<T: Hashable>: Identifiable {
|
||||
|
||||
struct AlertButton {
|
||||
let title: String
|
||||
var role: Role = .default
|
||||
let action: (() -> Void)?
|
||||
|
||||
enum Role {
|
||||
case `default`, cancel, destructive
|
||||
}
|
||||
}
|
||||
|
||||
extension AlertInfo {
|
||||
@@ -85,10 +90,19 @@ extension AlertInfo {
|
||||
}
|
||||
|
||||
private func alertButton(for buttonParameters: AlertButton) -> Alert.Button {
|
||||
guard let action = buttonParameters.action else {
|
||||
switch (buttonParameters.role, buttonParameters.action) {
|
||||
case (.default, nil):
|
||||
return .default(Text(buttonParameters.title))
|
||||
case (.default, let action):
|
||||
return .default(Text(buttonParameters.title), action: action)
|
||||
case (.cancel, nil):
|
||||
return .cancel(Text(buttonParameters.title))
|
||||
case (.cancel, let action):
|
||||
return .cancel(Text(buttonParameters.title), action: action)
|
||||
case (.destructive, nil):
|
||||
return .destructive(Text(buttonParameters.title))
|
||||
case (.destructive, let action):
|
||||
return .destructive(Text(buttonParameters.title), action: action)
|
||||
}
|
||||
|
||||
return .default(Text(buttonParameters.title), action: action)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,8 @@ final class LoginCoordinator: CoordinatorProtocol {
|
||||
viewModel.displayError(.alert(ElementL10n.authInvalidLoginParam))
|
||||
case .accountDeactivated:
|
||||
viewModel.displayError(.alert(ElementL10n.authInvalidLoginDeactivatedAccount))
|
||||
case .slidingSyncNotAvailable:
|
||||
viewModel.displayError(.slidingSyncAlert)
|
||||
default:
|
||||
viewModel.displayError(.alert(ElementL10n.unknownError))
|
||||
}
|
||||
@@ -197,10 +199,8 @@ final class LoginCoordinator: CoordinatorProtocol {
|
||||
|
||||
/// Presents the server selection screen as a modal.
|
||||
private func presentServerSelectionScreen() {
|
||||
let userNotificationController = UserNotificationController(rootCoordinator: navigationStackCoordinator)
|
||||
|
||||
let parameters = ServerSelectionCoordinatorParameters(authenticationService: authenticationService,
|
||||
userNotificationController: userNotificationController,
|
||||
userNotificationController: ServiceLocator.shared.userNotificationController,
|
||||
isModallyPresented: false)
|
||||
|
||||
let coordinator = ServerSelectionCoordinator(parameters: parameters)
|
||||
|
||||
@@ -94,6 +94,8 @@ enum LoginErrorType: Hashable {
|
||||
case alert(String)
|
||||
/// Looking up the homeserver from the username failed.
|
||||
case invalidHomeserver
|
||||
/// An alert that allows the user to learn about sliding sync.
|
||||
case slidingSyncAlert
|
||||
/// The response from the homeserver was unexpected.
|
||||
case unknown
|
||||
}
|
||||
|
||||
@@ -62,6 +62,16 @@ class LoginViewModel: LoginViewModelType, LoginViewModelProtocol {
|
||||
state.bindings.alertInfo = AlertInfo(id: type,
|
||||
title: ElementL10n.dialogTitleError,
|
||||
message: ElementL10n.loginSigninMatrixIdErrorInvalidMatrixId)
|
||||
case .slidingSyncAlert:
|
||||
let openURL = { UIApplication.shared.open(ServiceLocator.shared.settings.slidingSyncLearnMoreURL) }
|
||||
state.bindings.alertInfo = AlertInfo(id: .slidingSyncAlert,
|
||||
title: ElementL10n.serverSelectionSlidingSyncAlertTitle,
|
||||
message: ElementL10n.serverSelectionSlidingSyncAlertMessage,
|
||||
primaryButton: .init(title: ElementL10n.actionLearnMore, role: .cancel, action: openURL),
|
||||
secondaryButton: .init(title: ElementL10n.actionCancel, action: nil))
|
||||
|
||||
// Clear out the invalid username to avoid an attempted login to matrix.org
|
||||
state.bindings.username = ""
|
||||
case .unknown:
|
||||
state.bindings.alertInfo = AlertInfo(id: type)
|
||||
}
|
||||
|
||||
@@ -64,7 +64,6 @@ struct LoginScreen: View {
|
||||
LoginServerInfoSection(address: context.viewState.homeserver.address) {
|
||||
context.send(viewAction: .selectServer)
|
||||
}
|
||||
.disabled(true) // The button is disabled for this demo.
|
||||
}
|
||||
|
||||
/// The form with text fields for username and password, along with a submit button.
|
||||
@@ -96,14 +95,6 @@ struct LoginScreen: View {
|
||||
.onSubmit(submit)
|
||||
.accessibilityIdentifier("passwordTextField")
|
||||
|
||||
// uncomment this piece of code once forgot password will be available
|
||||
// Button { context.send(viewAction: .forgotPassword) } label: {
|
||||
// Text(ElementL10n.ftueAuthForgotPassword)
|
||||
// .font(.element.body)
|
||||
// }
|
||||
// .frame(maxWidth: .infinity, alignment: .trailing)
|
||||
// .padding(.bottom, 8)
|
||||
|
||||
Spacer().frame(height: 32)
|
||||
|
||||
Button(action: submit) {
|
||||
|
||||
@@ -48,7 +48,6 @@ struct LoginServerInfoSection: View {
|
||||
Image(systemName: "chevron.right")
|
||||
.foregroundColor(.element.tertiaryContent)
|
||||
.padding(.trailing, 16)
|
||||
.hidden() // The button is disabled for this demo.
|
||||
}
|
||||
.background(RoundedRectangle(cornerRadius: 14).fill(Color.element.system))
|
||||
}
|
||||
|
||||
@@ -102,6 +102,8 @@ final class ServerSelectionCoordinator: CoordinatorProtocol {
|
||||
switch error {
|
||||
case .invalidServer, .invalidHomeserverAddress:
|
||||
viewModel.displayError(.footerMessage(ElementL10n.loginErrorHomeserverNotFound))
|
||||
case .slidingSyncNotAvailable:
|
||||
viewModel.displayError(.slidingSyncAlert)
|
||||
default:
|
||||
viewModel.displayError(.footerMessage(ElementL10n.unknownError))
|
||||
}
|
||||
|
||||
@@ -71,4 +71,6 @@ enum ServerSelectionViewAction {
|
||||
enum ServerSelectionErrorType: Hashable {
|
||||
/// An error message to be shown in the text field footer.
|
||||
case footerMessage(String)
|
||||
/// An alert that allows the user to learn about sliding sync.
|
||||
case slidingSyncAlert
|
||||
}
|
||||
|
||||
@@ -45,6 +45,13 @@ class ServerSelectionViewModel: ServerSelectionViewModelType, ServerSelectionVie
|
||||
withElementAnimation {
|
||||
state.footerErrorMessage = message
|
||||
}
|
||||
case .slidingSyncAlert:
|
||||
let openURL = { UIApplication.shared.open(ServiceLocator.shared.settings.slidingSyncLearnMoreURL) }
|
||||
state.bindings.alertInfo = AlertInfo(id: .slidingSyncAlert,
|
||||
title: ElementL10n.serverSelectionSlidingSyncAlertTitle,
|
||||
message: ElementL10n.serverSelectionSlidingSyncAlertMessage,
|
||||
primaryButton: .init(title: ElementL10n.actionLearnMore, role: .cancel, action: openURL),
|
||||
secondaryButton: .init(title: ElementL10n.actionCancel, action: nil))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||
|
||||
init(userSessionStore: UserSessionStoreProtocol) {
|
||||
self.userSessionStore = userSessionStore
|
||||
authenticationService = AuthenticationService(basePath: userSessionStore.baseDirectory.path, passphrase: nil)
|
||||
authenticationService = AuthenticationService(basePath: userSessionStore.baseDirectory.path,
|
||||
passphrase: nil,
|
||||
customSlidingSyncProxy: ServiceLocator.shared.settings.slidingSyncProxyURL?.absoluteString)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
@@ -51,6 +53,9 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||
|
||||
self.homeserver = homeserver
|
||||
return .success(())
|
||||
} catch AuthenticationError.SlidingSyncNotAvailable {
|
||||
MXLog.info("User entered a homeserver that isn't configured for sliding sync.")
|
||||
return .failure(.slidingSyncNotAvailable)
|
||||
} catch {
|
||||
MXLog.error("Failed configuring a server: \(error)")
|
||||
return .failure(.invalidHomeserverAddress)
|
||||
|
||||
@@ -23,6 +23,7 @@ enum AuthenticationServiceError: Error {
|
||||
case invalidServer
|
||||
case invalidCredentials
|
||||
case invalidHomeserverAddress
|
||||
case slidingSyncNotAvailable
|
||||
case accountDeactivated
|
||||
case failedLoggingIn
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
}
|
||||
|
||||
do {
|
||||
let slidingSyncBuilder = try client.slidingSync().homeserver(url: ServiceLocator.shared.settings.slidingSyncProxyURL.absoluteString)
|
||||
let slidingSyncBuilder = client.slidingSync()
|
||||
|
||||
// Build the visibleRoomsSlidingSyncView here so that it can take advantage of the SS builder cold cache
|
||||
// We will still register the allRoomsSlidingSyncView later, and than will have no cache
|
||||
|
||||
@@ -29,7 +29,8 @@ extension MatrixRustSDK.Session: Codable {
|
||||
userId: try container.decode(String.self, forKey: .userId),
|
||||
deviceId: try container.decode(String.self, forKey: .deviceId),
|
||||
homeserverUrl: try container.decode(String.self, forKey: .homeserverUrl),
|
||||
isSoftLogout: try container.decode(Bool.self, forKey: .isSoftLogout))
|
||||
isSoftLogout: try container.decode(Bool.self, forKey: .isSoftLogout),
|
||||
slidingSyncProxy: try container.decode(String.self, forKey: .slidingSyncProxy))
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@@ -40,9 +41,10 @@ extension MatrixRustSDK.Session: Codable {
|
||||
try container.encode(deviceId, forKey: .deviceId)
|
||||
try container.encode(homeserverUrl, forKey: .homeserverUrl)
|
||||
try container.encode(isSoftLogout, forKey: .isSoftLogout)
|
||||
try container.encode(slidingSyncProxy, forKey: .slidingSyncProxy)
|
||||
}
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case accessToken, refreshToken, userId, deviceId, homeserverUrl, isSoftLogout
|
||||
case accessToken, refreshToken, userId, deviceId, homeserverUrl, isSoftLogout, slidingSyncProxy
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,13 @@ class KeychainControllerTests: XCTestCase {
|
||||
|
||||
// When adding an restoration token.
|
||||
let username = "@test:example.com"
|
||||
let restorationToken = RestorationToken(session: .init(accessToken: "accessToken", refreshToken: "refreshToken", userId: "userId", deviceId: "deviceId", homeserverUrl: "homeserverUrl", isSoftLogout: false))
|
||||
let restorationToken = RestorationToken(session: .init(accessToken: "accessToken",
|
||||
refreshToken: "refreshToken",
|
||||
userId: "userId",
|
||||
deviceId: "deviceId",
|
||||
homeserverUrl: "homeserverUrl",
|
||||
isSoftLogout: false,
|
||||
slidingSyncProxy: "https://my.sync.proxy"))
|
||||
keychain.setRestorationToken(restorationToken, forUsername: username)
|
||||
|
||||
// Then the restoration token should be stored in the keychain.
|
||||
@@ -42,7 +48,13 @@ class KeychainControllerTests: XCTestCase {
|
||||
func testRemovingRestorationToken() {
|
||||
// Given a keychain with a stored restoration token.
|
||||
let username = "@test:example.com"
|
||||
let restorationToken = RestorationToken(session: .init(accessToken: "accessToken", refreshToken: "refreshToken", userId: "userId", deviceId: "deviceId", homeserverUrl: "homeserverUrl", isSoftLogout: false))
|
||||
let restorationToken = RestorationToken(session: .init(accessToken: "accessToken",
|
||||
refreshToken: "refreshToken",
|
||||
userId: "userId",
|
||||
deviceId: "deviceId",
|
||||
homeserverUrl: "homeserverUrl",
|
||||
isSoftLogout: false,
|
||||
slidingSyncProxy: "https://my.sync.proxy"))
|
||||
keychain.setRestorationToken(restorationToken, forUsername: username)
|
||||
XCTAssertEqual(keychain.restorationTokens().count, 1, "The keychain should have 1 restoration token.")
|
||||
XCTAssertEqual(keychain.restorationTokenForUsername(username), restorationToken, "The initial restoration token should match the value that was stored.")
|
||||
@@ -58,7 +70,13 @@ class KeychainControllerTests: XCTestCase {
|
||||
func testRemovingAllRestorationTokens() {
|
||||
// Given a keychain with 5 stored restoration tokens.
|
||||
for index in 0..<5 {
|
||||
let restorationToken = RestorationToken(session: .init(accessToken: "accessToken", refreshToken: "refreshToken", userId: "userId", deviceId: "deviceId", homeserverUrl: "homeserverUrl", isSoftLogout: false))
|
||||
let restorationToken = RestorationToken(session: .init(accessToken: "accessToken",
|
||||
refreshToken: "refreshToken",
|
||||
userId: "userId",
|
||||
deviceId: "deviceId",
|
||||
homeserverUrl: "homeserverUrl",
|
||||
isSoftLogout: false,
|
||||
slidingSyncProxy: "https://my.sync.proxy"))
|
||||
keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com")
|
||||
}
|
||||
XCTAssertEqual(keychain.restorationTokens().count, 5, "The keychain should have 5 restoration tokens.")
|
||||
@@ -73,7 +91,13 @@ class KeychainControllerTests: XCTestCase {
|
||||
func testRemovingSingleRestorationTokens() {
|
||||
// Given a keychain with 5 stored restoration tokens.
|
||||
for index in 0..<5 {
|
||||
let restorationToken = RestorationToken(session: .init(accessToken: "accessToken", refreshToken: "refreshToken", userId: "userId", deviceId: "deviceId", homeserverUrl: "homeserverUrl", isSoftLogout: false))
|
||||
let restorationToken = RestorationToken(session: .init(accessToken: "accessToken",
|
||||
refreshToken: "refreshToken",
|
||||
userId: "userId",
|
||||
deviceId: "deviceId",
|
||||
homeserverUrl: "homeserverUrl",
|
||||
isSoftLogout: false,
|
||||
slidingSyncProxy: "https://my.sync.proxy"))
|
||||
keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com")
|
||||
}
|
||||
XCTAssertEqual(keychain.restorationTokens().count, 5, "The keychain should have 5 restoration tokens.")
|
||||
|
||||
1
changelog.d/410.feature
Normal file
1
changelog.d/410.feature
Normal file
@@ -0,0 +1 @@
|
||||
Enable auto-discovery of sliding sync proxy, directing users to more information when their server doesn't support it.
|
||||
@@ -26,7 +26,7 @@ settings:
|
||||
APP_GROUP_IDENTIFIER: group.$(BASE_APP_GROUP_IDENTIFIER)
|
||||
BASE_BUNDLE_IDENTIFIER: io.element.elementx
|
||||
KEYCHAIN_ACCESS_GROUP_IDENTIFIER: $(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)
|
||||
MARKETING_VERSION: 1.0.19
|
||||
MARKETING_VERSION: 1.0.20
|
||||
CURRENT_PROJECT_VERSION: 1
|
||||
DEVELOPMENT_TEAM: 7J4U792NQT
|
||||
|
||||
@@ -40,7 +40,7 @@ include:
|
||||
packages:
|
||||
MatrixRustSDK:
|
||||
url: https://github.com/matrix-org/matrix-rust-components-swift
|
||||
exactVersion: 1.0.37-alpha
|
||||
exactVersion: 1.0.38-alpha
|
||||
# path: ../matrix-rust-sdk
|
||||
DesignKit:
|
||||
path: DesignKit
|
||||
|
||||
Reference in New Issue
Block a user