diff --git a/src/App/Localizable.xcstrings b/src/App/Localizable.xcstrings index d3c0554..c97c707 100644 --- a/src/App/Localizable.xcstrings +++ b/src/App/Localizable.xcstrings @@ -3971,6 +3971,88 @@ } } }, + "Copyright" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "حقوق النشر" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Urheberrechte" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Derechos de autor" + } + }, + "es-419" : { + "stringUnit" : { + "state" : "translated", + "value" : "Derechos de autor" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Droits d'auteur" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Diritto d'autore" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "著作権" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "저작권" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prawo autorskie" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Direito autoral" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Авторские права" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "版权" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "版權" + } + } + } + }, "Data" : { "localizations" : { "ar" : { @@ -4135,6 +4217,88 @@ } } }, + "Data Source Info" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "معلومات مصدر البيانات" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Informationen zur Datenquelle" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Información de origen de datos" + } + }, + "es-419" : { + "stringUnit" : { + "state" : "translated", + "value" : "Información de origen de datos" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Informations sur la source de données" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Informazioni sull'origine dati" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "データソース情報" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "데이터 소스 정보" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Informacje o źródle danych" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Informações da Fonte de Dados" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Информация источника данных" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "数据源信息" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "資料來源資訊" + } + } + } + }, "Delete Favorite" : { "localizations" : { "ar" : { @@ -6743,6 +6907,12 @@ }, "GPLv3 License" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "رخصة GPLv3" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -8371,8 +8541,102 @@ } } }, + "License" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "رخصة" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lizenz" + } + }, + "en-GB" : { + "stringUnit" : { + "state" : "translated", + "value" : "Licence" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Licencia" + } + }, + "es-419" : { + "stringUnit" : { + "state" : "translated", + "value" : "Licencia" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Licence" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Licenza" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "ライセンス" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "사용권" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Licencja" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Licença" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Лицензия" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "许可证" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "許可證" + } + } + } + }, "LICENSES" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "تراخيص" + } + }, "de" : { "stringUnit" : { "state" : "translated", diff --git a/src/App/ViewModels/Settings/DataSettingsViewModel.swift b/src/App/ViewModels/Settings/DataSettingsViewModel.swift index f7ebc47..9f61fe3 100644 --- a/src/App/ViewModels/Settings/DataSettingsViewModel.swift +++ b/src/App/ViewModels/Settings/DataSettingsViewModel.swift @@ -18,6 +18,9 @@ final class DataSettingsViewModel: ObservableObject { app.sourceURL.absoluteString } + @Published + private(set) var currentDataSourceInformation: MHDataSourceInformation? + #if os(watchOS) @Published var isSourceURLChanged: Bool = false @@ -48,6 +51,10 @@ final class DataSettingsViewModel: ObservableObject { } self.app = app self.sourceURLString = Self.getSourceURLString(app) + + app.$dataSourceInformation + .receive(on: DispatchQueue.main) + .assign(to: &$currentDataSourceInformation) } // MARK: - Data Source diff --git a/src/App/Views/Settings/Data/DataSettingsPane.swift b/src/App/Views/Settings/Data/DataSettingsPane.swift index 90967d9..e89ac8f 100644 --- a/src/App/Views/Settings/Data/DataSettingsPane.swift +++ b/src/App/Views/Settings/Data/DataSettingsPane.swift @@ -95,6 +95,17 @@ struct DataSettingsPane: View { } if !isEditMode { + if let dataSourceInfo = viewModel.currentDataSourceInformation { + SettingsSection("Data Source Info") { + SettingsLabeledContent(LocalizedStringKey("Name"), value: dataSourceInfo.name) + SettingsLabeledContent(LocalizedStringKey("Copyright"), value: dataSourceInfo.copyright) + SettingsLabeledContent(LocalizedStringKey("License"), value: dataSourceInfo.license) + } +#if os(watchOS) + .listRowBackground(EmptyView()) +#endif + } + SettingsSection { ResetSettingsButton(viewModel: viewModel) ResetCacheButton(viewModel: viewModel) diff --git a/src/Core/DataSources/MockDataSource.swift b/src/Core/DataSources/MockDataSource.swift index a3fbb6d..2156269 100644 --- a/src/Core/DataSources/MockDataSource.swift +++ b/src/Core/DataSources/MockDataSource.swift @@ -1,7 +1,7 @@ import Foundation public struct MockDataSource { - static let config = MHConfig(version: 3, games: ["mockgame"], languages: ["en", "ja"]) + static let config = MHConfig(version: 3, games: ["mockgame"], languages: ["en", "ja"], source: nil) static let localizationEnglish = MHLocalization( games: [ diff --git a/src/Core/DataSources/Objects/MHConfig.swift b/src/Core/DataSources/Objects/MHConfig.swift index 6c10f56..e5eec9e 100644 --- a/src/Core/DataSources/Objects/MHConfig.swift +++ b/src/Core/DataSources/Objects/MHConfig.swift @@ -1,9 +1,16 @@ import Foundation +public struct MHDataSourceInformation: Codable, Sendable { + public let name: String + public let copyright: String + public let license: String +} + struct MHConfig: Codable, Sendable { let version: UInt8 let games: [String] let languages: [String] + let source: MHDataSourceInformation? static let currentVersion: UInt8 = 3 } diff --git a/src/Core/StarSwings/App.swift b/src/Core/StarSwings/App.swift index e5ca8f1..d5c46f9 100644 --- a/src/Core/StarSwings/App.swift +++ b/src/Core/StarSwings/App.swift @@ -23,6 +23,9 @@ public final class App: FetchableEntity<[Game]>, Entity { private var requireReinitApp: Bool = false + @Published + public private(set) var dataSourceInformation: MHDataSourceInformation? + public init(container: Container, requestBehavior: RepeatBehavior, pad: Bool) { @@ -135,6 +138,11 @@ public final class App: FetchableEntity<[Game]>, Entity { throw StarSwingsError.notSupported } + // Set data source information. + if let source = config.source { + self.dataSourceInformation = source + } + // Get localization. let preferredLocaleKey = LanguageUtil.getPreferredLanguageKey(config.languages) let localization = try await _dataSource.getLocalization(of: preferredLocaleKey)