Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Riot/Managers/Settings/RiotSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -426,10 +426,15 @@ final class RiotSettings: NSObject {
var tchapSecureBackupNextDisplayDate

// Tchap has tried to automatically activate cross-signing.
// This automatic activation must be tried only once because if it fails, it could pro;pt user each time the application is activated.
// This automatic activation must be tried only once because if it fails, it could prompt user each time the application is activated.
@UserDefault(key: "tchapCrossSigningAutoActivationTried", defaultValue: false, storage: defaults)
var tchapCrossSigningAutoActivationTried

// Tchap migrate to new Tchap last display.
// Register the last time the new Tchap Migration alert was displayed to decide if enough time has spent before showing the alert again.
@UserDefault(key: "tchapNewTchapMigrationAlertLastPresentationDate", defaultValue: Date.distantPast, storage: defaults)
var tchapNewTchapMigrationAlertLastPresentationDate

}

// MARK: - RiotSettings notification constants
Expand Down
81 changes: 81 additions & 0 deletions Riot/Modules/Home/AllChats/AllChatsCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,50 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {
self.createLeftButtonItem(for: allChatsViewController)
}

// Tchap: check if Migration to new Tchap View should be presented to user.
private func tchapCheckMigration(userSession: UserSession) {
// Tchap: check for new Tchap advertizing in wellknown.
Task {

// Don't present alert more than once a day.
guard Date.now.timeIntervalSince(RiotSettings.shared.tchapNewTchapMigrationAlertLastPresentationDate) > 86400 else {
return
}

RiotSettings.shared.tchapNewTchapMigrationAlertLastPresentationDate = .now

if let homeServerName = MXTools.serverName(inMatrixIdentifier: userSession.userId),
let newTchapAppStoreUrl = await newTchapAppStoreUrl(for: homeServerName) {

// Check if a ViewController is already presented. If so, present our Migration view from this presented view controller.
Task { @MainActor in

let presentingViewController = (navigationRouter as? NavigationRouter)?.presentedViewController()

// Prepare Coordinator
let checkMigrateToNewTchapCoordinator = MigrateToNewTchapCoordinator(appStoreUrl: newTchapAppStoreUrl) { [weak self] in
// Dismiss Migration to new Tchap View from right context.
if let presentingViewController {
presentingViewController.dismiss(animated: true, completion: nil)
} else {
self?.navigationRouter.dismissModule(animated: true, completion: nil)
}
}

// Start Coordinator
checkMigrateToNewTchapCoordinator.start()

// Present Coordinator in right context.
if let presentingViewController {
presentingViewController.present(checkMigrateToNewTchapCoordinator.toPresentable(), animated: true)
} else {
navigationRouter.present(checkMigrateToNewTchapCoordinator, animated: true)
}
}
}
}
}

