feat: add migration dialog 1 (MESSENGER-7553)

This commit is contained in:
Jan Niklas Grabowski
2025-09-17 17:34:29 +02:00
parent 00d9048124
commit bed94efd52
15 changed files with 375 additions and 20 deletions

View File

@@ -677,7 +677,7 @@ class BWIBuildSettings: NSObject {
var isLabsFederationEnabled
// Migration status from wellknown config
@UserDefault(key: UserDefaultsKeys.BuMXMigrationInfoLevelKey, defaultValue: 0, storage: RiotSettings.defaults)
@UserDefault(key: UserDefaultsKeys.BuMXMigrationInfoLevelKey, defaultValue: 1, storage: RiotSettings.defaults)
var BuMXMigrationInfoLevel
// Migration level already shown

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "BuM_Appicon-next_iOS_1024.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@@ -748,8 +748,28 @@
"room_error_join_failed_federation_disabled_message" = "Du kannst den Raum nicht beitreten. Grund: Die Föderation wurde für diesen Raum aufgehoben.";
// MARK: migration to new client
// Banner
"bwi_mobile_dialog_m_banner_title" = "Wechsel zum BundesMessengerX";
"bwi_mobileMdialog_m1_banner_text" = "Das ist eine neue, technisch optimierte App vom BuM. Du kannst sie jetzt schon ausprobieren, bevor bald alle umsteigen müssen.";
"bwi_mobileMdialog_m1_banner_text_bold" = " Alle deine Kontakte und Nachrichten bleiben erhalten.";
"bwi_mobile_dialog_m_banner_button2" = "Erfahre mehr";
"bwi_mobile_dialog_m_banner_button1" = "Später erinnern";
// Sheet page 1
"bwi_mobile_dialog_m_more_title" = "BundesMessengerX";
"bwi_mobile_dialog_m1_more_text_1" = "Diese App wird bald abgeschaltet und durch eine neue technisch optimierte App ersetzt ";
"bwi_mobile_dialog_m1_more_text_2" = "(alle deine Kontakte und Nachrichten bleiben erhalten).";
"bwi_mobile_dialog_m1_more_text_3" = "\n\nDich erwartet u.a.:";
"bwi_mobile_dialog_m1_more_text_bullet_1" = "schnellere Performance";
"bwi_mobile_dialog_m1_more_text_bullet_2" = "verbessertes Design";
"bwi_mobile_dialog_m1_more_text_bullet_3" = "neue Funktionen, wie Nachrichten anheften";
"bwi_mobile_dialog_m1_more_text_bullet_4" = "optimierte Barrierefreiheit";
// Sheet page 2
"bwi_mobile_dialog_m_more2_title" = "Wechsel jetzt:";
"bwi_mobile_dialog_m_more2_text_1" = "Benutzername hier kopieren";
"bwi_mobile_dialog_m_more2_text_2" = "App über den Button herunterladen";
"bwi_mobile_dialog_m_more2_text_3" = "Mit deinen Anmeldedaten einloggen";
"bwi_mobile_dialog_m_more_button" = "Neue App herunterladen";
"bwi_mobile_dialog_m_more_success" = "Benutzername kopiert";

View File

@@ -661,8 +661,27 @@
"room_error_join_failed_federation_disabled_message" = "You cannot join the room. The federation for this room has been withdrawn.";
// MARK: migration to new client
// Banner
"bwi_mobile_dialog_m_banner_title" = "Change to BundesMessengerX";
"bwi_mobileMdialog_m1_banner_text" = "This is a new technically optimized app from BuM. You can try it out now before everyone has to switch soon.";
"bwi_mobileMdialog_m1_banner_text_bold" = " All your contacts and messages will be retained.";
"bwi_mobile_dialog_m_banner_button2" = "Learn more";
"bwi_mobile_dialog_m_banner_button1" = "Remember later";
// Sheet page 1
"bwi_mobile_dialog_m_more_title" = "BundesMessengerX";
"bwi_mobile_dialog_m1_more_text_1" = "This app will soon be shut down and replaced by a new technically optimized app ";
"bwi_mobile_dialog_m1_more_text_2" = "(all your contacts and messages will remain).";
"bwi_mobile_dialog_m1_more_text_3" = "\n\nAmong other things, you can expect:";
"bwi_mobile_dialog_m1_more_text_bullet_1" = "faster performance";
"bwi_mobile_dialog_m1_more_text_bullet_2" = "improved design";
"bwi_mobile_dialog_m1_more_text_bullet_3" = "new functions, such as pinning messages";
"bwi_mobile_dialog_m1_more_text_bullet_4" = "optimized accessibility";
// Sheet page 2
"bwi_mobile_dialog_m_more2_title" = "Change now:";
"bwi_mobile_dialog_m_more2_text_1" = "Copy user name here";
"bwi_mobile_dialog_m_more2_text_2" = "Download app via the button";
"bwi_mobile_dialog_m_more2_text_3" = "Log in with your credentials";
"bwi_mobile_dialog_m_more_button" = "Download new app";
"bwi_mobile_dialog_m_more_success" = "user name copied";

View File

@@ -299,6 +299,34 @@ public class BWIL10n: NSObject {
public static var bwiMdmLogoutMessage: String {
return BWIL10n.tr("Bwi", "bwi_mdm_logout_message")
}
/// Diese App wird bald abgeschaltet und durch eine neue technisch optimierte App ersetzt
public static var bwiMobileDialogM1MoreText1: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m1_more_text_1")
}
/// (alle deine Kontakte und Nachrichten bleiben erhalten).
public static var bwiMobileDialogM1MoreText2: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m1_more_text_2")
}
/// \n\nDich erwartet u.a.:
public static var bwiMobileDialogM1MoreText3: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m1_more_text_3")
}
/// schnellere Performance
public static var bwiMobileDialogM1MoreTextBullet1: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m1_more_text_bullet_1")
}
/// verbessertes Design
public static var bwiMobileDialogM1MoreTextBullet2: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m1_more_text_bullet_2")
}
/// neue Funktionen, wie Nachrichten anheften
public static var bwiMobileDialogM1MoreTextBullet3: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m1_more_text_bullet_3")
}
/// optimierte Barrierefreiheit
public static var bwiMobileDialogM1MoreTextBullet4: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m1_more_text_bullet_4")
}
/// Später erinnern
public static var bwiMobileDialogMBannerButton1: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m_banner_button1")
@@ -311,6 +339,34 @@ public class BWIL10n: NSObject {
public static var bwiMobileDialogMBannerTitle: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m_banner_title")
}
/// Benutzername hier kopieren
public static var bwiMobileDialogMMore2Text1: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m_more2_text_1")
}
/// App über den Button herunterladen
public static var bwiMobileDialogMMore2Text2: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m_more2_text_2")
}
/// Mit deinen Anmeldedaten einloggen
public static var bwiMobileDialogMMore2Text3: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m_more2_text_3")
}
/// Wechsel jetzt:
public static var bwiMobileDialogMMore2Title: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m_more2_title")
}
/// Neue App herunterladen
public static var bwiMobileDialogMMoreButton: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m_more_button")
}
/// Benutzername kopiert
public static var bwiMobileDialogMMoreSuccess: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m_more_success")
}
/// BundesMessengerX
public static var bwiMobileDialogMMoreTitle: String {
return BWIL10n.tr("Bwi", "bwi_mobile_dialog_m_more_title")
}
/// Das ist eine neue, technisch optimierte App vom BuM. Du kannst sie jetzt schon ausprobieren, bevor bald alle umsteigen müssen.
public static var bwiMobileMdialogM1BannerText: String {
return BWIL10n.tr("Bwi", "bwi_mobileMdialog_m1_banner_text")

View File

@@ -411,6 +411,7 @@ internal class Asset: NSObject {
@objc(AssetSharedImages) internal class SharedImages: NSObject {
internal static let cancel = ImageAsset(name: "cancel")
internal static let e2eVerified = ImageAsset(name: "e2e_verified")
internal static let bumxLogo = ImageAsset(name: "bumx_logo")
internal static let horizontalLogo = ImageAsset(name: "horizontal_logo")
internal static let loginFlowLogo = ImageAsset(name: "login_flow_logo")
internal static let radioButtonDefault = ImageAsset(name: "radio-button-default")

View File

@@ -1894,7 +1894,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
MXSession* session = [self mxSession];
if(!session)
return;
FeatureBannerVisibilityService *featureBannerService = [[FeatureBannerVisibilityService alloc] initWithMxSession:session];
FeatureBannerVisibilityService *featureBannerService = [FeatureBannerVisibilityService alloc];
[featureBannerService isUnreadWithCompletion: ^(BOOL unread) {
if (unread) {
// this notification will be called either if the user clicked on the banner or wants to hide it
@@ -1932,7 +1932,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
MXSession* session = [self mxSession];
if(!session)
return;
FeatureBannerVisibilityService *featureBannerService = [[FeatureBannerVisibilityService alloc] initWithMxSession:session];
FeatureBannerVisibilityService *featureBannerService = [FeatureBannerVisibilityService alloc];
[featureBannerService markAsRead];
self->shouldHideFeatureBanner = TRUE;
[self.delegate dataSource:self didCellChange:nil];

View File

@@ -772,6 +772,11 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {
self.currentMatrixSession?.refreshHomeserverWellknown(false, success: { wellknown in
// bwi: #5706 fix crash: only show matomo alert when wellknown is available
wellknown?.updateFederationStatus()
// BWI #7564 add migration level
if let migrationLevel = wellknown?.migrationInfoLevel() {
BWIBuildSettings.shared.BuMXMigrationInfoLevel = migrationLevel
}
// BWI #7564 END
self.bwiCheckForMatomoPromt()
}, failure: nil)
}

View File

@@ -250,7 +250,11 @@ class AuthenticationService: NSObject {
if let wellKnown = try? await wellKnown(for: homeserverURL) {
self.wellknown = wellKnown
wellknown?.updateFederationStatus()
// BWI #7564 add migration level
if let migrationLevel = wellknown?.migrationInfoLevel() {
BWIBuildSettings.shared.BuMXMigrationInfoLevel = migrationLevel
}
// BWI #7564 END
if let baseURL = URL(string: wellKnown.homeServer.baseUrl) {
homeserverURL = baseURL
}

View File

@@ -229,15 +229,11 @@ fileprivate func unrestrictUser(mxSession: MXSession?) -> Bool {
return true
}
fileprivate func unmarkBannerVersion(mxSession: MXSession?) -> Bool {
guard let mxSession = mxSession else {
return false
}
fileprivate func unmarkBannerVersion(mxSession: MXSession?) -> Bool {
// NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
_ = FeatureBannerVisibilityService(mxSession: mxSession).markAsUnread(version: version)
FeatureBannerVisibilityService().markAsUnread(version: version)
}
return true

View File

@@ -90,8 +90,10 @@ protocol FeatureBannerDelegate {
}
func didPressShowDetails() {
hideTopBanner()
// Show Details
let migrationInfoView = MigrationInfoView().interactiveDismissDisabled(true)
let hostingViewController = UIHostingController(rootView: migrationInfoView)
hostingViewController.modalPresentationStyle = .popover
hostingController.parent?.present(hostingViewController, animated: true, completion: nil)
}
@objc func closeModal() {
@@ -169,7 +171,7 @@ struct FeatureBannerView: View {
.font(.system(size: 18))
.bold()
.padding(10)
.foregroundColor(Color(ThemeService.shared().theme.tintColor))
.foregroundColor(ThemeService.shared().isCurrentThemeDark() ? Color(ThemeService.shared().theme.tintColor) : Color.black)
Spacer()
}
}

View File

@@ -0,0 +1,243 @@
//
/*
* Copyright (c) 2025 BWI GmbH
*
* 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 SwiftUI
// MARK: Migraion Info View
struct MigrationInfoView: View {
@Environment(\.dismiss) var dismissView
@State private var selectedTab = 1
var body: some View {
TabView(selection: $selectedTab) {
MigrationInfoViewOne()
.tag(1)
MigrationInfoViewTwo()
.tag(2)
}
.tabViewStyle(.page)
.indexViewStyle(.page(backgroundDisplayMode: .always))
//.background(Color.white.ignoresSafeArea())
.onAppear() {
FeatureBannerVisibilityService().markAsRead()
NotificationCenter.default.post(name: .bwiMarkTopBannerAsRead, object: self, userInfo: ["type" : "feature_banner"])
}
.overlay {
VStack() {
HStack() {
Spacer()
Button {
dismissView()
} label: {
Image(Asset.Images.closeButton.name)
.renderingMode(.template)
.resizable()
.frame(width: 36, height: 36)
.foregroundColor(Color(ThemeService.shared().theme.tintColor))
.padding(20)
}
}
Spacer()
HStack() {
Button {
withAnimation {
selectedTab = 1
}
} label: {
Image(systemName: "arrow.left")
.resizable()
.frame(width: 24, height: 24)
.foregroundStyle(Color(ThemeService.shared().theme.tintColor))
}
.padding(EdgeInsets(top: 20, leading: 30, bottom: 10, trailing: 30))
.opacity(selectedTab == 1 ? 0 : 1)
Spacer()
Button {
withAnimation {
selectedTab = 2
}
} label: {
Image(systemName: "arrow.right")
.resizable()
.frame(width: 24, height: 24)
.foregroundStyle(Color(ThemeService.shared().theme.tintColor))
}
.padding(EdgeInsets(top: 20, leading: 30, bottom: 10, trailing: 30))
.opacity(selectedTab == 2 ? 0 : 1)
}
}
}
}
}
// MARK: Migraion Info View one
struct MigrationInfoViewOne: View {
var body: some View {
GeometryReader { geo in
ScrollView(.vertical) {
VStack(alignment: .center, spacing: 30) {
Spacer()
header
infoText
Spacer()
}
.frame(width: geo.size.width, height: geo.size.height)
}
}
}
var header: some View {
VStack(spacing: 50) {
Image("bumx_logo")
.resizable()
.frame(width: 150, height: 150)
.clipShape(.rect(cornerRadius: 26))
.overlay(
RoundedRectangle(cornerRadius: 26)
.stroke(.gray, lineWidth: 0.4)
)
Text(BWIL10n.bwiMobileDialogMMoreTitle)
.font(.title)
.bold()
}
}
var infoText: some View {
VStack(alignment: .leading) {
Text(BWIL10n.bwiMobileDialogM1MoreText1) +
Text(BWIL10n.bwiMobileDialogM1MoreText2).bold() +
Text(BWIL10n.bwiMobileDialogM1MoreText3)
VStack(alignment: .leading) {
HStack(alignment: .top) {
Text("")
Text(BWIL10n.bwiMobileDialogM1MoreTextBullet1)
}
HStack(alignment: .top) {
Text("")
Text(BWIL10n.bwiMobileDialogM1MoreTextBullet2)
}
HStack(alignment: .top) {
Text("")
Text(BWIL10n.bwiMobileDialogM1MoreTextBullet3)
}
HStack(alignment: .top) {
Text("")
Text(BWIL10n.bwiMobileDialogM1MoreTextBullet4)
}
}
.multilineTextAlignment(.leading)
.padding(.leading, 16)
}
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)
.padding(EdgeInsets(top: 0, leading: 30, bottom: 0, trailing: 30))
}
}
// MARK: Migraion Info View two
struct MigrationInfoViewTwo: View {
var body: some View {
GeometryReader { geo in
ScrollView(.vertical) {
VStack(alignment: .center, spacing: 30) {
Spacer()
header
instructionsList
Spacer()
downloadNewAppButton
}
.frame(width: geo.size.width, height: geo.size.height)
}
}
}
var header: some View {
VStack(spacing: 50) {
Image("bumx_logo")
.resizable()
.frame(width: 150, height: 150)
.clipShape(.rect(cornerRadius: 26))
.overlay(
RoundedRectangle(cornerRadius: 26)
.stroke(.gray, lineWidth: 0.4)
)
Text(BWIL10n.bwiMobileDialogMMore2Title)
.font(.title)
.bold()
}
}
var instructionsList: some View {
VStack(alignment: .leading, spacing: 10) {
HStack() {
Text("1.")
Button(action: {
}, label: {
Text(BWIL10n.bwiMobileDialogMMore2Text1)
.underline()
Image(systemName: "square.on.square")
.resizable()
.frame(width: 15, height: 15)
})
}
HStack() {
Text("2.")
Text(BWIL10n.bwiMobileDialogMMore2Text2)
}
HStack() {
Text("3.")
Text(BWIL10n.bwiMobileDialogMMore2Text3)
}
}
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)
}
var downloadNewAppButton: some View {
Button(action: {
guard let bumxAppStoreURL = URL(string: "itms-apps://itunes.apple.com/app/id6738500048") else { return }
guard UIApplication.shared.canOpenURL(bumxAppStoreURL) else { return }
UIApplication.shared.open(bumxAppStoreURL, options: [:], completionHandler: nil)
}, label: {
Text(BWIL10n.bwiMobileDialogMMoreButton)
.foregroundColor(.white)
.padding(.vertical, 10)
.padding(.horizontal, 50)
.background(Color(ThemeService.shared().theme.tintColor))
.clipShape(RoundedRectangle(cornerRadius: 10))
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)
})
.padding(.bottom, 100)
}
}

View File

@@ -43,7 +43,7 @@ import UIKit
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
FeatureBannerVisibilityService(mxSession: self.session).markAsRead()
FeatureBannerVisibilityService().markAsRead()
NotificationCenter.default.post(name: .bwiMarkTopBannerAsRead, object: self, userInfo: ["type" : "feature_banner"])
}

View File

@@ -29,12 +29,6 @@ import Foundation
static let featureVisibility = "de.bwi.should_show_ios_release_notes"
}
private let session:MXSession
init(mxSession: MXSession) {
self.session = mxSession
}
func markAsRead() {
BWIBuildSettings.shared.didShowBuMXMigrationInfoLevel = BWIBuildSettings.shared.BuMXMigrationInfoLevel
}