From 49fa198de580cbaf4a5140f82d2c8bc977f714ef Mon Sep 17 00:00:00 2001 From: Arnfried Griesert Date: Tue, 19 Sep 2023 11:59:20 +0000 Subject: [PATCH] MESSENGER-4565 Added new developer settings options --- Riot/Assets/de.lproj/Bwi.strings | 10 ++ Riot/Assets/en.lproj/Bwi.strings | 10 ++ .../DeveloperSettingsView.swift | 27 ++++++ bwi/DeveloperSettings/MaintenanceView.swift | 73 ++++++++++++++ .../ServerCapabilitiesView.swift | 73 ++++++++++++++ .../ServerSideKeyBackupView.swift | 96 +++++++++++++++++++ .../UserAccountDataView.swift | 96 +++++++++++++++++++ bwi/DeveloperSettings/WellKnownView.swift | 73 ++++++++++++++ bwi/Tools/BWIRestClient.swift | 63 +++++++++++- 9 files changed, 520 insertions(+), 1 deletion(-) create mode 100644 bwi/DeveloperSettings/MaintenanceView.swift create mode 100644 bwi/DeveloperSettings/ServerCapabilitiesView.swift create mode 100644 bwi/DeveloperSettings/ServerSideKeyBackupView.swift create mode 100644 bwi/DeveloperSettings/UserAccountDataView.swift create mode 100644 bwi/DeveloperSettings/WellKnownView.swift diff --git a/Riot/Assets/de.lproj/Bwi.strings b/Riot/Assets/de.lproj/Bwi.strings index 09659fa5f..818ff0ad0 100644 --- a/Riot/Assets/de.lproj/Bwi.strings +++ b/Riot/Assets/de.lproj/Bwi.strings @@ -52,6 +52,16 @@ "bwi_settings_developer_restrict_user" = "Nutzer einschränken"; "bwi_settings_developer_unrestrict_user" = "Nutzereinschränkung aufheben"; "bwi_settings_developer_unmark_banner" = "Banner als nicht gelesen markieren"; +"bwi_settings_developer_well_known" = "Well-Known"; +"bwi_settings_developer_capabilities" = "Capabilities"; +"bwi_settings_developer_maintenance" = "Maintenance"; +"bwi_settings_developer_user_account_data" = "Account Data"; +"bwi_settings_developer_user_account_data_type" = "Type"; +"bwi_settings_developer_key_backup" = "Key Backup"; +"bwi_settings_developer_key_backup_algorithm" = "Algorithmus"; +"bwi_settings_developer_key_backup_count" = "Gespeicherte Schlüssel"; +"bwi_settings_developer_key_backup_etag" = "ETag"; +"bwi_settings_developer_key_backup_version" = "Version"; // MARK: - MDM diff --git a/Riot/Assets/en.lproj/Bwi.strings b/Riot/Assets/en.lproj/Bwi.strings index 0de08e92b..e45e03506 100644 --- a/Riot/Assets/en.lproj/Bwi.strings +++ b/Riot/Assets/en.lproj/Bwi.strings @@ -53,6 +53,16 @@ "bwi_settings_developer_restrict_user" = "Restrict user"; "bwi_settings_developer_unrestrict_user" = "Remove user restriction"; "bwi_settings_developer_unmark_banner" = "Unmark Feature Banner"; +"bwi_settings_developer_well_known" = "Well-Known"; +"bwi_settings_developer_capabilities" = "Capabilities"; +"bwi_settings_developer_maintenance" = "Maintenance"; +"bwi_settings_developer_user_account_data" = "Account Data"; +"bwi_settings_developer_user_account_data_type" = "Type"; +"bwi_settings_developer_key_backup" = "Key Backup"; +"bwi_settings_developer_key_backup_algorithm" = "Algorithm"; +"bwi_settings_developer_key_backup_count" = "Stored Keys"; +"bwi_settings_developer_key_backup_etag" = "ETag"; +"bwi_settings_developer_key_backup_version" = "Version"; // MARK: - MDM diff --git a/bwi/DeveloperSettings/DeveloperSettingsView.swift b/bwi/DeveloperSettings/DeveloperSettingsView.swift index 7fb41e534..25a790b1e 100644 --- a/bwi/DeveloperSettings/DeveloperSettingsView.swift +++ b/bwi/DeveloperSettings/DeveloperSettingsView.swift @@ -94,6 +94,33 @@ struct DeveloperSettingsView: View { } } } + SwiftUI.Section { + NavigationLink { + WellKnownView(session: session) + } label: { + Text(BWIL10n.bwiSettingsDeveloperWellKnown) + } + NavigationLink { + ServerCapabilitiesView(session: session) + } label: { + Text(BWIL10n.bwiSettingsDeveloperCapabilities) + } + NavigationLink { + MaintenanceView(session: session) + } label: { + Text(BWIL10n.bwiSettingsDeveloperMaintenance) + } + NavigationLink { + UserAccountDataView(session: session) + } label: { + Text(BWIL10n.bwiSettingsDeveloperUserAccountData) + } + NavigationLink { + ServerSideKeyBackupView(session: session) + } label: { + Text(BWIL10n.bwiSettingsDeveloperKeyBackup) + } + } } .listStyle(.grouped) .navigationTitle(BWIL10n.bwiSettingsDeveloper) diff --git a/bwi/DeveloperSettings/MaintenanceView.swift b/bwi/DeveloperSettings/MaintenanceView.swift new file mode 100644 index 000000000..236110943 --- /dev/null +++ b/bwi/DeveloperSettings/MaintenanceView.swift @@ -0,0 +1,73 @@ +// +/* + * Copyright (c) 2022 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 + +struct MaintenanceView: View { + @State var jsonString = "" + var session: MXSession? + + var body: some View { + ScrollView { + VStack(alignment: .leading) { + HStack { + Text(jsonString) + .font(.caption) + .padding() + Spacer() + } + } + } + .navigationTitle(BWIL10n.bwiSettingsDeveloperMaintenance) + .navigationBarTitleDisplayMode(.inline) + .onAppear { + Task { + await fetchData() + } + } + } + + private func fetchData() async { + guard let restClient = session?.matrixRestClient else { + return + } + + let responseDict = await withCheckedContinuation { continuation in + restClient.getDowntime { jsonResponse, error in + continuation.resume(returning: jsonResponse) + } + } + await MainActor.run { + do { + if let responseDict = responseDict { + let data = try JSONSerialization.data(withJSONObject: responseDict as Any, options: [.prettyPrinted]) + jsonString = String(data: data, encoding: .utf8) ?? "" + } else { + jsonString = "" + } + } catch { + jsonString = "" + } + } + } +} + +struct MaintenanceView_Previews: PreviewProvider { + static var previews: some View { + MaintenanceView() + } +} diff --git a/bwi/DeveloperSettings/ServerCapabilitiesView.swift b/bwi/DeveloperSettings/ServerCapabilitiesView.swift new file mode 100644 index 000000000..8b05f48df --- /dev/null +++ b/bwi/DeveloperSettings/ServerCapabilitiesView.swift @@ -0,0 +1,73 @@ +// +/* + * Copyright (c) 2022 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 + +struct ServerCapabilitiesView: View { + @State var jsonString = "" + var session: MXSession? + + var body: some View { + ScrollView { + VStack(alignment: .leading) { + HStack { + Text(jsonString) + .font(.caption) + .padding() + Spacer() + } + } + } + .navigationTitle(BWIL10n.bwiSettingsDeveloperCapabilities) + .navigationBarTitleDisplayMode(.inline) + .onAppear { + Task { + await fetchData() + } + } + } + + private func fetchData() async { + guard let restClient = session?.matrixRestClient else { + return + } + + let responseDict = await withCheckedContinuation { continuation in + restClient.getServerCapabilities { jsonResponse, error in + continuation.resume(returning: jsonResponse) + } + } + await MainActor.run { + do { + if let responseDict = responseDict { + let data = try JSONSerialization.data(withJSONObject: responseDict as Any, options: [.prettyPrinted]) + jsonString = String(data: data, encoding: .utf8) ?? "" + } else { + jsonString = "" + } + } catch { + jsonString = "" + } + } + } +} + +struct ServerCapabilitiesView_Previews: PreviewProvider { + static var previews: some View { + ServerCapabilitiesView() + } +} diff --git a/bwi/DeveloperSettings/ServerSideKeyBackupView.swift b/bwi/DeveloperSettings/ServerSideKeyBackupView.swift new file mode 100644 index 000000000..3a867b6c7 --- /dev/null +++ b/bwi/DeveloperSettings/ServerSideKeyBackupView.swift @@ -0,0 +1,96 @@ +// +/* + * Copyright (c) 2022 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 + +struct ServerSideKeyBackupView: View { + @State var algorithm: String? + @State var count: Int? + @State var etag: String? + @State var version: String? + var session: MXSession? + + var body: some View { + Form { + if let algorithm = algorithm { + TitleAndValueView(title: NSLocalizedString(BWIL10n.bwiSettingsDeveloperKeyBackupAlgorithm, comment: ""), value: algorithm) + } + if let count = count { + TitleAndValueView(title: NSLocalizedString(BWIL10n.bwiSettingsDeveloperKeyBackupCount, comment: ""), value: "\(count)") + } + if let etag = etag { + TitleAndValueView(title: NSLocalizedString(BWIL10n.bwiSettingsDeveloperKeyBackupEtag, comment: ""), value: etag) + } + if let version = version { + TitleAndValueView(title: NSLocalizedString(BWIL10n.bwiSettingsDeveloperKeyBackupVersion, comment: ""), value: version) + } + } + .navigationTitle(BWIL10n.bwiSettingsDeveloperKeyBackup) + .navigationBarTitleDisplayMode(.inline) + .onAppear { + Task { + await fetchData() + } + } + } + + private func fetchData() async { + guard let restClient = session?.matrixRestClient else { + return + } + + let responseDict = await withCheckedContinuation { continuation in + restClient.getKeyBackupVersion { jsonResponse, error in + continuation.resume(returning: jsonResponse) + } + } + await MainActor.run { + if let responseDict = responseDict { + algorithm = responseDict["algorithm"] as? String + count = responseDict["count"] as? Int + etag = responseDict["etag"] as? String + version = responseDict["version"] as? String + } else { + algorithm = nil + count = nil + etag = nil + version = nil + } + } + } + +} + +struct TitleAndValueView: View { + var title: String + var value: String + + var body: some View { + HStack(alignment: .firstTextBaseline) { + Text(title) + Spacer() + Text(value) + .foregroundColor(.secondary) + } + } +} + +struct ServerSideKeyBackupView_Previews: PreviewProvider { + static var previews: some View { + ServerSideKeyBackupView() + } +} diff --git a/bwi/DeveloperSettings/UserAccountDataView.swift b/bwi/DeveloperSettings/UserAccountDataView.swift new file mode 100644 index 000000000..ec423dd99 --- /dev/null +++ b/bwi/DeveloperSettings/UserAccountDataView.swift @@ -0,0 +1,96 @@ +// +/* + * Copyright (c) 2022 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 + +fileprivate let availableAccountDataTypes: [String] = [ + "de.bwi.personal_notes_room", + "de.bwi.should_show_ios_release_notes", + "de.bwi.notification_times", + "de.bwi.top_banner_features", + "de.bwi.notifications", + "im.vector.setting.integration_provisioning", + "im.vector.setting.allowed_widgets" +] + +struct UserAccountDataView: View { + @State var selectedAccountDataType = "de.bwi.personal_notes_room" + @State var jsonString = "" + var session: MXSession? + + var body: some View { + Form { + SwiftUI.Section { + Picker(BWIL10n.bwiSettingsDeveloperUserAccountDataType, selection: $selectedAccountDataType) { + ForEach(availableAccountDataTypes, id:\.self) { type in + Text(type).tag(type) + } + } + .onChange(of: selectedAccountDataType) { newValue in + Task { + await fetchData(forType: newValue) + } + } + } + if !jsonString.isEmpty { + SwiftUI.Section { + Text(jsonString) + .font(.caption) + .padding() + } + } + } + .navigationTitle(BWIL10n.bwiSettingsDeveloperUserAccountData) + .navigationBarTitleDisplayMode(.inline) + .onAppear { + Task { + await fetchData(forType: selectedAccountDataType) + } + } + } + + private func fetchData(forType accountDataType: String) async { + guard let restClient = session?.matrixRestClient else { + return + } + + let responseDict = await withCheckedContinuation { continuation in + restClient.getAccountData(forType: accountDataType) { jsonResponse, error in + continuation.resume(returning: jsonResponse) + } + } + await MainActor.run { + do { + if let responseDict = responseDict { + print(responseDict) + let data = try JSONSerialization.data(withJSONObject: responseDict as Any, options: [.prettyPrinted]) + jsonString = String(data: data, encoding: .utf8) ?? "" + } else { + jsonString = "" + } + } catch { + jsonString = "" + } + } + } +} + +struct UserAccountDataView_Previews: PreviewProvider { + static var previews: some View { + UserAccountDataView() + } +} diff --git a/bwi/DeveloperSettings/WellKnownView.swift b/bwi/DeveloperSettings/WellKnownView.swift new file mode 100644 index 000000000..df63e02eb --- /dev/null +++ b/bwi/DeveloperSettings/WellKnownView.swift @@ -0,0 +1,73 @@ +// +/* + * Copyright (c) 2022 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 + +struct WellKnownView: View { + @State var jsonString = "" + var session: MXSession? + + var body: some View { + ScrollView { + VStack(alignment: .leading) { + HStack { + Text(jsonString) + .font(.caption) + .padding() + Spacer() + } + } + } + .navigationTitle(BWIL10n.bwiSettingsDeveloperWellKnown) + .navigationBarTitleDisplayMode(.inline) + .onAppear { + Task { + await fetchData() + } + } + } + + private func fetchData() async { + guard let restClient = session?.matrixRestClient else { + return + } + + let responseDict = await withCheckedContinuation { continuation in + restClient.getWellKnown { jsonResponse, error in + continuation.resume(returning: jsonResponse) + } + } + await MainActor.run { + do { + if let responseDict = responseDict { + let data = try JSONSerialization.data(withJSONObject: responseDict as Any, options: [.prettyPrinted]) + jsonString = String(data: data, encoding: .utf8) ?? "" + } else { + jsonString = "" + } + } catch { + jsonString = "" + } + } + } +} + +struct WellKnownView_Previews: PreviewProvider { + static var previews: some View { + WellKnownView() + } +} diff --git a/bwi/Tools/BWIRestClient.swift b/bwi/Tools/BWIRestClient.swift index ff71310dc..21b49bae4 100644 --- a/bwi/Tools/BWIRestClient.swift +++ b/bwi/Tools/BWIRestClient.swift @@ -17,7 +17,49 @@ import Foundation public extension MXRestClient { + + @discardableResult + func getWellKnown(completion: @escaping (_ jsonResponse: Dictionary?, _ error: Error?) -> Void) -> MXHTTPOperation? { + + guard let httpClient = httpClient else { + completion(nil, "HTTPClient not available") + return nil + } + + let path = ".well-known/matrix/client" + + return httpClient.request(withMethod: "GET", path: path, parameters: nil, success: { response in + guard response != nil else { + completion(nil, "Response empty") + return + } + completion(response, nil) + }, failure: { (error) in + completion(nil, error) + }) + } + @discardableResult + func getServerCapabilities(completion: @escaping (_ jsonResponse: Dictionary?, _ error: Error?) -> Void) -> MXHTTPOperation? { + + guard let httpClient = httpClient else { + completion(nil, "HTTPClient not available") + return nil + } + + let path = apiPathPrefix + "/capabilities" + + return httpClient.request(withMethod: "GET", path: path, parameters: nil, success: { response in + guard response != nil else { + completion(nil, "Response empty") + return + } + completion(response, nil) + }, failure: { (error) in + completion(nil, error) + }) + } + @discardableResult func getAccountData(forType type: String, completion: @escaping (_ jsonResponse: Dictionary?, _ error: Error?) -> Void) -> MXHTTPOperation? { @@ -73,7 +115,26 @@ public extension MXRestClient { return nil } - let path = "_matrix/cmaintenance" + let path = "/_matrix/cmaintenance" + + return httpClient.request(withMethod: "GET", path: path, parameters: nil, success: { response in + guard response != nil else { + completion(nil, "Response empty") + return + } + completion(response, nil) + }, failure: { (error) in + completion(nil, error) + }) + } + + @discardableResult + func getKeyBackupVersion(completion: @escaping (_ jsonResponse: Dictionary?, _ error: Error?) -> Void) -> MXHTTPOperation? { + guard let httpClient = httpClient else { + return nil + } + + let path = "/_matrix/client/v3/room_keys/version" return httpClient.request(withMethod: "GET", path: path, parameters: nil, success: { response in guard response != nil else {