From 8042164871d673c1dd4aaf834a7e4d51085fb455 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Bertholon Date: Thu, 30 Jan 2025 19:07:18 +0100 Subject: [PATCH 1/5] Remove default service url --- .../Resources/Apps/Play RSI/ApplicationConfiguration.json | 1 - .../Resources/Apps/Play RTR/ApplicationConfiguration.json | 1 - .../Resources/Apps/Play RTS/ApplicationConfiguration.json | 1 - .../Resources/Apps/Play SRF/ApplicationConfiguration.json | 1 - .../Resources/Apps/Play SWI/ApplicationConfiguration.json | 1 - 5 files changed, 5 deletions(-) diff --git a/Application/Resources/Apps/Play RSI/ApplicationConfiguration.json b/Application/Resources/Apps/Play RSI/ApplicationConfiguration.json index 0fdfc645b..de137b026 100755 --- a/Application/Resources/Apps/Play RSI/ApplicationConfiguration.json +++ b/Application/Resources/Apps/Play RSI/ApplicationConfiguration.json @@ -5,7 +5,6 @@ "tvSiteName": "rsi-player-tvos-apple", "voiceOverLanguageCode": "it", "appStoreProductIdentifier": 920753497, - "serviceURL": "https://il.srf.ch", "playURLs": "{\"rsi\":\"https://www.rsi.ch/play/\",\"rtr\":\"https://www.rtr.ch/play/\",\"rts\":\"https://www.rts.ch/play/\",\"srf\":\"https://www.srf.ch/play/\",\"swi\":\"https://play.swissinfo.ch/play/\"}", "playServiceURL": "https://www.rsi.ch/play/", "middlewareURL": "https://playfff.herokuapp.com", diff --git a/Application/Resources/Apps/Play RTR/ApplicationConfiguration.json b/Application/Resources/Apps/Play RTR/ApplicationConfiguration.json index 84863b498..5637b118e 100755 --- a/Application/Resources/Apps/Play RTR/ApplicationConfiguration.json +++ b/Application/Resources/Apps/Play RTR/ApplicationConfiguration.json @@ -4,7 +4,6 @@ "siteName": "rtr-player-ios-v", "tvSiteName": "rtr-player-tvos-apple", "appStoreProductIdentifier": 920754925, - "serviceURL": "https://il.srf.ch", "playURLs": "{\"rsi\":\"https://www.rsi.ch/play/\",\"rtr\":\"https://www.rtr.ch/play/\",\"rts\":\"https://www.rts.ch/play/\",\"srf\":\"https://www.srf.ch/play/\",\"swi\":\"https://play.swissinfo.ch/play/\"}", "playServiceURL": "https://www.rtr.ch/play/", "middlewareURL": "https://playfff.herokuapp.com", diff --git a/Application/Resources/Apps/Play RTS/ApplicationConfiguration.json b/Application/Resources/Apps/Play RTS/ApplicationConfiguration.json index 7c3964337..e9f68bb0f 100755 --- a/Application/Resources/Apps/Play RTS/ApplicationConfiguration.json +++ b/Application/Resources/Apps/Play RTS/ApplicationConfiguration.json @@ -5,7 +5,6 @@ "tvSiteName": "rts-player-tvos-apple", "voiceOverLanguageCode": "fr", "appStoreProductIdentifier": 920754415, - "serviceURL": "https://il.srf.ch", "playURLs": "{\"rsi\":\"https://www.rsi.ch/play/\",\"rtr\":\"https://www.rtr.ch/play/\",\"rts\":\"https://www.rts.ch/play/\",\"srf\":\"https://www.srf.ch/play/\",\"swi\":\"https://play.swissinfo.ch/play/\"}", "playServiceURL": "https://www.rts.ch/play/", "middlewareURL": "https://playfff.herokuapp.com", diff --git a/Application/Resources/Apps/Play SRF/ApplicationConfiguration.json b/Application/Resources/Apps/Play SRF/ApplicationConfiguration.json index 59be87314..099b90644 100755 --- a/Application/Resources/Apps/Play SRF/ApplicationConfiguration.json +++ b/Application/Resources/Apps/Play SRF/ApplicationConfiguration.json @@ -5,7 +5,6 @@ "tvSiteName": "srf-player-tvos-apple", "voiceOverLanguageCode": "de", "appStoreProductIdentifier": 638194352, - "serviceURL": "https://il.srf.ch", "playURLs": "{\"rsi\":\"https://www.rsi.ch/play/\",\"rtr\":\"https://www.rtr.ch/play/\",\"rts\":\"https://www.rts.ch/play/\",\"srf\":\"https://www.srf.ch/play/\",\"swi\":\"https://play.swissinfo.ch/play/\"}", "playServiceURL": "https://www.srf.ch/play/", "middlewareURL": "https://playfff.herokuapp.com", diff --git a/Application/Resources/Apps/Play SWI/ApplicationConfiguration.json b/Application/Resources/Apps/Play SWI/ApplicationConfiguration.json index 4338c212a..5612d9e11 100755 --- a/Application/Resources/Apps/Play SWI/ApplicationConfiguration.json +++ b/Application/Resources/Apps/Play SWI/ApplicationConfiguration.json @@ -5,7 +5,6 @@ "tvSiteName": "swi-player-tvos-apple", "voiceOverLanguageCode": "en", "appStoreProductIdentifier": 920785201, - "serviceURL": "https://il.srf.ch", "playURLs": "{\"rsi\":\"https://www.rsi.ch/play/\",\"rtr\":\"https://www.rtr.ch/play/\",\"rts\":\"https://www.rts.ch/play/\",\"srf\":\"https://www.srf.ch/play/\",\"swi\":\"https://play.swissinfo.ch/play/\"}", "playServiceURL": "https://play.swissinfo.ch/play/", "middlewareURL": "https://playfff.herokuapp.com", From 327d436362f8364e90d7f76f50a4e542707a1f73 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Bertholon Date: Thu, 30 Jan 2025 20:17:40 +0100 Subject: [PATCH 2/5] Add service urls in remote configurations --- .../Configuration/ApplicationConfiguration.h | 2 +- .../Configuration/ApplicationConfiguration.m | 10 +++++-- .../Configuration/PlayFirebaseConfiguration.h | 6 ++++ .../Configuration/PlayFirebaseConfiguration.m | 24 ++++++++++++++++ Application/Sources/Settings/Service.swift | 28 +++++++++++++------ docs/REMOTE_CONFIGURATION.md | 2 +- 6 files changed, 59 insertions(+), 13 deletions(-) diff --git a/Application/Sources/Configuration/ApplicationConfiguration.h b/Application/Sources/Configuration/ApplicationConfiguration.h index 41460af0d..7f84997c4 100755 --- a/Application/Sources/Configuration/ApplicationConfiguration.h +++ b/Application/Sources/Configuration/ApplicationConfiguration.h @@ -38,7 +38,6 @@ OBJC_EXPORT NSString * const ApplicationConfigurationDidChangeNotification; @property (nonatomic, readonly, copy) NSNumber *appStoreProductIdentifier; -@property (nonatomic, readonly, nullable) NSURL *serviceURL; @property (nonatomic, readonly) NSURL *playServiceURL; @property (nonatomic, readonly) NSURL *middlewareURL; @property (nonatomic, readonly, nullable) NSURL *identityWebserviceURL; @@ -114,6 +113,7 @@ OBJC_EXPORT NSString * const ApplicationConfigurationDidChangeNotification; - (nullable NSURL *)playURLForVendor:(SRGVendor)vendor; +- (nullable NSURL *)serviceURLForId:(NSString *)serviceId; /** * URLs to be used for sharing diff --git a/Application/Sources/Configuration/ApplicationConfiguration.m b/Application/Sources/Configuration/ApplicationConfiguration.m index 376923e79..7230c7b58 100755 --- a/Application/Sources/Configuration/ApplicationConfiguration.m +++ b/Application/Sources/Configuration/ApplicationConfiguration.m @@ -122,7 +122,7 @@ @interface ApplicationConfiguration () @property (nonatomic, copy) NSNumber *appStoreProductIdentifier; -@property (nonatomic) NSURL *serviceURL; +@property (nonatomic) NSDictionary *serviceURLs; @property (nonatomic) NSDictionary *playURLs; @property (nonatomic) NSURL *playServiceURL; @property (nonatomic) NSURL *middlewareURL; @@ -450,8 +450,7 @@ - (BOOL)synchronizeWithFirebaseConfiguration:(PlayFirebaseConfiguration *)fireba self.voiceOverLanguageCode = [firebaseConfiguration stringForKey:@"voiceOverLanguageCode"]; - NSString *serviceURLString = [firebaseConfiguration stringForKey:@"serviceURL"]; - self.serviceURL = serviceURLString ? [NSURL URLWithString:serviceURLString] : nil; + self.serviceURLs = [firebaseConfiguration serviceURLsForKey:@"serviceURLs"]; NSString *identityWebserviceURLString = [firebaseConfiguration stringForKey:@"identityWebserviceURL"]; self.identityWebserviceURL = identityWebserviceURLString ? [NSURL URLWithString:identityWebserviceURLString] : nil; @@ -613,6 +612,11 @@ - (NSURL *)playURLForVendor:(SRGVendor)vendor return playURLs[@(vendor)]; } +- (NSURL *)serviceURLForId:(NSString *)serviceId +{ + return self.serviceURLs[serviceId]; +} + - (NSURL *)sharingURLForMedia:(SRGMedia *)media atTime:(CMTime)time { if (! media || ! [self playURLForVendor:media.vendor]) { diff --git a/Application/Sources/Configuration/PlayFirebaseConfiguration.h b/Application/Sources/Configuration/PlayFirebaseConfiguration.h index 407c000d8..8a5d0f95b 100644 --- a/Application/Sources/Configuration/PlayFirebaseConfiguration.h +++ b/Application/Sources/Configuration/PlayFirebaseConfiguration.h @@ -72,6 +72,12 @@ OBJC_EXPORT NSArray * _Nullable FirebaseConfigurat */ - (NSDictionary *)playURLsForKey:(NSString *)key; +/** + * Service URLs accessor. Return an empty dictionnary if no valid data is found under the specified key. + */ +- (NSDictionary *)serviceURLsForKey:(NSString *)key; + + @end NS_ASSUME_NONNULL_END diff --git a/Application/Sources/Configuration/PlayFirebaseConfiguration.m b/Application/Sources/Configuration/PlayFirebaseConfiguration.m index 4e3b956ea..031b4ff28 100644 --- a/Application/Sources/Configuration/PlayFirebaseConfiguration.m +++ b/Application/Sources/Configuration/PlayFirebaseConfiguration.m @@ -7,6 +7,7 @@ #import "PlayFirebaseConfiguration.h" #import "PlayLogger.h" +#import "PlaySRG-Swift.h" @import Firebase; @import SRGAppearance; @@ -367,6 +368,29 @@ - (NSDictionary *)JSONDictionaryForKey:(NSString *)key return playURLs.copy; } +- (NSDictionary *)serviceURLsForKey:(NSString *)key +{ + NSMutableDictionary *serviceURLs = [NSMutableDictionary dictionary]; + + NSDictionary *serviceURLsDictionary = [self JSONDictionaryForKey:key]; + for (NSString *key in serviceURLsDictionary) { + if ([ServiceObjC.ids containsObject:key]) { + NSURL *URL = [NSURL URLWithString:serviceURLsDictionary[key]]; + if (URL) { + serviceURLs[key] = URL; + } + else { + PlayLogWarning(@"configuration", @"Service URL configuration is not valid. The URL of %@ is not valid.", key); + } + } + else { + PlayLogWarning(@"configuration", @"Service URL configuration identifier is not valid. %@ is not valid.", key); + } + } + + return serviceURLs.copy; +} + #pragma mark Update - (void)update diff --git a/Application/Sources/Settings/Service.swift b/Application/Sources/Settings/Service.swift index 7947a1d5f..950121142 100644 --- a/Application/Sources/Settings/Service.swift +++ b/Application/Sources/Settings/Service.swift @@ -12,26 +12,36 @@ struct Service: Identifiable, Equatable { let name: String let url: URL + private enum Id { + static let production = "production" + static let stage = "stage" + static let test = "test" + static let mmf = "play mmf" + static let samProduction = "sam production" + static let samStage = "sam stage" + static let samTest = "sam test" + } + static var production = Self( - id: "production", + id: Id.production, name: NSLocalizedString("Production", comment: "Server setting name"), url: SRGIntegrationLayerProductionServiceURL() ) static var stage = Self( - id: "stage", + id: Id.stage, name: NSLocalizedString("Stage", comment: "Server setting name"), url: SRGIntegrationLayerStagingServiceURL() ) static var test = Self( - id: "test", + id: Id.test, name: NSLocalizedString("Test", comment: "Server setting name"), url: SRGIntegrationLayerTestServiceURL() ) static var mmf = Self( - id: "play mmf", + id: Id.mmf, name: "Play MMF", url: mmfUrl ) @@ -46,19 +56,19 @@ struct Service: Identifiable, Equatable { }() static var samProduction = Self( - id: "sam production", + id: Id.samProduction, name: "SAM \(NSLocalizedString("Production", comment: "Server setting name"))", url: SRGIntegrationLayerProductionServiceURL().appendingPathComponent("sam") ) static var samStage = Self( - id: "sam stage", + id: Id.samStage, name: "SAM \(NSLocalizedString("Stage", comment: "Server setting name"))", url: SRGIntegrationLayerStagingServiceURL().appendingPathComponent("sam") ) static var samTest = Self( - id: "sam test", + id: Id.samTest, name: "SAM \(NSLocalizedString("Test", comment: "Server setting name"))", url: SRGIntegrationLayerTestServiceURL().appendingPathComponent("sam") ) @@ -78,11 +88,13 @@ struct Service: Identifiable, Equatable { } @objc class ServiceObjC: NSObject { + @objc static var ids = Service.services.map(\.id) + @objc static func name(forServiceId serviceId: String) -> String { Service.service(forId: serviceId).name } @objc static func url(forServiceId serviceId: String) -> URL { - ApplicationConfiguration().serviceURL ?? Service.service(forId: serviceId).url + ApplicationConfiguration().serviceURL(forId: serviceId) ?? Service.service(forId: serviceId).url } } diff --git a/docs/REMOTE_CONFIGURATION.md b/docs/REMOTE_CONFIGURATION.md index 3d7f7ca91..6b454c8a3 100755 --- a/docs/REMOTE_CONFIGURATION.md +++ b/docs/REMOTE_CONFIGURATION.md @@ -26,7 +26,7 @@ If a remote configuration is found to be invalid (usually a mandatory parameter * `faqURL` (optional, string): The URL of the FAQs. * `dataProtectionURL` (optional, string): The URL of the data protection information page. * `impressumURL` (optional, string): The URL of the impressum page. If none is provided, the corresponding menu entry will not be displayed. -* `serviceURL` (optional, string): The URL of the Content service (DataProvider). If set, it overrides the local server option available in beta builds only. +* `serviceURLs` (optional, JSON): A JSON dictionary describing all URLs of the DataProvider services. Key (string) is the identifier of the service, value (string) is the base URL of the DataProvider service. If the key matches a service id, it overrides the default URL for this service. See `Service.swift` for available ids. * `identityWebserviceURL` (optional, string): The URL of the identity webservices. * `identityWebsiteURL` (optional, string): The URL of the identity web portal. * `userDataServiceURL` (optional, string): The URL of the service with which user data can be synchronized (history, preferences, playlists). From aa324f53c841962a80462bc6811301d79f7043ae Mon Sep 17 00:00:00 2001 From: Pierre-Yves Bertholon Date: Fri, 31 Jan 2025 23:50:57 +0100 Subject: [PATCH 3/5] Fix type issue --- Application/Sources/Configuration/PlayFirebaseConfiguration.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/Sources/Configuration/PlayFirebaseConfiguration.m b/Application/Sources/Configuration/PlayFirebaseConfiguration.m index 031b4ff28..73ce6274f 100644 --- a/Application/Sources/Configuration/PlayFirebaseConfiguration.m +++ b/Application/Sources/Configuration/PlayFirebaseConfiguration.m @@ -370,7 +370,7 @@ - (NSDictionary *)JSONDictionaryForKey:(NSString *)key - (NSDictionary *)serviceURLsForKey:(NSString *)key { - NSMutableDictionary *serviceURLs = [NSMutableDictionary dictionary]; + NSMutableDictionary *serviceURLs = [NSMutableDictionary dictionary]; NSDictionary *serviceURLsDictionary = [self JSONDictionaryForKey:key]; for (NSString *key in serviceURLsDictionary) { From 12559c3048d9ff9959aef0756261c7b868afa798 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Bertholon Date: Fri, 31 Jan 2025 23:52:28 +0100 Subject: [PATCH 4/5] Renaming --- Application/Sources/Settings/Service.swift | 16 ++++++++-------- docs/REMOTE_CONFIGURATION.md | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Application/Sources/Settings/Service.swift b/Application/Sources/Settings/Service.swift index 950121142..8ab8d6e11 100644 --- a/Application/Sources/Settings/Service.swift +++ b/Application/Sources/Settings/Service.swift @@ -12,7 +12,7 @@ struct Service: Identifiable, Equatable { let name: String let url: URL - private enum Id { + private enum Environment { static let production = "production" static let stage = "stage" static let test = "test" @@ -23,25 +23,25 @@ struct Service: Identifiable, Equatable { } static var production = Self( - id: Id.production, + id: Environment.production, name: NSLocalizedString("Production", comment: "Server setting name"), url: SRGIntegrationLayerProductionServiceURL() ) static var stage = Self( - id: Id.stage, + id: Environment.stage, name: NSLocalizedString("Stage", comment: "Server setting name"), url: SRGIntegrationLayerStagingServiceURL() ) static var test = Self( - id: Id.test, + id: Environment.test, name: NSLocalizedString("Test", comment: "Server setting name"), url: SRGIntegrationLayerTestServiceURL() ) static var mmf = Self( - id: Id.mmf, + id: Environment.mmf, name: "Play MMF", url: mmfUrl ) @@ -56,19 +56,19 @@ struct Service: Identifiable, Equatable { }() static var samProduction = Self( - id: Id.samProduction, + id: Environment.samProduction, name: "SAM \(NSLocalizedString("Production", comment: "Server setting name"))", url: SRGIntegrationLayerProductionServiceURL().appendingPathComponent("sam") ) static var samStage = Self( - id: Id.samStage, + id: Environment.samStage, name: "SAM \(NSLocalizedString("Stage", comment: "Server setting name"))", url: SRGIntegrationLayerStagingServiceURL().appendingPathComponent("sam") ) static var samTest = Self( - id: Id.samTest, + id: Environment.samTest, name: "SAM \(NSLocalizedString("Test", comment: "Server setting name"))", url: SRGIntegrationLayerTestServiceURL().appendingPathComponent("sam") ) diff --git a/docs/REMOTE_CONFIGURATION.md b/docs/REMOTE_CONFIGURATION.md index 6b454c8a3..d419b2296 100755 --- a/docs/REMOTE_CONFIGURATION.md +++ b/docs/REMOTE_CONFIGURATION.md @@ -26,7 +26,7 @@ If a remote configuration is found to be invalid (usually a mandatory parameter * `faqURL` (optional, string): The URL of the FAQs. * `dataProtectionURL` (optional, string): The URL of the data protection information page. * `impressumURL` (optional, string): The URL of the impressum page. If none is provided, the corresponding menu entry will not be displayed. -* `serviceURLs` (optional, JSON): A JSON dictionary describing all URLs of the DataProvider services. Key (string) is the identifier of the service, value (string) is the base URL of the DataProvider service. If the key matches a service id, it overrides the default URL for this service. See `Service.swift` for available ids. +* `serviceURLs` (optional, JSON): A JSON dictionary describing all URLs of the DataProvider services. Key (string) is the environment identifier of the service, value (string) is the base URL of the DataProvider service. If the key matches a service environment identifier, it overrides the default URL for this service. See `Service.Environment` in `Service.swift` for available identifiers. * `identityWebserviceURL` (optional, string): The URL of the identity webservices. * `identityWebsiteURL` (optional, string): The URL of the identity web portal. * `userDataServiceURL` (optional, string): The URL of the service with which user data can be synchronized (history, preferences, playlists). From 06ec8dbb22ba327ae3e314b8556f1432371a50df Mon Sep 17 00:00:00 2001 From: Pierre-Yves Bertholon Date: Tue, 4 Feb 2025 16:19:08 +0100 Subject: [PATCH 5/5] Switch to service enum Co-authored-by: Walid Kayhal <3347810+waliid@users.noreply.github.com> --- .../Sources/Application/SceneDelegate.m | 2 +- .../Configuration/PlayFirebaseConfiguration.m | 2 +- .../Settings/ApplicationSettings+Common.m | 2 +- Application/Sources/Settings/Service.swift | 126 +++++++++--------- .../Sources/Settings/SettingsView.swift | 14 +- Scripts/check-quality.sh | 3 +- docs/REMOTE_CONFIGURATION.md | 2 +- 7 files changed, 72 insertions(+), 79 deletions(-) diff --git a/Application/Sources/Application/SceneDelegate.m b/Application/Sources/Application/SceneDelegate.m index e0590a6c5..45db2115e 100644 --- a/Application/Sources/Application/SceneDelegate.m +++ b/Application/Sources/Application/SceneDelegate.m @@ -110,7 +110,7 @@ - (void)handleDeepLinkAction:(DeepLinkAction *)action if (! [serviceIdentifier isEqual:ApplicationSettingServiceIdentifier()]) { ApplicationSettingSetServiceIdentifier(serviceIdentifier); - NSString *serviceName = [ServiceObjC nameForServiceId:serviceIdentifier]; + NSString *serviceName = [ServiceObjC nameFor:serviceIdentifier]; [Banner showWith:BannerStyleInfo message:[NSString stringWithFormat:NSLocalizedString(@"Server changed to '%@'", @"Notification message when the server URL changed due to a custom URL."), serviceName] image:[UIImage imageNamed:@"settings"] diff --git a/Application/Sources/Configuration/PlayFirebaseConfiguration.m b/Application/Sources/Configuration/PlayFirebaseConfiguration.m index 73ce6274f..5889f632b 100644 --- a/Application/Sources/Configuration/PlayFirebaseConfiguration.m +++ b/Application/Sources/Configuration/PlayFirebaseConfiguration.m @@ -374,7 +374,7 @@ - (NSDictionary *)JSONDictionaryForKey:(NSString *)key NSDictionary *serviceURLsDictionary = [self JSONDictionaryForKey:key]; for (NSString *key in serviceURLsDictionary) { - if ([ServiceObjC.ids containsObject:key]) { + if ([ServiceObjC.environments containsObject:key]) { NSURL *URL = [NSURL URLWithString:serviceURLsDictionary[key]]; if (URL) { serviceURLs[key] = URL; diff --git a/Application/Sources/Settings/ApplicationSettings+Common.m b/Application/Sources/Settings/ApplicationSettings+Common.m index a626b478d..50a0f3e3a 100755 --- a/Application/Sources/Settings/ApplicationSettings+Common.m +++ b/Application/Sources/Settings/ApplicationSettings+Common.m @@ -209,7 +209,7 @@ void ApplicationSettingSetServiceIdentifier(NSString *identifier) NSURL *ApplicationSettingServiceURL(void) { - return [ServiceObjC urlForServiceId:ApplicationSettingServiceIdentifier()]; + return [ServiceObjC urlFor:ApplicationSettingServiceIdentifier()]; } BOOL ApplicationSettingAutoplayEnabled(void) diff --git a/Application/Sources/Settings/Service.swift b/Application/Sources/Settings/Service.swift index 8ab8d6e11..4aba2fd47 100644 --- a/Application/Sources/Settings/Service.swift +++ b/Application/Sources/Settings/Service.swift @@ -7,80 +7,76 @@ import Foundation import SRGDataProvider -struct Service: Identifiable, Equatable { - let id: String - let name: String - let url: URL - - private enum Environment { - static let production = "production" - static let stage = "stage" - static let test = "test" - static let mmf = "play mmf" - static let samProduction = "sam production" - static let samStage = "sam stage" - static let samTest = "sam test" - } - - static var production = Self( - id: Environment.production, - name: NSLocalizedString("Production", comment: "Server setting name"), - url: SRGIntegrationLayerProductionServiceURL() - ) - - static var stage = Self( - id: Environment.stage, - name: NSLocalizedString("Stage", comment: "Server setting name"), - url: SRGIntegrationLayerStagingServiceURL() - ) - - static var test = Self( - id: Environment.test, - name: NSLocalizedString("Test", comment: "Server setting name"), - url: SRGIntegrationLayerTestServiceURL() - ) - - static var mmf = Self( - id: Environment.mmf, - name: "Play MMF", - url: mmfUrl - ) - - private static var mmfUrl: URL = { +enum Service: String, Identifiable, CaseIterable { + case production + case stage + case test + case mmf = "play mmf" + case samProduction = "sam production" + case samStage = "sam stage" + case samTest = "sam test" + + private static var mmfUrl: URL { guard let mmfUrlString = Bundle.main.object(forInfoDictionaryKey: "PlayMMFServiceURL") as? String, !mmfUrlString.isEmpty else { return URL(string: "https://play-mmf.herokuapp.com")! } return URL(string: mmfUrlString)! - }() + } - static var samProduction = Self( - id: Environment.samProduction, - name: "SAM \(NSLocalizedString("Production", comment: "Server setting name"))", - url: SRGIntegrationLayerProductionServiceURL().appendingPathComponent("sam") - ) + var id: Self { + self + } - static var samStage = Self( - id: Environment.samStage, - name: "SAM \(NSLocalizedString("Stage", comment: "Server setting name"))", - url: SRGIntegrationLayerStagingServiceURL().appendingPathComponent("sam") - ) + var environment: String { + rawValue + } - static var samTest = Self( - id: Environment.samTest, - name: "SAM \(NSLocalizedString("Test", comment: "Server setting name"))", - url: SRGIntegrationLayerTestServiceURL().appendingPathComponent("sam") - ) + var name: String { + switch self { + case .production: + NSLocalizedString("Production", comment: "Server setting name") + case .stage: + NSLocalizedString("Stage", comment: "Server setting name") + case .test: + NSLocalizedString("Test", comment: "Server setting name") + case .mmf: + "Play MMF" + case .samProduction: + "SAM \(NSLocalizedString("Production", comment: "Server setting name"))" + case .samStage: + "SAM \(NSLocalizedString("Stage", comment: "Server setting name"))" + case .samTest: + "SAM \(NSLocalizedString("Test", comment: "Server setting name"))" + } + } - static var services: [Self] = [production, stage, test, mmf, samProduction, samStage, samTest] + var url: URL { + switch self { + case .production: + SRGIntegrationLayerProductionServiceURL() + case .stage: + SRGIntegrationLayerStagingServiceURL() + case .test: + SRGIntegrationLayerTestServiceURL() + case .mmf: + Self.mmfUrl + case .samProduction: + SRGIntegrationLayerProductionServiceURL().appendingPathComponent("sam") + case .samStage: + SRGIntegrationLayerStagingServiceURL().appendingPathComponent("sam") + case .samTest: + SRGIntegrationLayerTestServiceURL().appendingPathComponent("sam") + } + } - static func service(forId id: String?) -> Self { + static func service(for environment: String?) -> Self { #if DEBUG || NIGHTLY || BETA - guard let id, let server = services.first(where: { $0.id == id }) else { + guard let environment, let service = Self(rawValue: environment) else { return .production } - return server + return service #else return .production #endif @@ -88,13 +84,13 @@ struct Service: Identifiable, Equatable { } @objc class ServiceObjC: NSObject { - @objc static var ids = Service.services.map(\.id) + @objc static var environments = Service.allCases.map(\.environment) - @objc static func name(forServiceId serviceId: String) -> String { - Service.service(forId: serviceId).name + @objc static func name(for environment: String) -> String { + Service.service(for: environment).name } - @objc static func url(forServiceId serviceId: String) -> URL { - ApplicationConfiguration().serviceURL(forId: serviceId) ?? Service.service(forId: serviceId).url + @objc static func url(for environment: String) -> URL { + ApplicationConfiguration().serviceURL(forId: environment) ?? Service.service(for: environment).url } } diff --git a/Application/Sources/Settings/SettingsView.swift b/Application/Sources/Settings/SettingsView.swift index 1a5f2e61a..0e0dbba34 100644 --- a/Application/Sources/Settings/SettingsView.swift +++ b/Application/Sources/Settings/SettingsView.swift @@ -565,7 +565,7 @@ struct SettingsView: View { @AppStorage(PlaySRGSettingServiceIdentifier) private var selectedServiceId: String? private var selectedService: Service { - Service.service(forId: selectedServiceId) + Service.service(for: selectedServiceId) } var body: some View { @@ -643,7 +643,7 @@ struct SettingsView: View { private struct ServiceSelectionView: View { var body: some View { List { - ForEach(Service.services) { service in + ForEach(Service.allCases) { service in ServiceCell(service: service) } } @@ -660,7 +660,7 @@ struct SettingsView: View { private struct ServiceCell: View { let service: Service - @AppStorage(PlaySRGSettingServiceIdentifier) var selectedServiceId: String? + @AppStorage(PlaySRGSettingServiceIdentifier) var selectedServiceIdentifier: String? var body: some View { Button(action: select) { @@ -676,15 +676,11 @@ struct SettingsView: View { } private func isSelected() -> Bool { - if let selectedServiceId { - service.id == selectedServiceId - } else { - service == .production - } + service == Service.service(for: selectedServiceIdentifier) } private func select() { - selectedServiceId = service.id + selectedServiceIdentifier = service.rawValue } } diff --git a/Scripts/check-quality.sh b/Scripts/check-quality.sh index db6d49012..b7e50f3fb 100755 --- a/Scripts/check-quality.sh +++ b/Scripts/check-quality.sh @@ -2,12 +2,13 @@ set -e -echo "... checking Swift code..." +echo "... checking Swift code with SwiftLint..." if [ $# -eq 0 ]; then swiftlint --quiet --strict elif [[ "$1" == "only-changes" ]]; then git diff --staged --name-only | grep ".swift$" | xargs -I FILE swiftlint lint --quiet --strict "FILE" fi +echo "... checking Swift code with SwiftFormat..." if [ $# -eq 0 ]; then swiftformat --lint --quiet . elif [[ "$1" == "only-changes" ]]; then diff --git a/docs/REMOTE_CONFIGURATION.md b/docs/REMOTE_CONFIGURATION.md index d419b2296..aaf756095 100755 --- a/docs/REMOTE_CONFIGURATION.md +++ b/docs/REMOTE_CONFIGURATION.md @@ -26,7 +26,7 @@ If a remote configuration is found to be invalid (usually a mandatory parameter * `faqURL` (optional, string): The URL of the FAQs. * `dataProtectionURL` (optional, string): The URL of the data protection information page. * `impressumURL` (optional, string): The URL of the impressum page. If none is provided, the corresponding menu entry will not be displayed. -* `serviceURLs` (optional, JSON): A JSON dictionary describing all URLs of the DataProvider services. Key (string) is the environment identifier of the service, value (string) is the base URL of the DataProvider service. If the key matches a service environment identifier, it overrides the default URL for this service. See `Service.Environment` in `Service.swift` for available identifiers. +* `serviceURLs` (optional, JSON): A JSON dictionary describing all URLs of the DataProvider services. Key (string) is the environment identifier of the service, value (string) is the base URL of the DataProvider service. If the key matches a service environment identifier, it overrides the default URL for this service. See `Service.swift` enum raw values for available environment identifiers. * `identityWebserviceURL` (optional, string): The URL of the identity webservices. * `identityWebsiteURL` (optional, string): The URL of the identity web portal. * `userDataServiceURL` (optional, string): The URL of the service with which user data can be synchronized (history, preferences, playlists).