diff --git a/Localization/app.json b/Localization/app.json
index 0e34ed2de..fa2af0935 100644
--- a/Localization/app.json
+++ b/Localization/app.json
@@ -523,6 +523,9 @@
"signout": "Sign Out"
}
},
+ "footer": {
+ "mastodon_description": "Mastodon is open source software. You can contribute or report issues on GitHub at %s (%s)"
+ },
"keyboard": {
"close_settings_window": "Close Settings Window"
}
diff --git a/Mastodon/Generated/Strings.swift b/Mastodon/Generated/Strings.swift
index 98c633f3a..163b13da7 100644
--- a/Mastodon/Generated/Strings.swift
+++ b/Mastodon/Generated/Strings.swift
@@ -910,6 +910,12 @@ internal enum L10n {
internal enum Settings {
/// Settings
internal static let title = L10n.tr("Localizable", "Scene.Settings.Title")
+ internal enum Footer {
+ /// Mastodon is open source software. You can contribute or report issues on GitHub at %@ (%@)
+ internal static func mastodonDescription(_ p1: Any, _ p2: Any) -> String {
+ return L10n.tr("Localizable", "Scene.Settings.Footer.MastodonDescription", String(describing: p1), String(describing: p2))
+ }
+ }
internal enum Keyboard {
/// Close Settings Window
internal static let closeSettingsWindow = L10n.tr("Localizable", "Scene.Settings.Keyboard.CloseSettingsWindow")
diff --git a/Mastodon/Resources/ar.lproj/Localizable.strings b/Mastodon/Resources/ar.lproj/Localizable.strings
index 819d6304f..82745b786 100644
--- a/Mastodon/Resources/ar.lproj/Localizable.strings
+++ b/Mastodon/Resources/ar.lproj/Localizable.strings
@@ -310,6 +310,7 @@ any server.";
"Scene.ServerRules.Subtitle" = "These rules are set by the admins of %@.";
"Scene.ServerRules.TermsOfService" = "terms of service";
"Scene.ServerRules.Title" = "Some ground rules.";
+"Scene.Settings.Footer.MastodonDescription" = "Mastodon is open source software. You can contribute or report issues on GitHub at %@ (%@)";
"Scene.Settings.Keyboard.CloseSettingsWindow" = "Close Settings Window";
"Scene.Settings.Section.Appearance.Automatic" = "Automatic";
"Scene.Settings.Section.Appearance.Dark" = "Always Dark";
diff --git a/Mastodon/Resources/en.lproj/Localizable.strings b/Mastodon/Resources/en.lproj/Localizable.strings
index 819d6304f..82745b786 100644
--- a/Mastodon/Resources/en.lproj/Localizable.strings
+++ b/Mastodon/Resources/en.lproj/Localizable.strings
@@ -310,6 +310,7 @@ any server.";
"Scene.ServerRules.Subtitle" = "These rules are set by the admins of %@.";
"Scene.ServerRules.TermsOfService" = "terms of service";
"Scene.ServerRules.Title" = "Some ground rules.";
+"Scene.Settings.Footer.MastodonDescription" = "Mastodon is open source software. You can contribute or report issues on GitHub at %@ (%@)";
"Scene.Settings.Keyboard.CloseSettingsWindow" = "Close Settings Window";
"Scene.Settings.Section.Appearance.Automatic" = "Automatic";
"Scene.Settings.Section.Appearance.Dark" = "Always Dark";
diff --git a/Mastodon/Scene/Settings/SettingsViewController.swift b/Mastodon/Scene/Settings/SettingsViewController.swift
index 8c74bbcfa..b21623265 100644
--- a/Mastodon/Scene/Settings/SettingsViewController.swift
+++ b/Mastodon/Scene/Settings/SettingsViewController.swift
@@ -102,7 +102,13 @@ class SettingsViewController: UIViewController, NeedsDependency {
tableView.register(SettingsLinkTableViewCell.self, forCellReuseIdentifier: String(describing: SettingsLinkTableViewCell.self))
return tableView
}()
-
+
+ let tableFooterActiveLabel: ActiveLabel = {
+ let label = ActiveLabel(style: .default)
+ label.adjustsFontForContentSizeCategory = true
+ label.textAlignment = .center
+ return label
+ }()
lazy var tableFooterView: UIView = {
// init with a frame to fix a conflict ('UIView-Encapsulated-Layout-Height' UIStackView:0x7ffe41e47da0.height == 0)
let view = UIStackView(frame: CGRect(x: 0, y: 0, width: 320, height: 320))
@@ -110,14 +116,9 @@ class SettingsViewController: UIViewController, NeedsDependency {
view.layoutMargins = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
view.axis = .vertical
view.alignment = .center
-
- let label = ActiveLabel(style: .default)
- label.adjustsFontForContentSizeCategory = true
- label.textAlignment = .center
- label.configure(content: "Mastodon is open source software. You can contribute or report issues on GitHub at tootsuite/mastodon (v3.3.0).", emojiDict: [:])
- label.delegate = self
-
- view.addArrangedSubview(label)
+
+ tableFooterActiveLabel.delegate = self
+ view.addArrangedSubview(tableFooterActiveLabel)
return view
}()
@@ -190,6 +191,17 @@ class SettingsViewController: UIViewController, NeedsDependency {
}
}
.store(in: &disposeBag)
+
+ viewModel.currentInstance
+ .receive(on: RunLoop.main)
+ .sink { [weak self] instance in
+ guard let self = self else { return }
+ let version = instance?.version ?? "-"
+ let link = #"tootsuite/mastodon"#
+ let content = L10n.Scene.Settings.Footer.mastodonDescription(link, version)
+ self.tableFooterActiveLabel.configure(content: content, emojiDict: [:])
+ }
+ .store(in: &disposeBag)
}
private func setupView() {
diff --git a/Mastodon/Scene/Settings/SettingsViewModel.swift b/Mastodon/Scene/Settings/SettingsViewModel.swift
index 15aaf66ff..f212a591f 100644
--- a/Mastodon/Scene/Settings/SettingsViewModel.swift
+++ b/Mastodon/Scene/Settings/SettingsViewModel.swift
@@ -32,6 +32,7 @@ class SettingsViewModel {
/// - does not has one
/// - does not find subscription for selected trigger when change trigger
let createSubscriptionSubject = PassthroughSubject<(triggerBy: String, values: [Bool?]), Never>()
+ let currentInstance = CurrentValueSubject(nil)
/// update a subscription when:
/// - change switch for specified alerts
@@ -55,6 +56,26 @@ class SettingsViewModel {
self.processDataSource(setting)
})
.store(in: &disposeBag)
+
+ context.authenticationService.activeMastodonAuthenticationBox
+ .compactMap { $0?.domain }
+ .map { context.apiService.instance(domain: $0) }
+ .switchToLatest()
+ .sink { [weak self] completion in
+ guard let self = self else { return }
+ switch completion {
+ case .failure(let error):
+ os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fetch instance fail: %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription)
+ self.currentInstance.value = nil
+ case .finished:
+ os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fetch instance success", ((#file as NSString).lastPathComponent), #line, #function)
+
+ }
+ } receiveValue: { [weak self] response in
+ guard let self = self else { return }
+ self.currentInstance.value = response.value
+ }
+ .store(in: &disposeBag)
}
deinit {