@objc private func userSessionsServiceWillRemoveUserSession(_ notification: Notification) {
guard let userSession = notification.userInfo?[UserSessionsService.NotificationUserInfoKey.userSession] as? UserSession else {
return
Expand Down Expand Up @@ -702,6 +746,33 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {
viewController.loadViewIfNeeded()
return viewController
}


// Tchap: check advertizing of new Tchap in returned wellknown
//
// Tchap: the key "fr.gouv.tchap.tchapx" is present in the payload if the homeserver advertizes the new Tchap.
// Check matrix/client wellknown content for "fr.gouv.tchap.tchapx" key.
//
// The awaited content is the urls of the applications on the application stores.
//
// "fr.gouv.tchap.tchapx": {
// "android": "https://store.tchapx.android",
// "ios": "https://apps.apple.com/fr/app/tchap-x/id6736991029"
// }
//
// Returns the new Tchap appStore URL if found in well-known.
private func newTchapAppStoreUrl(for homeserverName: String) async -> URL? {
let homeserverAddress = HomeserverAddress.sanitized(homeserverName)
guard let homeserverURL = URL(string: homeserverAddress),
let wellknown = try? await AuthenticationService.shared.wellKnown(for: homeserverURL),
let wellknownEntries = wellknown.jsonDictionary() as? [String: Any],
let newTchapEntry = wellknownEntries["fr.gouv.tchap.tchapx"] as? [String: String],
let newTchapIosEntry = newTchapEntry["ios"],
let appStoreUrl = URL(string: newTchapIosEntry) else {
return nil
}
return appStoreUrl
}
}

extension AllChatsCoordinator: SignOutFlowPresenterDelegate {
Expand Down Expand Up @@ -766,6 +837,16 @@ extension AllChatsCoordinator: AllChatsViewControllerDelegate {
self.navigationRouter.present(router, animated: true)

}

// Tchap: new Tchap migration
func allChatsViewControllerShouldShowNewTchapMigration(_ allChatsViewController: AllChatsViewController) {
// This method can be called by `viewDidAppear` before device is verified.
// In this case, userSession will be nil.
guard let userSession = self.parameters.userSessionsService.mainUserSession else {
return
}
tchapCheckMigration(userSession: userSession)
}
}

// MARK: - RoomCoordinatorDelegate
Expand Down
6 changes: 5 additions & 1 deletion Riot/Modules/Home/AllChats/AllChatsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ protocol AllChatsViewControllerDelegate: AnyObject {
// Tchap: Add methods to use Tchap specific flows.
func allChatsViewControllerShouldOpenRoomCreation(_ allChatsViewController: AllChatsViewController)
func allChatsViewControllerShouldOpenRoomList(_ allChatsViewController: AllChatsViewController)
func allChatsViewControllerShouldShowNewTchapMigration(_ allChatsViewController: AllChatsViewController)
}

class AllChatsViewController: HomeViewController {
Expand Down Expand Up @@ -178,7 +179,10 @@ class AllChatsViewController: HomeViewController {
return
}

AppDelegate.theDelegate().checkAppVersion()
// Tchap: Tchap doesn't check for version update anymore.
// AppDelegate.theDelegate().checkAppVersion()

allChatsDelegate?.allChatsViewControllerShouldShowNewTchapMigration(self)

if BuildSettings.newAppLayoutEnabled && !RiotSettings.shared.allChatsOnboardingHasBeenDisplayed {
// Tchap: Disable new layout tutorials. Wait for an updated tutorials before show it.
Expand Down
7 changes: 7 additions & 0 deletions Riot/Routers/NavigationRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -403,3 +403,10 @@ extension NavigationRouter {
static let navigationController = "navigationController"
}
}

// Tchap: Used to know from which controller or coordinator to present New Tchap Migration View.
extension NavigationRouter {
func presentedViewController() -> UIViewController? {
navigationController.presentedViewController
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,9 @@ class AuthenticationService: NSObject {
}

/// Perform a well-known request on the specified homeserver URL.
private func wellKnown(for homeserverURL: URL) async throws -> MXWellKnown {
// Tchap: make wellknown() method available outside (needed in AllChatsCoordinator to check the existence of new Tchap application).
// private func wellKnown(for homeserverURL: URL) async throws -> MXWellKnown {
func wellKnown(for homeserverURL: URL) async throws -> MXWellKnown {
let wellKnownClient = clientType.init(homeServer: homeserverURL, unrecognizedCertificateHandler: nil)

// The .well-known/matrix/client API is often just a static file returned with no content type.
Expand Down
7 changes: 7 additions & 0 deletions Tchap/Assets/Localizations/fr.lproj/Tchap.strings
Original file line number Diff line number Diff line change
Expand Up @@ -379,3 +379,10 @@
// Chat participants
"room_participants_leave_not_allowed_for_last_owner_msg" = "Vous ne pouvez pas quitter ce salon car vous êtes le seul administrateur.";

////////////////////////////////////////////////////////////////////////////////
// MARK: Migrate to New Tchap
"migrate_to_new_tchap_title" = "Tchap évolue !";
"migrate_to_new_tchap_message" = "Une nouvelle application est disponible pour iPhone. Veuillez la télécharger pour accéder à de nouvelles fonctionnalités.";
"migrate_to_new_tchap_warning" = "L'ancienne application sera bientôt abandonnée. Pour migrer, installez la nouvelle application, connectez-vous en vérifiant votre identité, puis supprimez l'ancienne.";
"migrate_to_new_tchap_action_accept_title" = "Télécharger";
"migrate_to_new_tchap_action_help_title" = "Aide à la migration";
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "next_tchap_logo@1x.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "next_tchap_logo@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "next_tchap_logo@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright 2019 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 UIKit

final class MigrateToNewTchapCoordinator: MigrateToNewTchapCoordinatorType {

// MARK: Constant

private enum Constants {
static let nextTchapHelpURL = "https://app.crisp.chat/website/6dacc68e-de3a-4511-8177-1339616098de/helpdesk/articles/fr/45a1de71-1093-4392-ab09-c88a6338c181/"
}

// MARK: - Properties

// MARK: Private

private(set) var migrateToNewTchapViewController: MigrateToNewTchapViewController!

// MARK: Public

var childCoordinators: [Coordinator] = []

weak var delegate: MigrateToNewTchapCoordinatorDelegate?

// MARK: - Setup

init(appStoreUrl: URL, cancelAction: @escaping () -> Void) {
let migrateToNewTchapViewModel = MigrateToNewTchapViewModel(
appStoreAppUrl: appStoreUrl,
helpArticleUrl: URL(string: Constants.nextTchapHelpURL)!, // swiftlint:disable:this force_unwrapping
actionCancel: cancelAction)
migrateToNewTchapViewController = MigrateToNewTchapViewController.instantiate(with: migrateToNewTchapViewModel)
}

// MARK: - Public methods

func start() {
}

func toPresentable() -> UIViewController {
return self.migrateToNewTchapViewController
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
Copyright 2019 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

protocol MigrateToNewTchapCoordinatorDelegate: AnyObject {
func migrateToNewTchapCoordinatorDidCancel(_ coordinator: MigrateToNewTchapCoordinatorType)
}

protocol MigrateToNewTchapCoordinatorType: Coordinator, Presentable {
var delegate: MigrateToNewTchapCoordinatorDelegate? { get set }
}
Loading
Loading