diff --git a/Application/Resources/Apps/Play RSI/ApplicationConfiguration.json b/Application/Resources/Apps/Play RSI/ApplicationConfiguration.json
index 2436687d9..694206b61 100755
--- a/Application/Resources/Apps/Play RSI/ApplicationConfiguration.json
+++ b/Application/Resources/Apps/Play RSI/ApplicationConfiguration.json
@@ -1,6 +1,6 @@
{
"businessUnit": "rsi",
- "container": 10,
+ "sourceKey": "1b30366c-9e8d-4720-8b12-4165f468f9ae",
"siteName": "rsi-player-ios-v",
"tvSiteName": "rsi-player-tvos-apple",
"voiceOverLanguageCode": "it",
diff --git a/Application/Resources/Apps/Play RTR/ApplicationConfiguration.json b/Application/Resources/Apps/Play RTR/ApplicationConfiguration.json
index 375bae290..7ff72d13a 100755
--- a/Application/Resources/Apps/Play RTR/ApplicationConfiguration.json
+++ b/Application/Resources/Apps/Play RTR/ApplicationConfiguration.json
@@ -1,6 +1,6 @@
{
"businessUnit": "rtr",
- "container": 10,
+ "sourceKey": "1b30366c-9e8d-4720-8b12-4165f468f9ae",
"siteName": "rtr-player-ios-v",
"tvSiteName": "rtr-player-tvos-apple",
"appStoreProductIdentifier": 920754925,
diff --git a/Application/Resources/Apps/Play RTS/ApplicationConfiguration.json b/Application/Resources/Apps/Play RTS/ApplicationConfiguration.json
index bf0f3f97f..f1c14838d 100755
--- a/Application/Resources/Apps/Play RTS/ApplicationConfiguration.json
+++ b/Application/Resources/Apps/Play RTS/ApplicationConfiguration.json
@@ -1,6 +1,6 @@
{
"businessUnit": "rts",
- "container": 10,
+ "sourceKey": "1b30366c-9e8d-4720-8b12-4165f468f9ae",
"siteName": "rts-player-ios-v",
"tvSiteName": "rts-player-tvos-apple",
"voiceOverLanguageCode": "fr",
diff --git a/Application/Resources/Apps/Play SRF/ApplicationConfiguration.json b/Application/Resources/Apps/Play SRF/ApplicationConfiguration.json
index 36e70b518..634c95379 100755
--- a/Application/Resources/Apps/Play SRF/ApplicationConfiguration.json
+++ b/Application/Resources/Apps/Play SRF/ApplicationConfiguration.json
@@ -1,6 +1,6 @@
{
"businessUnit": "srf",
- "container": 10,
+ "sourceKey": "1b30366c-9e8d-4720-8b12-4165f468f9ae",
"siteName": "srf-player-ios-v",
"tvSiteName": "srf-player-tvos-apple",
"voiceOverLanguageCode": "de",
diff --git a/Application/Resources/Apps/Play SWI/ApplicationConfiguration.json b/Application/Resources/Apps/Play SWI/ApplicationConfiguration.json
index 702a9473f..a0966fabc 100755
--- a/Application/Resources/Apps/Play SWI/ApplicationConfiguration.json
+++ b/Application/Resources/Apps/Play SWI/ApplicationConfiguration.json
@@ -1,6 +1,6 @@
{
"businessUnit": "swi",
- "container": 10,
+ "sourceKey": "1b30366c-9e8d-4720-8b12-4165f468f9ae",
"siteName": "swi-player-ios-v",
"tvSiteName": "swi-player-tvos-apple",
"voiceOverLanguageCode": "en",
diff --git a/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.latest_result.txt b/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.latest_result.txt
index 5b8da932a..68bc4de35 100755
--- a/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.latest_result.txt
+++ b/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.latest_result.txt
@@ -109,7 +109,7 @@ name: Aiolos, nameSpecified: Aiolos, owner: IdeasOnCanvas, version: 1.9.7, sourc
name: appcenter-sdk-apple, nameSpecified: AppCenter, owner: microsoft, version: 5.0.4, source: https://github.com/microsoft/appcenter-sdk-apple
-name: Comscore-Swift-Package-Manager, nameSpecified: Comscore-Swift-Package-Manager, owner: comScore, version: 6.10.2, source: https://github.com/comScore/Comscore-Swift-Package-Manager
+name: Comscore-Swift-Package-Manager, nameSpecified: Comscore-Swift-Package-Manager, owner: comScore, version: 6.11.0, source: https://github.com/comScore/Comscore-Swift-Package-Manager
name: DZNEmptyDataSet, nameSpecified: DZNEmptyDataSet, owner: dzenbot, version: , source: https://github.com/dzenbot/DZNEmptyDataSet
@@ -137,6 +137,8 @@ name: interop-ios-for-google-sdks, nameSpecified: InteropForGoogle, owner: googl
name: ios-library, nameSpecified: Airship, owner: urbanairship, version: 16.12.4, source: https://github.com/urbanairship/ios-library
+name: iOSV5, nameSpecified: TagCommander SDK V5, owner: CommandersAct, version: 5.4.2, source: https://github.com/CommandersAct/iOSV5
+
name: leveldb, nameSpecified: leveldb, owner: firebase, version: 1.22.2, source: https://github.com/firebase/leveldb
name: libextobjc, nameSpecified: libextobjc, owner: SRGSSR, version: 0.6.0-srg4, source: https://github.com/SRGSSR/libextobjc
@@ -157,7 +159,7 @@ name: PLCrashReporter, nameSpecified: PLCrashReporter, owner: microsoft, version
name: promises, nameSpecified: Promises, owner: google, version: 2.3.1, source: https://github.com/google/promises
-name: srganalytics-apple, nameSpecified: SRGAnalytics, owner: SRGSSR, version: 8.2.0, source: https://github.com/SRGSSR/srganalytics-apple
+name: srganalytics-apple, nameSpecified: SRGAnalytics, owner: SRGSSR, version: 9.0.1, source: https://github.com/SRGSSR/srganalytics-apple
name: srgappearance-apple, nameSpecified: SRGAppearance, owner: SRGSSR, version: 5.2.1, source: https://github.com/SRGSSR/srgappearance-apple
@@ -169,7 +171,7 @@ name: srgdiagnostics-apple, nameSpecified: SRGDiagnostics, owner: SRGSSR, versio
name: srgidentity-apple, nameSpecified: SRGIdentity, owner: SRGSSR, version: 3.3.0, source: https://github.com/SRGSSR/srgidentity-apple
-name: srgletterbox-apple, nameSpecified: SRGLetterbox, owner: SRGSSR, version: 9.1.2, source: https://github.com/SRGSSR/srgletterbox-apple
+name: srgletterbox-apple, nameSpecified: SRGLetterbox, owner: SRGSSR, version: 9.2.1, source: https://github.com/SRGSSR/srgletterbox-apple
name: srglogger-apple, nameSpecified: SRGLogger, owner: SRGSSR, version: 3.1.0, source: https://github.com/SRGSSR/srglogger-apple
@@ -187,10 +189,6 @@ name: SwiftMessages, nameSpecified: SwiftMessages, owner: SwiftKickMobile, versi
name: SwiftUI-Introspect, nameSpecified: Introspect, owner: siteline, version: 0.12.0, source: https://github.com/siteline/SwiftUI-Introspect
-name: TCCore-xcframework-apple, nameSpecified: TCCore, owner: SRGSSR, version: 4.5.4-srg5, source: https://github.com/SRGSSR/TCCore-xcframework-apple
-
-name: TCSDK-xcframework-apple, nameSpecified: TCSDK, owner: SRGSSR, version: 4.4.1-srg5, source: https://github.com/SRGSSR/TCSDK-xcframework-apple
-
name: UICKeyChainStore, nameSpecified: UICKeyChainStore, owner: kishikawakatsumi, version: 2.2.1, source: https://github.com/kishikawakatsumi/UICKeyChainStore
name: YYWebImage, nameSpecified: YYWebImage, owner: SRGSSR, version: 1.0.5-srg3, source: https://github.com/SRGSSR/YYWebImage
diff --git a/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.plist b/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.plist
index a41938e65..e6b7ff4b0 100755
--- a/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.plist
+++ b/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.plist
@@ -46,7 +46,7 @@
File
com.mono0926.LicensePlist/Comscore-Swift-Package-Manager
Title
- Comscore-Swift-Package-Manager (6.10.2)
+ Comscore-Swift-Package-Manager (6.11.0)
Type
PSChildPaneSpecifier
@@ -154,6 +154,14 @@
Type
PSChildPaneSpecifier
+
+ File
+ com.mono0926.LicensePlist/iOSV5
+ Title
+ TagCommander SDK V5 (5.4.2)
+ Type
+ PSChildPaneSpecifier
+
File
com.mono0926.LicensePlist/leveldb
@@ -262,7 +270,7 @@
File
com.mono0926.LicensePlist/srganalytics-apple
Title
- SRGAnalytics (8.2.0)
+ SRGAnalytics (9.0.1)
Type
PSChildPaneSpecifier
@@ -310,7 +318,7 @@
File
com.mono0926.LicensePlist/srgletterbox-apple
Title
- SRGLetterbox (9.1.2)
+ SRGLetterbox (9.2.1)
Type
PSChildPaneSpecifier
diff --git a/Application/Resources/Settings.bundle/com.mono0926.LicensePlist/iOSV5.plist b/Application/Resources/Settings.bundle/com.mono0926.LicensePlist/iOSV5.plist
new file mode 100644
index 000000000..e12b5e632
--- /dev/null
+++ b/Application/Resources/Settings.bundle/com.mono0926.LicensePlist/iOSV5.plist
@@ -0,0 +1,131 @@
+
+
+
+
+ PreferenceSpecifiers
+
+
+ FooterText
+ **SDK Licence Agreement FOR** **COMMANDERS' CLIENTS**
+
+PLEASE READ CAREFULLY THE TERMS OF THIS SDK LICENSE AGREEMENT ("AGREEMENT") BEFORE INSTALLING OUR SDK.
+
+**IMPORTANT**
+
+**THIS SKD CAN ONLY BE INSTALLED AND USED BY COMMANDERS ACT' CLIENTS IN CONNECTION WITH OUR PRODUCTS.**
+
+**IF YOU ARE NOT A COMMANDERS' ACT CLIENTS AND DECIDE TO INSTALL AND USE OUR SDK, WE SHALL NOT LIABLE FOR ANY CONSEQUENCE RESULTING FROM THE INSTALLATION AND/OR THE USE OF** **OUR SDK and you are likely to be subject to prosecution for unauthorized use of our SDK**.
+
+BY INSTALLING, ACCESSING AND/OR USING OUR SDK, YOU EXPRESSLY ACKNOWLEDGE AND AGREE THAT YOU, OR THE COMPANY YOU REPRESENT, ("YOU" OR "LICENSEE") ARE ENTERING INTO A LEGAL AGREEMENT WITH COMMANDERS ACT, AND HAVE UNDERSTOOD AND AGREE TO COMPLY WITH, AND BE LEGALLY BOUND BY, THE TERMS AND CONDITIONS OF THIS AGREEMENT.
+
+- - - -
+
+1. **Definitions.**
+
+- -- **Documentation** means the user's guides and technical manuals delivered by COMMANDERS ACT to Licensee.
+- -- **Intellectual Property Rights** means all intangible legal rights, titles and interests evidenced by or embodied in SDK.
+- -- **License** means the right to use SDK pursuant to this Agreement.
+- -- **Products** means any product, service, platform provided by COMMANDERS ACT.
+- -- **SDK** means SDK Development Kit created by COMMANDERS ACT in connection with its Products including any updates and upgrade thereto (to the extent delivered) **.**
+
+1. **Term and Termination.**
+
+This Agreement shall continue as long as You have a subscription to a Product compatible with the SDK (the "Term").
+
+In the event of termination of Your subscription to a Product compatible with the SDK, this Agreement will be automatically terminated provided that You have removed the SDK from Your system and destroyed all copies of the SDK and Documentation.
+
+Unauthorized copying of the SDK or otherwise failing to comply with this Agreement will result in automatic immediate termination of this Agreement and will make available to COMMANDERS ACT legal remedies.
+
+COMMANDERS ACT reserves the right to terminate this Agreement and the License at any time and without notice.
+
+Upon termination of this Agreement, the License will terminate and You: (i) will cease any and all rights to use the SDK, and (ii) will remove the SDK from all hard drives, networks and other storage media and destroy all copies of the SDK in your possession or under your control.
+
+The provisions above shall survive the termination, expiration or other ending of this Agreement.
+
+1. **License scope**
+
+Subject to the terms and conditions of this Agreement, COMMANDERS ACT grants You, during the Term, a personal, non-exclusive, non-sublicensable, non-transferable, revocable license to: (i) use the SDK solely in connection with COMMANDERS ACT's PRODUCTS.
+
+COMMANDERS ACT shall make available Documentation to be used solely in connection with Licensee's use of the SDK during the Term of this Agreement.
+
+Licensee may print or copy the Documentation as needed for its own purposes provided that all copyright notices are included therein.
+
+Documentation shall be considered as confidential information of COMMANDERS ACT.
+
+Licensee shall have no other rights, express or implied, in the SDK, other than the rights explicitly granted in this Agreement.
+
+Without limiting the generality of the foregoing, Licensee agrees and undertakes not to: (i) allow any third party to use the SDK in any manner, including but not limited to, sell, lease, sublicense or distribute the SDK, or any part thereof; (ii) modify, revise, or alter the SDK or reverse engineer, decompile, disassemble or otherwise reduce to human-perceivable form the SDK's source code; (iii) copy or allow copies of the SDK to be made; (iv) remove, alter or obscure any proprietary notice or identification, contained in or displayed on or via the SDK; (v) use the SDK to violate any applicable laws, rules or regulations, or for any unlawful, harmful, irresponsible, or inappropriate purpose, or in any manner that breaches this Agreement, and/or (vi) represent that it possesses any proprietary interest in the SDK.
+
+1. **Open Source Licenses**
+
+The SDK may include certain open source code and materials (as shall be listed in the documentation of the SDK) ("Open Source Code") that are subject to their respective open source licenses ("Open Source Licenses").
+
+Such Open Source Licenses contain a list of conditions with respect to warranty, copyright policy and other provisions.
+
+By executing this Agreement, Licensee undertakes to strictly comply with the terms and condition of the Open Source Licenses, as may be amended from time to time.
+
+In order to comply with the Open Source Licenses, Licensee shall read the respective licenses or notices, such list of Open Source Licenses may be amended from time to time by COMMANDERS ACT, at its sole discretion.
+
+In the event of any inconsistencies or conflicting provisions between the provisions of the Open Source Licenses and the provisions of this Agreement, the provisions of the Open Source Licenses shall prevail.
+
+Without derogating from the generality of the foregoing, it is clarified that any Open Source Code is provided on an "AS IS" basis, without indemnity or warranty of any kind, whether express or implied.
+
+For clarity, the representations and warranties set forth in this Agreement shall not apply to any Open Source Code.
+
+1. **Ownership**
+
+COMMANDERS ACT DOES NOT SELL OR TRANSFER ANY TITLE IN THE SDK, OR ANY PART THEREOF, TO LICENSEE. T
+
+Documentation, SDK (excluding any Open Source Code) shall remain COMMANDERS ACT' sole and exclusive property.
+
+All Intellectual Property Rights evidenced by or embodied in and/or related to the SDK, or part thereof, are and shall be owned solely and exclusively by COMMANDERS ACT.
+
+Nothing in this Agreement shall constitute a waiver of COMMANDERS ACT' Intellectual Property Rights or be in any way construed or interpreted as such.
+
+It is further agreed that Licensee acknowledges that any and all rights, including Intellectual Property Rights in any evolution shall belong exclusively to COMMANDERS ACT.
+
+1. **Warranty**
+
+COMMANDERS ACT warrants that it has the right to grant the license under this Agreement. COMMANDERS ACT' sole liability for any breach of this warranty or any other warranty under this Agreement shall be, at COMMANDERS ACT' sole discretion: (i) to replace or repair the SDK or the applicable portion thereof; or (ii) to terminate this Agreement.
+
+The warranties set forth above are contingent upon Licensee's proper use of the SDK, and shall not apply to damage caused by abuse, misuse, alteration, neglect or unauthorized repair or installation, or by the use or attempted use of SDK other than that supplied and supported by COMMANDERS ACT.
+
+COMMANDERS ACT will use reasonable commercial efforts to repair or replace the SDK or the applicable portion thereof, as soon as possible.
+
+1. **Indemnification**
+
+You agree that COMMANDERS ACT shall have no liability whatsoever for any use made of the SDK by You or any third party. You hereby agree to defend, indemnify and hold harmless COMMANDERS ACT from any and all claims, damages, liabilities, costs, and expenses (including attorney's fees) arising from claims related to Your use of the SDK as well as from Your failure to comply with this Agreement.
+
+1. **Limitation of Liability**
+
+UNDER NO CIRCUMSTANCES SHALL COMMANDERS ACT BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL DAMAGES, OR FOR ANY LOSS OF DATA, REVENUE, BUSINESS OR REPUTATION, THAT ARISES UNDER OR IN CONNECTION WITH THIS AGREEMENT, OR THAT RESULTS FROM THE USE OF, OR THE INABILITY TO USE, THE SDK.
+
+COMMANDERS ACT'S TOTAL AGGREGATE LIABILITY FOR ANY AND ALL DIRECT DAMAGES AND LOSSES THAT ARISE UNDER OR IN CONNECTION WITH THIS AGREEMENT SHALL NOT IN ANY CIRCUMSTANCE EXCEED THE AMOUNT OF β¬1000.
+
+THE FOREGOING LIMITATIONS AND EXCLUSIONS IN THIS SECTION βSHALL APPLY: (I) EVEN IF COMMANDERS ACT HAS BEEN ADVISED OF THE POSSIBILITY OF ANY DAMAGES OR LOSSES; (II) EVEN IF ANY REMEDY SET FORTH HEREIN FAILS OF ITS ESSENTIAL PURPOSE; AND (III) REGARDLESS OF THE BASIS OR THEORY OF LIABILITY.
+
+1. **Miscellaneous**
+
+This Agreement represents the complete agreement concerning the SDK between You and COMMANDERS ACT and supersedes all prior agreements and representations between You and COMMANDERS ACT.
+
+If any provision of this Agreement is held to be unenforceable for any reason, such provision shall be reformed only to the extent necessary to make it enforceable.
+
+Any waiver of any provision of this Agreement will be effective only if in writing and signed by COMMANDERS ACT.
+
+This Agreement is personal to You and may not be assigned or transferred for any reason whatsoever without the consent of COMMANDERS ACT and any action or conduct in violation of the foregoing shall be void and without effect.
+
+COMMANDERS ACT expressly reserves the right to assign this Agreement and to delegate any of its obligations hereunder.
+
+1. **Law and jurisdiction**
+
+This Agreement is governed by and construed under the laws of the State of France.
+
+You expressly agree that the exclusive jurisdiction for any claim or action arising out of or relating to this Agreement shall be the courts located in Paris, France.
+ License
+ unknown
+ Type
+ PSGroupSpecifier
+
+
+
+
diff --git a/Application/Sources/Application/AppDelegate.m b/Application/Sources/Application/AppDelegate.m
index 626bf3f60..386666a5d 100755
--- a/Application/Sources/Application/AppDelegate.m
+++ b/Application/Sources/Application/AppDelegate.m
@@ -104,11 +104,6 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
name:SRGLetterboxPlaybackDidContinueAutomaticallyNotification
object:nil];
- [NSNotificationCenter.defaultCenter addObserver:self
- selector:@selector(userConsentWillShowBanner:)
- name:UserConsentHelper.userConsentWillShowBannerNotification
- object:nil];
-
[PushService.sharedService setupWithLaunchingWithOptions:launchOptions];
[PushService.sharedService updateApplicationBadge];
@@ -201,7 +196,7 @@ - (void)applicationDidBecomeActive:(UIApplication *)application
- (SRGAnalyticsLabels *)srg_globalLabels
{
- return UserConsentHelper.srgAnalyticsLabels;
+ return SRGAnalyticsLabels.play_globalLabels;
}
#pragma mark Helpers
@@ -266,14 +261,12 @@ - (void)setupDataProvider
- (void)setupAnalytics
{
- ApplicationConfiguration *applicationConfiguration = ApplicationConfiguration.sharedApplicationConfiguration;
+ [SRGAnalyticsTracker applySetupAnalyticsWorkaround];
+ ApplicationConfiguration *applicationConfiguration = ApplicationConfiguration.sharedApplicationConfiguration;
SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:applicationConfiguration.analyticsBusinessUnitIdentifier
- container:applicationConfiguration.analyticsContainer
+ sourceKey:applicationConfiguration.analyticsSourceKey
siteName:applicationConfiguration.siteName];
-#if defined(DEBUG) || defined(NIGHTLY) || defined(BETA)
- configuration.environmentMode = SRGAnalyticsEnvironmentModePreProduction;
-#endif
[SRGAnalyticsTracker.sharedTracker startWithConfiguration:configuration
dataSource:self
identityService:SRGIdentityService.currentIdentityService];
@@ -377,25 +370,20 @@ - (void)playbackDidContinueAutomatically:(NSNotification *)notification
{
SRGMedia *media = notification.userInfo[SRGLetterboxMediaKey];
if (media) {
- [[AnalyticsHiddenEventObjC continuousPlaybackWithAction:AnalyticsContiniousPlaybackActionPlayAutomatic
+ [[AnalyticsEventObjC continuousPlaybackWithAction:AnalyticsContiniousPlaybackActionPlayAutomatic
mediaUrn:media.URN]
send];
}
}
-- (void)userConsentWillShowBanner:(NSNotification *)notification
-{
- [SRGLetterboxService.sharedService.controller pause];
-}
-
- (void)userDidCancelLogin:(NSNotification *)notification
{
- [[AnalyticsHiddenEventObjC identityWithAction:AnalyticsIdentityActionCancelLogin] send];
+ [[AnalyticsEventObjC identityWithAction:AnalyticsIdentityActionCancelLogin] send];
}
- (void)userDidLogin:(NSNotification *)notification
{
- [[AnalyticsHiddenEventObjC identityWithAction:AnalyticsIdentityActionLogin] send];
+ [[AnalyticsEventObjC identityWithAction:AnalyticsIdentityActionLogin] send];
}
- (void)didUpdateAccount:(NSNotification *)notification
@@ -421,7 +409,7 @@ - (void)userDidLogout:(NSNotification *)notification
}
AnalyticsIdentityAction action = unexpectedLogout ? AnalyticsIdentityActionUnexpectedLogout : AnalyticsIdentityActionLogout;
- [[AnalyticsHiddenEventObjC identityWithAction:action] send];
+ [[AnalyticsEventObjC identityWithAction:action] send];
}
#pragma mark KVO
diff --git a/Application/Sources/Application/Navigation.swift b/Application/Sources/Application/Navigation.swift
index 299151ed6..fa368a7e9 100644
--- a/Application/Sources/Application/Navigation.swift
+++ b/Application/Sources/Application/Navigation.swift
@@ -48,26 +48,17 @@ extension UIViewController {
.sink { upcomingMedia in
guard let upcomingMedia else { return }
- AnalyticsHiddenEvent.continuousPlayback(action: .display,
- mediaUrn: upcomingMedia.urn)
+ AnalyticsEvent.continuousPlayback(action: .display,
+ mediaUrn: upcomingMedia.urn)
.send()
}
.store(in: &cancellables)
- NotificationCenter.default.weakPublisher(for: UserConsentHelper.userConsentWillShowBannerNotification)
- .sink { _ in
- controller.pause()
- }
- .store(in: &cancellables)
-
let position = HistoryResumePlaybackPositionForMedia(media)
- controller.prepare(toPlay: media, at: position, withPreferredSettings: nil, completionHandler: {
- if !UserConsentHelper.isShowingBanner {
- controller.play()
- }
- })
+ controller.playMedia(media, at: position, withPreferredSettings: nil)
+
present(letterboxViewController, animated: animated) {
- SRGAnalyticsTracker.shared.trackPageView(withTitle: AnalyticsPageTitle.player.rawValue, levels: [AnalyticsPageLevel.play.rawValue])
+ SRGAnalyticsTracker.shared.trackPageView(withTitle: AnalyticsPageTitle.player.rawValue, type: AnalyticsPageType.detail.rawValue, levels: [AnalyticsPageLevel.play.rawValue])
if let completion {
completion()
}
@@ -212,11 +203,11 @@ extension UIViewController {
} receiveValue: { [weak self] media in
guard let self else { return }
self.play_presentMediaPlayer(with: media, position: nil, airPlaySuggestions: true, fromPushNotification: false, animated: animated) { _ in
- AnalyticsHiddenEvent.notification(action: .playMedia,
- from: .application,
- uid: mediaUrn,
- overrideSource: notification.showURN,
- overrideType: UserNotificationTypeString(notification.type))
+ AnalyticsEvent.notification(action: .playMedia,
+ from: .application,
+ uid: mediaUrn,
+ overrideSource: notification.showURN,
+ overrideType: UserNotificationTypeString(notification.type))
.send()
UserConsentHelper.waitCollectingConsentRelease()
}
@@ -236,19 +227,19 @@ extension UIViewController {
let showViewController = SectionViewController.showViewController(for: show)
navigationController.pushViewController(showViewController, animated: animated)
- AnalyticsHiddenEvent.notification(action: .displayShow,
- from: .application,
- uid: showUrn,
- overrideType: UserNotificationTypeString(notification.type))
+ AnalyticsEvent.notification(action: .displayShow,
+ from: .application,
+ uid: showUrn,
+ overrideType: UserNotificationTypeString(notification.type))
.send()
UserConsentHelper.waitCollectingConsentRelease()
}
}
else {
- AnalyticsHiddenEvent.notification(action: .alert,
- from: .application,
- uid: notification.body,
- overrideType: UserNotificationTypeString(notification.type))
+ AnalyticsEvent.notification(action: .alert,
+ from: .application,
+ uid: notification.body,
+ overrideType: UserNotificationTypeString(notification.type))
.send()
}
}
diff --git a/Application/Sources/Application/SceneDelegate.m b/Application/Sources/Application/SceneDelegate.m
index 990b762e5..4fd0ac1b3 100644
--- a/Application/Sources/Application/SceneDelegate.m
+++ b/Application/Sources/Application/SceneDelegate.m
@@ -120,31 +120,31 @@ - (void)handleDeepLinkAction:(DeepLinkAction *)action
NSString *channelUid = [action parameterWithName:@"channel_id"];
NSInteger startTime = [action parameterWithName:@"start_time"].integerValue;
[self openMediaWithURN:action.identifier startTime:startTime channelUid:channelUid fromPushNotification:NO completionBlock:^{
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}];
}
else if ([action.type isEqualToString:DeepLinkTypeShow]) {
NSString *channelUid = [action parameterWithName:@"channel_id"];
[self openShowWithURN:action.identifier channelUid:channelUid fromPushNotification:NO completionBlock:^{
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}];
}
else if ([action.type isEqualToString:DeepLinkTypeTopic]) {
[self openTopicWithURN:action.identifier completionBlock:^{
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}];
}
else if ([action.type isEqualToString:DeepLinkTypeHome]) {
NSString *channelUid = [action parameterWithName:@"channel_id"];
[self openHomeWithChannelUid:channelUid completionBlock:^{
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}];
}
else if ([action.type isEqualToString:DeepLinkTypeAZ]) {
NSString *index = [action parameterWithName:@"index"];
NSString *channelUid = [action parameterWithName:@"channel_id"];
[self openShowListAtIndex:index withChannelUid:channelUid completionBlock:^{
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}];
}
else if ([action.type isEqualToString:DeepLinkTypeByDate]) {
@@ -152,12 +152,12 @@ - (void)handleDeepLinkAction:(DeepLinkAction *)action
NSDate *date = dateString ? [NSDateFormatter.play_iso8601CalendarDate dateFromString:dateString] : nil;
NSString *channelUid = [action parameterWithName:@"channel_id"];
[self openCalendarAtDate:date withChannelUid:channelUid completionBlock:^{
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}];
}
else if ([action.type isEqualToString:DeepLinkTypeSection]) {
[self openSectionWithUid:action.identifier completionBlock:^{
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}];
}
else if ([action.type isEqualToString:DeepLinkTypeSearch]) {
@@ -174,27 +174,27 @@ - (void)handleDeepLinkAction:(DeepLinkAction *)action
SRGMediaType mediaType = s_mediaTypes[mediaTypeName].integerValue;
[self openSearchWithQuery:query mediaType:mediaType completionBlock:^{
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}];
}
else if ([action.type isEqualToString:DeepLinkTypeLivestreams]) {
[self openLivestreamsWithCompletionBlock:^{
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}];
}
else if ([action.type isEqualToString:DeepLinkTypeLink]) {
NSURL *URL = [NSURL URLWithString:action.identifier];
if (URL) {
[UIApplication.sharedApplication play_openURL:URL withCompletionHandler:^(BOOL success) {
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}];
}
else {
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}
}
else {
- [action.analyticsHiddenEvent send];
+ [action.analyticsEvent send];
}
}
@@ -332,7 +332,7 @@ - (void)handleUserActivity:(NSUserActivity *)userActivity
NSNumber *position = [userActivity.userInfo[@"position"] isKindOfClass:NSNumber.class] ? userActivity.userInfo[@"position"] : nil;
[self playURN:mediaURN media:media atPosition:[SRGPosition positionAtTimeInSeconds:position.integerValue] fromPushNotification:NO completion:nil];
- [[AnalyticsHiddenEventObjC userActivityWithAction:AnalyticsUserActivityActionPlayMedia urn:mediaURN] send];
+ [[AnalyticsEventObjC userActivityWithAction:AnalyticsUserActivityActionPlayMedia urn:mediaURN] send];
}
else {
NSError *error = [NSError errorWithDomain:PlayErrorDomain
@@ -353,7 +353,7 @@ - (void)handleUserActivity:(NSUserActivity *)userActivity
[self openShowURN:showURN show:show fromPushNotification:NO];
}];
- [[AnalyticsHiddenEventObjC userActivityWithAction:AnalyticsUserActivityActionDisplayShow urn:showURN] send];
+ [[AnalyticsEventObjC userActivityWithAction:AnalyticsUserActivityActionDisplayShow urn:showURN] send];
}
else {
NSError *error = [NSError errorWithDomain:PlayErrorDomain
@@ -378,19 +378,19 @@ - (BOOL)handleShortcutItem:(UIApplicationShortcutItem *)shortcutItem
ApplicationSectionInfo *applicationSectionInfo = nil;
if ([shortcutItem.type isEqualToString:@"favorites"]) {
applicationSectionInfo = [ApplicationSectionInfo applicationSectionInfoWithApplicationSection:ApplicationSectionFavorites radioChannel:nil];
- [[AnalyticsHiddenEventObjC shortcutItemWithAction:AnalyticsShortcutItemActionFavorites] send];
+ [[AnalyticsEventObjC shortcutItemWithAction:AnalyticsShortcutItemActionFavorites] send];
}
else if ([shortcutItem.type isEqualToString:@"downloads"]) {
applicationSectionInfo = [ApplicationSectionInfo applicationSectionInfoWithApplicationSection:ApplicationSectionDownloads radioChannel:nil];
- [[AnalyticsHiddenEventObjC shortcutItemWithAction:AnalyticsShortcutItemActionDownloads] send];
+ [[AnalyticsEventObjC shortcutItemWithAction:AnalyticsShortcutItemActionDownloads] send];
}
else if ([shortcutItem.type isEqualToString:@"history"]) {
applicationSectionInfo = [ApplicationSectionInfo applicationSectionInfoWithApplicationSection:ApplicationSectionHistory radioChannel:nil];
- [[AnalyticsHiddenEventObjC shortcutItemWithAction:AnalyticsShortcutItemActionHistory] send];
+ [[AnalyticsEventObjC shortcutItemWithAction:AnalyticsShortcutItemActionHistory] send];
}
else if ([shortcutItem.type isEqualToString:@"search"]) {
applicationSectionInfo = [ApplicationSectionInfo applicationSectionInfoWithApplicationSection:ApplicationSectionSearch radioChannel:nil];
- [[AnalyticsHiddenEventObjC shortcutItemWithAction:AnalyticsShortcutItemActionSearch] send];
+ [[AnalyticsEventObjC shortcutItemWithAction:AnalyticsShortcutItemActionSearch] send];
}
else {
return NO;
diff --git a/Application/Sources/Application/UserConsentHelper.swift b/Application/Sources/Application/UserConsentHelper.swift
index df471eacd..c05b203f5 100644
--- a/Application/Sources/Application/UserConsentHelper.swift
+++ b/Application/Sources/Application/UserConsentHelper.swift
@@ -283,13 +283,14 @@ enum UCService: Hashable, CaseIterable {
switch service {
#if os(iOS)
case .airship:
- // Airship analytics feature is disabled at launch. See `PushService.m`.
- if acceptedConsent {
- Airship.shared.privacyManager.enableFeatures(Features.analytics)
- }
- else {
- Airship.shared.privacyManager.disableFeatures(Features.analytics)
- }
+ if PushService.shared != nil {
+ // Airship analytics feature is disabled at launch. See `PushService.m`.
+ if acceptedConsent {
+ Airship.shared.privacyManager.enableFeatures(Features.analytics)
+ }
+ else {
+ Airship.shared.privacyManager.disableFeatures(Features.analytics)
+ }}
#endif
case .appcenter:
// Only `Crashes` service is used. `Analytics` service not instantiated.
diff --git a/Application/Sources/Browser/WebViewController.h b/Application/Sources/Browser/WebViewController.h
index 15477a83a..9d97b6ca8 100755
--- a/Application/Sources/Browser/WebViewController.h
+++ b/Application/Sources/Browser/WebViewController.h
@@ -38,6 +38,13 @@ typedef void (^WebViewControllerCustomizationBlock)(WKWebView *webView);
*/
@property (nonatomic, copy, nullable) NSString *analyticsPageTitle;
+/**
+ * Page type. Must be set before view display.
+ *
+ * @discussion If `nil` no tracking is made.
+ */
+@property (nonatomic, copy, nullable) NSString *analyticsPageType;
+
/**
* Page levels. Defaults to `nil`.
*/
diff --git a/Application/Sources/Browser/WebViewController.m b/Application/Sources/Browser/WebViewController.m
index 9016026e0..c8fc391e2 100755
--- a/Application/Sources/Browser/WebViewController.m
+++ b/Application/Sources/Browser/WebViewController.m
@@ -183,6 +183,12 @@ - (NSString *)srg_pageViewTitle
return self.analyticsPageTitle ?: @"";
}
+- (NSString *)srg_pageViewType
+{
+ return self.analyticsPageType ?: @"";
+}
+
+
- (NSArray *)srg_pageViewLevels
{
return self.analyticsPageLevels;
diff --git a/Application/Sources/Calendar/CalendarViewController.m b/Application/Sources/Calendar/CalendarViewController.m
index fe447956c..1b6040d0b 100755
--- a/Application/Sources/Calendar/CalendarViewController.m
+++ b/Application/Sources/Calendar/CalendarViewController.m
@@ -357,6 +357,11 @@ - (NSString *)srg_pageViewTitle
return AnalyticsPageTitleShowsCalendar;
}
+- (NSString *)srg_pageViewType
+{
+ return AnalyticsPageTypeOverview;
+}
+
- (NSArray *)srg_pageViewLevels
{
if (self.radioChannel) {
diff --git a/Application/Sources/CarPlay/CarPlayList.swift b/Application/Sources/CarPlay/CarPlayList.swift
index 1a8af26d7..1a03e7346 100644
--- a/Application/Sources/CarPlay/CarPlayList.swift
+++ b/Application/Sources/CarPlay/CarPlayList.swift
@@ -47,6 +47,17 @@ enum CarPlayList {
}
}
+ var pageViewType: String? {
+ switch self {
+ case .latestEpisodesFromFavorites, .livePrograms, .mostPopularMedias:
+ return AnalyticsPageType.detail.rawValue
+ case .livestreams:
+ return AnalyticsPageType.live.rawValue
+ case .mostPopular:
+ return AnalyticsPageType.overview.rawValue
+ }
+ }
+
var pageViewLevels: [String]? {
switch self {
case .latestEpisodesFromFavorites:
diff --git a/Application/Sources/CarPlay/CarPlayNowPlayingController.swift b/Application/Sources/CarPlay/CarPlayNowPlayingController.swift
index 788f25412..f618f34e8 100644
--- a/Application/Sources/CarPlay/CarPlayNowPlayingController.swift
+++ b/Application/Sources/CarPlay/CarPlayNowPlayingController.swift
@@ -126,6 +126,7 @@ extension CarPlayNowPlayingController: CarPlayTemplateController {
func didAppear(animated: Bool) {
SRGAnalyticsTracker.shared.uncheckedTrackPageView(
withTitle: AnalyticsPageTitle.player.rawValue,
+ type: AnalyticsPageType.detail.rawValue,
levels: [AnalyticsPageLevel.play.rawValue, AnalyticsPageLevel.automobile.rawValue]
)
}
diff --git a/Application/Sources/CarPlay/CarPlayTemplateListController.swift b/Application/Sources/CarPlay/CarPlayTemplateListController.swift
index 7c22cb312..1a2a8a803 100644
--- a/Application/Sources/CarPlay/CarPlayTemplateListController.swift
+++ b/Application/Sources/CarPlay/CarPlayTemplateListController.swift
@@ -65,8 +65,8 @@ extension CarPlayTemplateListController: CarPlayTemplateController {
}
func didAppear(animated: Bool) {
- if let pageViewTitle = list.pageViewTitle {
- SRGAnalyticsTracker.shared.uncheckedTrackPageView(withTitle: pageViewTitle, levels: list.pageViewLevels)
+ if let pageViewTitle = list.pageViewTitle, let pageViewType = list.pageViewType {
+ SRGAnalyticsTracker.shared.uncheckedTrackPageView(withTitle: pageViewTitle, type: pageViewType, levels: list.pageViewLevels)
}
}
diff --git a/Application/Sources/Configuration/ApplicationConfiguration.h b/Application/Sources/Configuration/ApplicationConfiguration.h
index 2def55c73..19df10dd8 100755
--- a/Application/Sources/Configuration/ApplicationConfiguration.h
+++ b/Application/Sources/Configuration/ApplicationConfiguration.h
@@ -29,7 +29,7 @@ OBJC_EXPORT NSString * const ApplicationConfigurationDidChangeNotification;
@property (nonatomic, readonly) SRGVendor vendor;
@property (nonatomic, readonly, copy) SRGAnalyticsBusinessUnitIdentifier analyticsBusinessUnitIdentifier;
-@property (nonatomic, readonly) NSInteger analyticsContainer;
+@property (nonatomic, readonly, copy) NSString *analyticsSourceKey;
@property (nonatomic, readonly, copy) NSString *siteName;
diff --git a/Application/Sources/Configuration/ApplicationConfiguration.m b/Application/Sources/Configuration/ApplicationConfiguration.m
index 0de375d75..438309599 100755
--- a/Application/Sources/Configuration/ApplicationConfiguration.m
+++ b/Application/Sources/Configuration/ApplicationConfiguration.m
@@ -114,7 +114,7 @@ @interface ApplicationConfiguration ()
@property (nonatomic) SRGVendor vendor;
@property (nonatomic, copy) SRGAnalyticsBusinessUnitIdentifier analyticsBusinessUnitIdentifier;
-@property (nonatomic) NSInteger analyticsContainer;
+@property (nonatomic, copy) NSString *analyticsSourceKey;
@property (nonatomic, copy) NSString *siteName;
@@ -286,9 +286,13 @@ - (BOOL)synchronizeWithFirebaseConfiguration:(PlayFirebaseConfiguration *)fireba
if (! analyticsBusinessUnitIdentifier) {
return NO;
}
-
- NSNumber *analyticsContainer = [firebaseConfiguration numberForKey:@"container"];
- if (! analyticsContainer) {
+
+#if defined(DEBUG) || defined(NIGHTLY) || defined(BETA)
+ NSString *analyticsSourceKey = @"39ae8f94-595c-4ca4-81f7-fb7748bd3f04";
+#else
+ NSString *analyticsSourceKey = [firebaseConfiguration stringForKey:@"sourceKey"];
+#endif
+ if (! analyticsSourceKey) {
return NO;
}
@@ -335,7 +339,7 @@ - (BOOL)synchronizeWithFirebaseConfiguration:(PlayFirebaseConfiguration *)fireba
self.businessUnitIdentifier = businessUnitIdentifier;
self.vendor = vendor;
self.analyticsBusinessUnitIdentifier = analyticsBusinessUnitIdentifier;
- self.analyticsContainer = analyticsContainer.integerValue;
+ self.analyticsSourceKey = analyticsSourceKey;
#if TARGET_OS_IOS
self.siteName = siteName;
#else
diff --git a/Application/Sources/Content/Content.swift b/Application/Sources/Content/Content.swift
index 2f16dbe4c..3cc2a311a 100644
--- a/Application/Sources/Content/Content.swift
+++ b/Application/Sources/Content/Content.swift
@@ -149,8 +149,9 @@ protocol SectionProperties {
/// Analytics information
var analyticsTitle: String? { get }
+ var analyticsType: String? { get }
var analyticsLevels: [String]? { get }
- func analyticsDeletionHiddenEvent(source: AnalyticsListSource) -> AnalyticsHiddenEvent?
+ func analyticsDeletionHiddenEvent(source: AnalyticsListSource) -> AnalyticsEvent?
/// Properties for section displayed as a row
var rowHighlight: Highlight? { get }
@@ -319,6 +320,15 @@ private extension Content {
}
}
+ var analyticsType: String? {
+ switch contentSection.type {
+ case .none:
+ return nil
+ default:
+ return AnalyticsPageType.detail.rawValue
+ }
+ }
+
var analyticsLevels: [String]? {
switch contentSection.type {
case .medias, .showAndMedias, .shows:
@@ -330,14 +340,14 @@ private extension Content {
}
}
- func analyticsDeletionHiddenEvent(source: AnalyticsListSource) -> AnalyticsHiddenEvent? {
+ func analyticsDeletionHiddenEvent(source: AnalyticsListSource) -> AnalyticsEvent? {
switch presentation.type {
case .favoriteShows:
- return AnalyticsHiddenEvent.favorite(action: .remove, source: source, urn: nil)
+ return AnalyticsEvent.favorite(action: .remove, source: source, urn: nil)
case .watchLater:
- return AnalyticsHiddenEvent.watchLater(action: .remove, source: source, urn: nil)
+ return AnalyticsEvent.watchLater(action: .remove, source: source, urn: nil)
case .continueWatching:
- return AnalyticsHiddenEvent.historyRemove(source: source, urn: nil)
+ return AnalyticsEvent.historyRemove(source: source, urn: nil)
default:
return nil
}
@@ -705,6 +715,17 @@ private extension Content {
}
}
+ var analyticsType: String? {
+ switch configuredSection {
+ case .show, .radioAllShows, .tvAllShows:
+ return AnalyticsPageType.overview.rawValue
+ case .tvLiveCenterScheduledLivestreams, .tvLiveCenterScheduledLivestreamsAll, .tvLiveCenterEpisodes, .tvLiveCenterEpisodesAll, .tvScheduledLivestreams, .tvScheduledLivestreamsSignLanguage, .tvLive, .radioLive, .radioLiveSatellite:
+ return AnalyticsPageType.live.rawValue
+ default:
+ return AnalyticsPageType.detail.rawValue
+ }
+ }
+
var analyticsLevels: [String]? {
switch configuredSection {
case let .show(show):
@@ -746,17 +767,17 @@ private extension Content {
}
}
- func analyticsDeletionHiddenEvent(source: AnalyticsListSource) -> AnalyticsHiddenEvent? {
+ func analyticsDeletionHiddenEvent(source: AnalyticsListSource) -> AnalyticsEvent? {
switch configuredSection {
case .favoriteShows, .radioFavoriteShows:
- return AnalyticsHiddenEvent.favorite(action: .remove, source: source, urn: nil)
+ return AnalyticsEvent.favorite(action: .remove, source: source, urn: nil)
case .radioWatchLater, .watchLater:
- return AnalyticsHiddenEvent.watchLater(action: .remove, source: source, urn: nil)
+ return AnalyticsEvent.watchLater(action: .remove, source: source, urn: nil)
case .history, .radioResumePlayback:
- return AnalyticsHiddenEvent.historyRemove(source: source, urn: nil)
+ return AnalyticsEvent.historyRemove(source: source, urn: nil)
#if os(iOS)
case .downloads:
- return AnalyticsHiddenEvent.download(action: .remove, source: source, urn: nil)
+ return AnalyticsEvent.download(action: .remove, source: source, urn: nil)
#endif
default:
return nil
diff --git a/Application/Sources/Content/PageViewController.swift b/Application/Sources/Content/PageViewController.swift
index 9cac66f5e..f31594da1 100644
--- a/Application/Sources/Content/PageViewController.swift
+++ b/Application/Sources/Content/PageViewController.swift
@@ -273,6 +273,7 @@ final class PageViewController: UIViewController {
self.analyticsPageViewTracked = true
SRGAnalyticsTracker.shared.trackPageView(withTitle: model.analyticsPageViewTitle,
+ type: model.analyticsPageViewType,
levels: model.analyticsPageViewLevels,
labels: model.analyticsPageViewLabels(pageUid: pageUid),
fromPushNotification: false)
diff --git a/Application/Sources/Content/PageViewModel.swift b/Application/Sources/Content/PageViewModel.swift
index 3224fdf64..7161acdfc 100644
--- a/Application/Sources/Content/PageViewModel.swift
+++ b/Application/Sources/Content/PageViewModel.swift
@@ -36,6 +36,17 @@ final class PageViewModel: Identifiable, ObservableObject {
}
}
+ var analyticsPageViewType: String {
+ switch id {
+ case .video, .audio:
+ return AnalyticsPageType.landingPage.rawValue
+ case .live:
+ return AnalyticsPageType.live.rawValue
+ case .topic:
+ return AnalyticsPageType.overview.rawValue
+ }
+ }
+
var analyticsPageViewLevels: [String]? {
switch id {
case .video:
diff --git a/Application/Sources/Content/SectionShowHeaderView.swift b/Application/Sources/Content/SectionShowHeaderView.swift
index f5f6d2b0b..d1cb735ca 100644
--- a/Application/Sources/Content/SectionShowHeaderView.swift
+++ b/Application/Sources/Content/SectionShowHeaderView.swift
@@ -126,7 +126,7 @@ struct SectionShowHeaderView: View {
}
var body: some View {
- SimpleButton(icon: "episodes", label: show.title) {
+ SimpleButton(icon: .episodes, label: show.title) {
firstResponder.sendAction(#selector(SectionShowHeaderViewAction.openShow(sender:event:)), for: OpenShowEvent(show: show))
}
.frame(maxWidth: 350)
diff --git a/Application/Sources/Content/SectionViewController.swift b/Application/Sources/Content/SectionViewController.swift
index fcf38c412..59e1c39dc 100644
--- a/Application/Sources/Content/SectionViewController.swift
+++ b/Application/Sources/Content/SectionViewController.swift
@@ -229,7 +229,7 @@ final class SectionViewController: UIViewController {
editButtonItem.title = NSLocalizedString("Done", comment: "Done button title")
let numberOfSelectedItems = model.numberOfSelectedItems
- let deleteBarButtonItem = UIBarButtonItem(image: UIImage(named: "delete"), style: .plain, target: self, action: #selector(deleteSelectedItems))
+ let deleteBarButtonItem = UIBarButtonItem(image: UIImage(resource: .delete), style: .plain, target: self, action: #selector(deleteSelectedItems))
deleteBarButtonItem.tintColor = .red
deleteBarButtonItem.isEnabled = (numberOfSelectedItems != 0)
deleteBarButtonItem.accessibilityLabel = PlaySRGAccessibilityLocalizedString("Delete", comment: "Delete button label")
@@ -246,7 +246,7 @@ final class SectionViewController: UIViewController {
navigationItem.title = (model.displaysTitle || !firstHeaderVisible) ? model.title : nil
if model.configuration.properties.sharingItem != nil {
- let shareButtonItem = UIBarButtonItem(image: UIImage(named: "share"),
+ let shareButtonItem = UIBarButtonItem(image: UIImage(resource: .share),
style: .plain,
target: self,
action: #selector(self.shareContent(_:)))
@@ -609,6 +609,10 @@ extension SectionViewController: SRGAnalyticsViewTracking {
return model.configuration.properties.analyticsTitle ?? ""
}
+ var srg_pageViewType: String {
+ return model.configuration.properties.analyticsType ?? ""
+ }
+
var srg_pageViewLevels: [String]? {
return model.configuration.properties.analyticsLevels
}
diff --git a/Application/Sources/Content/ShowHeaderViewModel.swift b/Application/Sources/Content/ShowHeaderViewModel.swift
index aa2c82387..fd0a9392a 100644
--- a/Application/Sources/Content/ShowHeaderViewModel.swift
+++ b/Application/Sources/Content/ShowHeaderViewModel.swift
@@ -79,8 +79,8 @@ final class ShowHeaderViewModel: ObservableObject {
return url(for: show?.image, size: .large)
}
- var favoriteIcon: String {
- return isFavorite ? "favorite_full" : "favorite"
+ var favoriteIcon: ImageResource {
+ return isFavorite ? .favoriteFull : .favorite
}
var favoriteLabel: String {
@@ -102,12 +102,12 @@ final class ShowHeaderViewModel: ObservableObject {
return PushService.shared != nil && isFavorite
}
- var subscriptionIcon: String {
+ var subscriptionIcon: ImageResource {
switch subscriptionStatus {
case .unavailable, .unsubscribed:
- return "subscription"
+ return .subscription
case .subscribed:
- return "subscription_full"
+ return .subscriptionFull
}
}
@@ -126,7 +126,7 @@ final class ShowHeaderViewModel: ObservableObject {
FavoritesToggleShow(show)
let action = isFavorite ? .remove : .add as AnalyticsListAction
- AnalyticsHiddenEvent.favorite(action: action, source: .button, urn: show.urn).send()
+ AnalyticsEvent.favorite(action: action, source: .button, urn: show.urn).send()
#if os(iOS)
Banner.showFavorite(!isFavorite, forItemWithName: show.title)
@@ -140,7 +140,7 @@ final class ShowHeaderViewModel: ObservableObject {
if FavoritesToggleSubscriptionForShow(show) {
let isSubscribed = (subscriptionStatus == .subscribed)
let action = isSubscribed ? .remove : .add as AnalyticsListAction
- AnalyticsHiddenEvent.subscription(action: action, source: .button, urn: show.urn).send()
+ AnalyticsEvent.subscription(action: action, source: .button, urn: show.urn).send()
Banner.showSubscription(!isSubscribed, forItemWithName: show.title)
}
diff --git a/Application/Sources/DeepLinking/DeepLinkAction.h b/Application/Sources/DeepLinking/DeepLinkAction.h
index 852e10cc3..dfad21251 100644
--- a/Application/Sources/DeepLinking/DeepLinkAction.h
+++ b/Application/Sources/DeepLinking/DeepLinkAction.h
@@ -9,7 +9,7 @@
NS_ASSUME_NONNULL_BEGIN
-@class AnalyticsHiddenEventObjC;
+@class AnalyticsEventObjC;
typedef NSString * DeepLinkType NS_STRING_ENUM;
@@ -62,7 +62,7 @@ OBJC_EXPORT DeepLinkType const DeepLinkTypeUnsupported;
*/
@property (nonatomic, readonly) DeepLinkType type;
@property (nonatomic, readonly, copy) NSString *identifier;
-@property (nonatomic, readonly) AnalyticsHiddenEventObjC *analyticsHiddenEvent;
+@property (nonatomic, readonly) AnalyticsEventObjC *analyticsEvent;
/**
* Return the parameter matching the specified name, if any.
diff --git a/Application/Sources/DeepLinking/DeepLinkAction.m b/Application/Sources/DeepLinking/DeepLinkAction.m
index fac9efc02..7aa1ecb0c 100644
--- a/Application/Sources/DeepLinking/DeepLinkAction.m
+++ b/Application/Sources/DeepLinking/DeepLinkAction.m
@@ -30,7 +30,7 @@ @interface DeepLinkAction ()
@property (nonatomic) DeepLinkType type;
@property (nonatomic, copy) NSString *identifier;
-@property (nonatomic) AnalyticsHiddenEventObjC *analyticsHiddenEvent;
+@property (nonatomic) AnalyticsEventObjC *analyticsEvent;
@property (nonatomic) NSArray *queryItems;
@end
@@ -41,13 +41,13 @@ @implementation DeepLinkAction
+ (instancetype)unsupportedActionWithSource:(AnalyticsOpenUrlSource)source
{
- AnalyticsHiddenEventObjC *hiddenEvent = [AnalyticsHiddenEventObjC openUrlWithAction:AnalyticsOpenUrlActionOpenPlayApp
+ AnalyticsEventObjC *hiddenEvent = [AnalyticsEventObjC openUrlWithAction:AnalyticsOpenUrlActionOpenPlayApp
source:source
urn:nil];
return [[self alloc] initWithType:DeepLinkTypeUnsupported
identifier:@""
- analyticsHiddenEvent:hiddenEvent
+ analyticsEvent:hiddenEvent
queryItems:nil];
}
@@ -71,13 +71,13 @@ + (instancetype)actionFromURL:(NSURL *)URL source:(AnalyticsOpenUrlSource)source
return [self unsupportedActionWithSource:source];
}
- AnalyticsHiddenEventObjC *hiddenEvent = [AnalyticsHiddenEventObjC openUrlWithAction:AnalyticsOpenUrlActionPlayMedia
+ AnalyticsEventObjC *hiddenEvent = [AnalyticsEventObjC openUrlWithAction:AnalyticsOpenUrlActionPlayMedia
source:source
urn:mediaURN];
return [[self alloc] initWithType:type
identifier:mediaURN
- analyticsHiddenEvent:hiddenEvent
+ analyticsEvent:hiddenEvent
queryItems:URLComponents.queryItems];
}
else if ([type isEqualToString:DeepLinkTypeShow]) {
@@ -86,13 +86,13 @@ + (instancetype)actionFromURL:(NSURL *)URL source:(AnalyticsOpenUrlSource)source
return [self unsupportedActionWithSource:source];
}
- AnalyticsHiddenEventObjC *hiddenEvent = [AnalyticsHiddenEventObjC openUrlWithAction:AnalyticsOpenUrlActionDisplayShow
+ AnalyticsEventObjC *hiddenEvent = [AnalyticsEventObjC openUrlWithAction:AnalyticsOpenUrlActionDisplayShow
source:source
urn:showURN];
return [[self alloc] initWithType:type
identifier:showURN
- analyticsHiddenEvent:hiddenEvent
+ analyticsEvent:hiddenEvent
queryItems:URLComponents.queryItems];
}
else if ([type isEqualToString:DeepLinkTypeTopic]) {
@@ -101,23 +101,23 @@ + (instancetype)actionFromURL:(NSURL *)URL source:(AnalyticsOpenUrlSource)source
return [self unsupportedActionWithSource:source];
}
- AnalyticsHiddenEventObjC *hiddenEvent = [AnalyticsHiddenEventObjC openUrlWithAction:AnalyticsOpenUrlActionDisplayPage
+ AnalyticsEventObjC *hiddenEvent = [AnalyticsEventObjC openUrlWithAction:AnalyticsOpenUrlActionDisplayPage
source:source
urn:topicURN];
return [[self alloc] initWithType:type
identifier:topicURN
- analyticsHiddenEvent:hiddenEvent
+ analyticsEvent:hiddenEvent
queryItems:URLComponents.queryItems];
}
else if ([@[ DeepLinkTypeHome, DeepLinkTypeAZ, DeepLinkTypeByDate, DeepLinkTypeSearch, DeepLinkTypeLivestreams ] containsObject:type]) {
- AnalyticsHiddenEventObjC *hiddenEvent = [AnalyticsHiddenEventObjC openUrlWithAction:AnalyticsOpenUrlActionDisplayPage
+ AnalyticsEventObjC *hiddenEvent = [AnalyticsEventObjC openUrlWithAction:AnalyticsOpenUrlActionDisplayPage
source:source
urn:type];
return [[self alloc] initWithType:type
identifier:type
- analyticsHiddenEvent:hiddenEvent
+ analyticsEvent:hiddenEvent
queryItems:URLComponents.queryItems];
}
else if ([type isEqualToString:DeepLinkTypeSection]) {
@@ -126,13 +126,13 @@ + (instancetype)actionFromURL:(NSURL *)URL source:(AnalyticsOpenUrlSource)source
return [self unsupportedActionWithSource:source];
}
- AnalyticsHiddenEventObjC *hiddenEvent = [AnalyticsHiddenEventObjC openUrlWithAction:AnalyticsOpenUrlActionDisplayPage
+ AnalyticsEventObjC *hiddenEvent = [AnalyticsEventObjC openUrlWithAction:AnalyticsOpenUrlActionDisplayPage
source:source
urn:sectionUid];
return [[self alloc] initWithType:type
identifier:sectionUid
- analyticsHiddenEvent:hiddenEvent
+ analyticsEvent:hiddenEvent
queryItems:URLComponents.queryItems];
}
else if ([type isEqualToString:DeepLinkTypeLink]) {
@@ -141,13 +141,13 @@ + (instancetype)actionFromURL:(NSURL *)URL source:(AnalyticsOpenUrlSource)source
return [self unsupportedActionWithSource:source];
}
- AnalyticsHiddenEventObjC *hiddenEvent = [AnalyticsHiddenEventObjC openUrlWithAction:AnalyticsOpenUrlActionDisplayUrl
+ AnalyticsEventObjC *hiddenEvent = [AnalyticsEventObjC openUrlWithAction:AnalyticsOpenUrlActionDisplayUrl
source:source
urn:URLString];
return [[self alloc] initWithType:type
identifier:URLString
- analyticsHiddenEvent:hiddenEvent
+ analyticsEvent:hiddenEvent
queryItems:URLComponents.queryItems];
}
#if TARGET_OS_IOS
@@ -176,17 +176,17 @@ + (NSString *)valueForParameterWithName:(NSString *)name inQueryItems:(NSArray *)queryItems
{
NSParameterAssert(identifier);
- NSParameterAssert(analyticsHiddenEvent);
+ NSParameterAssert(analyticsEvent);
if (self = [super init]) {
self.type = type;
self.identifier = identifier;
- self.analyticsHiddenEvent = analyticsHiddenEvent;
+ self.analyticsEvent = analyticsEvent;
self.queryItems = queryItems;
}
return self;
diff --git a/Application/Sources/Helpers/AnalyticsClickEvent.swift b/Application/Sources/Helpers/AnalyticsClickEvent.swift
index 8a84dd2f3..c2aacd3f9 100644
--- a/Application/Sources/Helpers/AnalyticsClickEvent.swift
+++ b/Application/Sources/Helpers/AnalyticsClickEvent.swift
@@ -12,7 +12,7 @@ import SRGDataProviderModel
*/
struct AnalyticsClickEvent {
let name: String
- let labels: SRGAnalyticsHiddenEventLabels
+ let labels: SRGAnalyticsEventLabels
private enum PageId: String {
case tvGuide
@@ -23,7 +23,7 @@ struct AnalyticsClickEvent {
* Use this method to send the event when needed.
*/
func send() {
- SRGAnalyticsTracker.shared.trackHiddenEvent(withName: name, labels: labels)
+ SRGAnalyticsTracker.shared.trackEvent(withName: name, labels: labels)
}
static func tvGuideOpenInfoBox(program: SRGProgram, programGuideLayout: ProgramGuideLayout) -> Self {
@@ -108,7 +108,7 @@ struct AnalyticsClickEvent {
private init(name: String, value1: String? = nil, value2: String? = nil, value3: String? = nil, value4: String? = nil, value5: String? = nil) {
self.name = name
- let labels = SRGAnalyticsHiddenEventLabels()
+ let labels = SRGAnalyticsEventLabels()
labels.source = "2797"
labels.type = "ClickEvent"
labels.extraValue1 = value1
diff --git a/Application/Sources/Helpers/AnalyticsConstants.h b/Application/Sources/Helpers/AnalyticsConstants.h
index ef33931a4..ef1e548ca 100755
--- a/Application/Sources/Helpers/AnalyticsConstants.h
+++ b/Application/Sources/Helpers/AnalyticsConstants.h
@@ -68,4 +68,16 @@ OBJC_EXPORT AnalyticsPageTitle const AnalyticsPageTitleTV;
OBJC_EXPORT AnalyticsPageTitle const AnalyticsPageTitleWatchLater;
OBJC_EXPORT AnalyticsPageTitle const AnalyticsPageTitleWhatsNew;
+/**
+ * @name Analytics standard page types
+ */
+typedef NSString * AnalyticsPageType NS_STRING_ENUM;
+
+OBJC_EXPORT AnalyticsPageType const AnalyticsPageTypeDetail;
+OBJC_EXPORT AnalyticsPageType const AnalyticsPageTypeHelp;
+OBJC_EXPORT AnalyticsPageType const AnalyticsPageTypeLandingPage;
+OBJC_EXPORT AnalyticsPageType const AnalyticsPageTypeLive;
+OBJC_EXPORT AnalyticsPageType const AnalyticsPageTypeNavigationPage;
+OBJC_EXPORT AnalyticsPageType const AnalyticsPageTypeOverview;
+
NS_ASSUME_NONNULL_END
diff --git a/Application/Sources/Helpers/AnalyticsConstants.m b/Application/Sources/Helpers/AnalyticsConstants.m
index e30d07618..029ee8dde 100755
--- a/Application/Sources/Helpers/AnalyticsConstants.m
+++ b/Application/Sources/Helpers/AnalyticsConstants.m
@@ -57,3 +57,10 @@
AnalyticsPageTitle const AnalyticsPageTitleTV = @"tv";
AnalyticsPageTitle const AnalyticsPageTitleWatchLater = @"watch later";
AnalyticsPageTitle const AnalyticsPageTitleWhatsNew = @"what is new";
+
+AnalyticsPageType const AnalyticsPageTypeDetail = @"detail";
+AnalyticsPageType const AnalyticsPageTypeHelp = @"help";
+AnalyticsPageType const AnalyticsPageTypeLandingPage = @"landingpage";
+AnalyticsPageType const AnalyticsPageTypeLive = @"live";
+AnalyticsPageType const AnalyticsPageTypeNavigationPage = @"navigationpage";
+AnalyticsPageType const AnalyticsPageTypeOverview = @"overview";
diff --git a/Application/Sources/Helpers/AnalyticsHiddenEvent.swift b/Application/Sources/Helpers/AnalyticsEvent.swift
similarity index 82%
rename from Application/Sources/Helpers/AnalyticsHiddenEvent.swift
rename to Application/Sources/Helpers/AnalyticsEvent.swift
index 8c54a26a0..359f1cabc 100644
--- a/Application/Sources/Helpers/AnalyticsHiddenEvent.swift
+++ b/Application/Sources/Helpers/AnalyticsEvent.swift
@@ -8,18 +8,18 @@ import SRGAnalytics
import SRGDataProviderModel
/**
- * Play analytics hidden event. Defined for native Play applications only.
+ * Play analytics event. Defined for native Play applications only.
*/
-struct AnalyticsHiddenEvent {
+struct AnalyticsEvent {
private let name: String
- private let labels: SRGAnalyticsHiddenEventLabels
+ private let labels: SRGAnalyticsEventLabels
/**
* Each struct created have expected values.
* Use this method to send the event when needed.
*/
func send() {
- SRGAnalyticsTracker.shared.trackHiddenEvent(withName: name, labels: labels)
+ SRGAnalyticsTracker.shared.trackEvent(withName: name, labels: labels)
}
static func calendarEventAdd(channel: SRGChannel) -> Self {
@@ -155,7 +155,7 @@ struct AnalyticsHiddenEvent {
private init(name: String, source: String? = nil, type: String? = nil, value: String? = nil, value1: String? = nil, value2: String? = nil, value3: String? = nil, value4: String? = nil, value5: String? = nil) {
self.name = name
- let labels = SRGAnalyticsHiddenEventLabels()
+ let labels = SRGAnalyticsEventLabels()
labels.source = source
labels.type = type
labels.value = value
@@ -167,17 +167,17 @@ struct AnalyticsHiddenEvent {
self.labels = labels
}
- private init(name: String, labels: SRGAnalyticsHiddenEventLabels) {
+ private init(name: String, labels: SRGAnalyticsEventLabels) {
self.name = name
self.labels = labels
}
}
/**
- * Analytics hidden event compatibility for Objective-C, as a class.
+ * Analytics event compatibility for Objective-C, as a class.
*/
-@objc class AnalyticsHiddenEventObjC: NSObject {
- private let event: AnalyticsHiddenEvent
+@objc class AnalyticsEventObjC: NSObject {
+ private let event: AnalyticsEvent
/**
* Each object created have expected values.
@@ -187,55 +187,55 @@ struct AnalyticsHiddenEvent {
self.event.send()
}
- @objc class func continuousPlayback(action: AnalyticsContiniousPlaybackAction, mediaUrn: String) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.continuousPlayback(action: action, mediaUrn: mediaUrn))
+ @objc class func continuousPlayback(action: AnalyticsContiniousPlaybackAction, mediaUrn: String) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.continuousPlayback(action: action, mediaUrn: mediaUrn))
}
- @objc class func download(action: AnalyticsListAction, source: AnalyticsListSource, urn: String?) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.download(action: action, source: source, urn: urn))
+ @objc class func download(action: AnalyticsListAction, source: AnalyticsListSource, urn: String?) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.download(action: action, source: source, urn: urn))
}
- @objc class func favorite(action: AnalyticsListAction, source: AnalyticsListSource, urn: String?) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.favorite(action: action, source: source, urn: urn))
+ @objc class func favorite(action: AnalyticsListAction, source: AnalyticsListSource, urn: String?) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.favorite(action: action, source: source, urn: urn))
}
- @objc class func googleGast(urn: String) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.googleGast(urn: urn))
+ @objc class func googleGast(urn: String) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.googleGast(urn: urn))
}
- @objc class func identity(action: AnalyticsIdentityAction) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.identity(action: action))
+ @objc class func identity(action: AnalyticsIdentityAction) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.identity(action: action))
}
- @objc class func notification(action: AnalyticsNotificationAction, from: AnalyticsNotificationFrom, uid: String, overrideSource: String? = nil, overrideType: String? = nil) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.notification(action: action, from: from, uid: uid, overrideSource: overrideSource, overrideType: overrideType))
+ @objc class func notification(action: AnalyticsNotificationAction, from: AnalyticsNotificationFrom, uid: String, overrideSource: String? = nil, overrideType: String? = nil) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.notification(action: action, from: from, uid: uid, overrideSource: overrideSource, overrideType: overrideType))
}
- @objc class func openUrl(action: AnalyticsOpenUrlAction, source: AnalyticsOpenUrlSource, urn: String?) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.openUrl(action: action, source: source, urn: urn))
+ @objc class func openUrl(action: AnalyticsOpenUrlAction, source: AnalyticsOpenUrlSource, urn: String?) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.openUrl(action: action, source: source, urn: urn))
}
- @objc class func pictureInPicture(urn: String?) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.pictureInPicture(urn: urn))
+ @objc class func pictureInPicture(urn: String?) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.pictureInPicture(urn: urn))
}
- @objc class func sharing(action: AnalyticsSharingAction, uid: String, mediaContentType: AnalyticsSharingMediaContentType, source: AnalyticsSharingSource, type: String?) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.sharing(action: action, uid: uid, mediaContentType: mediaContentType, source: source, type: type))
+ @objc class func sharing(action: AnalyticsSharingAction, uid: String, mediaContentType: AnalyticsSharingMediaContentType, source: AnalyticsSharingSource, type: String?) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.sharing(action: action, uid: uid, mediaContentType: mediaContentType, source: source, type: type))
}
- @objc class func shortcutItem(action: AnalyticsShortcutItemAction) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.shortcutItem(action: action))
+ @objc class func shortcutItem(action: AnalyticsShortcutItemAction) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.shortcutItem(action: action))
}
- @objc class func userActivity(action: AnalyticsUserActivityAction, urn: String) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.userActivity(action: action, urn: urn))
+ @objc class func userActivity(action: AnalyticsUserActivityAction, urn: String) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.userActivity(action: action, urn: urn))
}
- @objc class func watchLater(action: AnalyticsListAction, source: AnalyticsListSource, urn: String?) -> AnalyticsHiddenEventObjC {
- return Self(event: AnalyticsHiddenEvent.watchLater(action: action, source: source, urn: urn))
+ @objc class func watchLater(action: AnalyticsListAction, source: AnalyticsListSource, urn: String?) -> AnalyticsEventObjC {
+ return Self(event: AnalyticsEvent.watchLater(action: action, source: source, urn: urn))
}
- required init(event: AnalyticsHiddenEvent) {
+ required init(event: AnalyticsEvent) {
self.event = event
}
}
@@ -406,8 +406,8 @@ struct AnalyticsHiddenEvent {
case logout
case unexpectedLogout
- fileprivate var labels: SRGAnalyticsHiddenEventLabels {
- let labels = SRGAnalyticsHiddenEventLabels()
+ fileprivate var labels: SRGAnalyticsEventLabels {
+ let labels = SRGAnalyticsEventLabels()
switch self {
case .displayLogin:
labels.type = "display_login"
diff --git a/Application/Sources/Helpers/Categories/UIViewController+PlaySRG.m b/Application/Sources/Helpers/Categories/UIViewController+PlaySRG.m
index c11e0efd4..d40852e01 100755
--- a/Application/Sources/Helpers/Categories/UIViewController+PlaySRG.m
+++ b/Application/Sources/Helpers/Categories/UIViewController+PlaySRG.m
@@ -206,17 +206,11 @@ - (void)play_presentNativeMediaPlayerWithMedia:(SRGMedia *)media position:(SRGPo
&& letterboxController.playbackState != SRGMediaPlayerPlaybackStatePreparing
&& letterboxController.playbackState != SRGMediaPlayerPlaybackStateEnded) {
[letterboxController seekToPosition:position withCompletionHandler:^(BOOL finished) {
- if (![UserConsentHelper isShowingBanner]) {
- [letterboxController play];
- }
+ [letterboxController play];
}];
}
else {
- [letterboxController prepareToPlayMedia:media atPosition:position withPreferredSettings:ApplicationSettingPlaybackSettings()completionHandler:^{
- if (![UserConsentHelper isShowingBanner]) {
- [letterboxController play];
- }
- }];
+ [letterboxController playMedia:media atPosition:position withPreferredSettings:ApplicationSettingPlaybackSettings()];
}
completion ? completion() : nil;
}
@@ -304,7 +298,7 @@ - (void)play_presentGoogleCastControlsAnimated:(BOOL)animated completion:(void (
UIViewController *topViewController = UIApplication.sharedApplication.mainTopViewController;
[topViewController presentViewController:mediaControlsViewController animated:animated completion:completion];
- [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitlePlayer levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
+ [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitlePlayer type:AnalyticsPageTypeDetail levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
};
if ([topViewController isKindOfClass:MediaPlayerViewController.class]) {
diff --git a/Application/Sources/Helpers/Extensions.swift b/Application/Sources/Helpers/Extensions.swift
index 6d7fc77f7..8d36ea61b 100644
--- a/Application/Sources/Helpers/Extensions.swift
+++ b/Application/Sources/Helpers/Extensions.swift
@@ -9,6 +9,7 @@ import Foundation
import SRGAppearanceSwift
import SRGDataProviderCombine
import SwiftUI
+import TCServerSide_noIDFA
func constant(iOS: T, tvOS: T) -> T {
#if os(tvOS)
@@ -557,3 +558,39 @@ extension UIApplication {
}
#endif
}
+
+extension Locale {
+ static let currentLanguageIdentifier: String = {
+ if #available(iOS 16, tvOS 16, *) {
+ return Locale.current.identifier(.bcp47)
+ } else {
+ return Locale.current.identifier.replacingOccurrences(of: "_", with: "-")
+ }
+ }()
+}
+
+extension SRGAnalyticsLabels {
+ @objc class var play_globalLabels: SRGAnalyticsLabels {
+ let analyticsLabels = UserConsentHelper.srgAnalyticsLabels
+ var customInfo: [String: String] = analyticsLabels.customInfo ?? [:]
+
+ customInfo["navigation_app_language"] = Locale.currentLanguageIdentifier
+
+ analyticsLabels.customInfo = customInfo
+ return analyticsLabels
+ }
+}
+
+extension SRGAnalyticsTracker {
+ @objc class func applySetupAnalyticsWorkaround() {
+ // Workaround for Commanders Act migration from v4 to v5
+
+ // 1. Use the TC unique id value for new `device.sdk_id` property.
+ if let tcUniqueID = TCPredefinedVariables.sharedInstance().uniqueIdentifier(), !tcUniqueID.isEmpty {
+ TCDevice.sharedInstance().sdkID = tcUniqueID
+ }
+
+ // 2. Use the TC unique id value for the new `user.consistent_anonymous_id` property.
+ TCPredefinedVariables.sharedInstance().useLegacyUniqueIDForAnonymousID()
+ }
+}
diff --git a/Application/Sources/Helpers/Extensions/UIImage+PlaySRG.swift b/Application/Sources/Helpers/Extensions/UIImage+PlaySRG.swift
index eb5ef2d85..7cc33d358 100644
--- a/Application/Sources/Helpers/Extensions/UIImage+PlaySRG.swift
+++ b/Application/Sources/Helpers/Extensions/UIImage+PlaySRG.swift
@@ -14,9 +14,9 @@ extension UIImage {
@objc static func image(for youthProtectionColor: SRGYouthProtectionColor) -> UIImage? {
switch youthProtectionColor {
case .yellow:
- return UIImage(named: "youth_protection_yellow")
+ return UIImage(resource: .youthProtectionYellow)
case .red:
- return UIImage(named: "youth_protection_red")
+ return UIImage(resource: .youthProtectionRed)
default:
return nil
}
@@ -28,15 +28,15 @@ extension UIImage {
static func image(for blockingReason: SRGBlockingReason) -> UIImage? {
switch blockingReason {
case .geoblocking:
- return UIImage(named: "geoblocked")
+ return UIImage(resource: .geoblocked)
case .legal:
- return UIImage(named: "legal")
+ return UIImage(resource: .legal)
case .ageRating12, .ageRating18:
- return UIImage(named: "age_rating")
+ return UIImage(resource: .ageRating)
case .startDate, .endDate, .none:
return nil
default:
- return UIImage(named: "generic_blocked")
+ return UIImage(resource: .genericBlocked)
}
}
}
diff --git a/Application/Sources/Helpers/GoogleCast.m b/Application/Sources/Helpers/GoogleCast.m
index d443d0b01..eebc426e7 100755
--- a/Application/Sources/Helpers/GoogleCast.m
+++ b/Application/Sources/Helpers/GoogleCast.m
@@ -142,7 +142,7 @@ BOOL GoogleCastPlayMediaComposition(SRGMediaComposition *mediaComposition, SRGPo
[castSession.remoteMediaClient loadMedia:[mediaInfoBuilder build] withOptions:options];
SRGMedia *media = [mediaComposition mediaForSubdivision:mainChapter];
- [[AnalyticsHiddenEventObjC googleGastWithUrn:media.URN] send];
+ [[AnalyticsEventObjC googleGastWithUrn:media.URN] send];
[NSNotificationCenter.defaultCenter postNotificationName:GoogleCastPlaybackDidStartNotification
object:nil
userInfo:@{ GoogleCastMediaKey : media }];
@@ -229,13 +229,13 @@ - (void)applicationDidBecomeActive:(NSNotification *)notification
{
UIViewController *topViewController = UIApplication.sharedApplication.mainTopViewController;
if ([topViewController isKindOfClass:GCKUIExpandedMediaControlsViewController.class]) {
- [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitlePlayer levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
+ [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitlePlayer type:AnalyticsPageTypeDetail levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
}
else if ([topViewController isKindOfClass:UINavigationController.class]) {
UINavigationController *navigationTopViewController = (UINavigationController *)topViewController;
UIViewController *rootViewController = navigationTopViewController.viewControllers.firstObject;
if ([rootViewController isKindOfClass:NSClassFromString(@"GCKUIDeviceConnectionViewController")]) {
- [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitleDevices levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
+ [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitleDevices type:AnalyticsPageTypeOverview levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
}
}
}
@@ -289,7 +289,7 @@ - (id)GCKUICastButton_GoogleCast_swizzled_initWithCoder:(NSCoder *)decoder
- (void)openGoogleCastDeviceSelection:(id)sender
{
- [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitleDevices levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
+ [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitleDevices type:AnalyticsPageTypeOverview levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
}
@end
diff --git a/Application/Sources/Helpers/PushService.m b/Application/Sources/Helpers/PushService.m
index 771bfa6e0..3870b1e2e 100755
--- a/Application/Sources/Helpers/PushService.m
+++ b/Application/Sources/Helpers/PushService.m
@@ -290,7 +290,7 @@ - (void)receivedNotificationResponse:(UNNotificationResponse *)notificationRespo
NSInteger startTime = [userInfo[@"startTime"] integerValue];
SceneDelegate *sceneDelegate = UIApplication.sharedApplication.mainSceneDelegate;
[sceneDelegate openMediaWithURN:mediaURN startTime:startTime channelUid:channelUid fromPushNotification:YES completionBlock:^{
- [[AnalyticsHiddenEventObjC notificationWithAction:AnalyticsNotificationActionPlayMedia
+ [[AnalyticsEventObjC notificationWithAction:AnalyticsNotificationActionPlayMedia
from:AnalyticsNotificationFromOperatingSystem
uid:mediaURN
overrideSource:userInfo[@"show"]
@@ -302,7 +302,7 @@ - (void)receivedNotificationResponse:(UNNotificationResponse *)notificationRespo
NSString *showURN = userInfo[@"show"];
SceneDelegate *sceneDelegate = UIApplication.sharedApplication.mainSceneDelegate;
[sceneDelegate openShowWithURN:showURN channelUid:channelUid fromPushNotification:YES completionBlock:^{
- [[AnalyticsHiddenEventObjC notificationWithAction:AnalyticsNotificationActionDisplayShow
+ [[AnalyticsEventObjC notificationWithAction:AnalyticsNotificationActionDisplayShow
from:AnalyticsNotificationFromOperatingSystem
uid:showURN
overrideSource:nil
@@ -311,7 +311,7 @@ - (void)receivedNotificationResponse:(UNNotificationResponse *)notificationRespo
}];
}
else {
- [[AnalyticsHiddenEventObjC notificationWithAction:AnalyticsNotificationActionAlert
+ [[AnalyticsEventObjC notificationWithAction:AnalyticsNotificationActionAlert
from:AnalyticsNotificationFromOperatingSystem
uid:notificationContent.body
overrideSource:nil
diff --git a/Application/Sources/Helpers/SharingItem.m b/Application/Sources/Helpers/SharingItem.m
index 8587a04fa..f7c8fd778 100755
--- a/Application/Sources/Helpers/SharingItem.m
+++ b/Application/Sources/Helpers/SharingItem.m
@@ -160,7 +160,7 @@ - (instancetype)initWithSharingItem:(SharingItem *)sharingItem
return;
}
- [[AnalyticsHiddenEventObjC sharingWithAction:sharingItem.analyticsAction
+ [[AnalyticsEventObjC sharingWithAction:sharingItem.analyticsAction
uid:sharingItem.analyticsUid
mediaContentType:sharingItem.mediaContentType
source:SharingItemSourceFrom(sharingItemFrom)
diff --git a/Application/Sources/MiniPlayer/GoogleCastMiniPlayerView.m b/Application/Sources/MiniPlayer/GoogleCastMiniPlayerView.m
index e1429be95..48ec752ed 100755
--- a/Application/Sources/MiniPlayer/GoogleCastMiniPlayerView.m
+++ b/Application/Sources/MiniPlayer/GoogleCastMiniPlayerView.m
@@ -160,11 +160,11 @@ - (void)openFullScreenPlayer:(UIGestureRecognizer *)gestureRecognizer
mediaControlsViewController.modalPresentationStyle = UIModalPresentationFullScreen;
UIViewController *topViewController = UIApplication.sharedApplication.mainTopViewController;
[topViewController presentViewController:mediaControlsViewController animated:YES completion:nil];
- [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitlePlayer levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
+ [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitlePlayer type:AnalyticsPageTypeDetail levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
}
else {
[[GCKCastContext sharedInstance] presentCastDialog];
- [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitleDevices levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
+ [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:AnalyticsPageTitleDevices type:AnalyticsPageTypeOverview levels:@[ AnalyticsPageLevelPlay, AnalyticsPageLevelGoogleCast ]];
}
}
diff --git a/Application/Sources/MiniPlayer/PlayMiniPlayerView.m b/Application/Sources/MiniPlayer/PlayMiniPlayerView.m
index 41444f9f6..9f506d74b 100755
--- a/Application/Sources/MiniPlayer/PlayMiniPlayerView.m
+++ b/Application/Sources/MiniPlayer/PlayMiniPlayerView.m
@@ -379,11 +379,7 @@ - (void)playbackButton:(SRGPlaybackButton *)playbackButton didPressInState:(SRGP
else {
controller = [[SRGLetterboxController alloc] init];
ApplicationConfigurationApplyControllerSettings(controller);
- [controller prepareToPlayMedia:media atPosition:position withPreferredSettings:ApplicationSettingPlaybackSettings()completionHandler:^{
- if (![UserConsentHelper isShowingBanner]) {
- [controller play];
- }
- }];
+ [controller playMedia:media atPosition:position withPreferredSettings:ApplicationSettingPlaybackSettings()];
[SRGLetterboxService.sharedService enableWithController:controller pictureInPictureDelegate:nil];
}
diff --git a/Application/Sources/Onboarding/OnboardingViewController.swift b/Application/Sources/Onboarding/OnboardingViewController.swift
index 74c2cb8d5..971b25c92 100755
--- a/Application/Sources/Onboarding/OnboardingViewController.swift
+++ b/Application/Sources/Onboarding/OnboardingViewController.swift
@@ -182,6 +182,10 @@ extension OnboardingViewController: SRGAnalyticsViewTracking {
return onboarding.title
}
+ var srg_pageViewType: String {
+ return AnalyticsPageType.help.rawValue
+ }
+
var srg_pageViewLevels: [String]? {
return [AnalyticsPageLevel.play.rawValue, AnalyticsPageLevel.application.rawValue, AnalyticsPageLevel.feature.rawValue]
}
diff --git a/Application/Sources/Player/MediaPlayerViewController.m b/Application/Sources/Player/MediaPlayerViewController.m
index 73821cd42..0b899f529 100755
--- a/Application/Sources/Player/MediaPlayerViewController.m
+++ b/Application/Sources/Player/MediaPlayerViewController.m
@@ -311,7 +311,7 @@ - (void)setLetterboxController:(SRGLetterboxController *)letterboxController
[self updateSharingStatus];
if (letterboxController.continuousPlaybackUpcomingMedia) {
- [[AnalyticsHiddenEventObjC continuousPlaybackWithAction:AnalyticsContiniousPlaybackActionDisplay
+ [[AnalyticsEventObjC continuousPlaybackWithAction:AnalyticsContiniousPlaybackActionDisplay
mediaUrn:letterboxController.continuousPlaybackUpcomingMedia.URN]
send];
}
@@ -423,9 +423,7 @@ - (void)viewDidLoad
if (self.originalLetterboxController) {
// Always resume playback if the original controller was not playing
- if (![UserConsentHelper isShowingBanner]) {
- [self.letterboxController play];
- }
+ [self.letterboxController play];
}
else {
self.letterboxController.contentURLOverridingBlock = ^(NSString *URN) {
@@ -434,18 +432,10 @@ - (void)viewDidLoad
};
if (self.originalMedia) {
- [self.letterboxController prepareToPlayMedia:self.originalMedia atPosition:self.originalPosition withPreferredSettings:ApplicationSettingPlaybackSettings() completionHandler:^{
- if (![UserConsentHelper isShowingBanner]) {
- [self.letterboxController play];
- }
- }];
+ [self.letterboxController playMedia:self.originalMedia atPosition:self.originalPosition withPreferredSettings:ApplicationSettingPlaybackSettings()];
}
else {
- [self.letterboxController prepareToPlayURN:self.originalURN atPosition:self.originalPosition withPreferredSettings:ApplicationSettingPlaybackSettings() completionHandler:^{
- if (![UserConsentHelper isShowingBanner]) {
- [self.letterboxController play];
- }
- }];
+ [self.letterboxController playURN:self.originalURN atPosition:self.originalPosition withPreferredSettings:ApplicationSettingPlaybackSettings()];
}
}
@@ -554,7 +544,7 @@ - (void)viewDidDisappear:(BOOL)animated
[super viewDidDisappear:animated];
if (self.letterboxController.continuousPlaybackUpcomingMedia) {
- [[AnalyticsHiddenEventObjC continuousPlaybackWithAction:AnalyticsContiniousPlaybackActionCancel
+ [[AnalyticsEventObjC continuousPlaybackWithAction:AnalyticsContiniousPlaybackActionCancel
mediaUrn:self.letterboxController.continuousPlaybackUpcomingMedia.URN]
send];
}
@@ -1503,6 +1493,11 @@ - (NSString *)srg_pageViewTitle
return AnalyticsPageTitlePlayer;
}
+- (NSString *)srg_pageViewType
+{
+ return AnalyticsPageTypeDetail;
+}
+
- (NSArray *)srg_pageViewLevels
{
return @[ AnalyticsPageLevelPlay ];
@@ -1658,7 +1653,7 @@ - (void)letterboxView:(SRGLetterboxView *)letterboxView didSelectAudioLanguageCo
- (void)letterboxView:(SRGLetterboxView *)letterboxView didEngageInContinuousPlaybackWithUpcomingMedia:(SRGMedia *)upcomingMedia
{
- [[AnalyticsHiddenEventObjC continuousPlaybackWithAction:AnalyticsContiniousPlaybackActionPlay
+ [[AnalyticsEventObjC continuousPlaybackWithAction:AnalyticsContiniousPlaybackActionPlay
mediaUrn:upcomingMedia.URN]
send];
}
@@ -1681,7 +1676,7 @@ - (void)letterboxView:(SRGLetterboxView *)letterboxView didCancelContinuousPlayb
[self presentViewController:alertController animated:YES completion:nil];
}, @"DisableAutoplayAsked");
- [[AnalyticsHiddenEventObjC continuousPlaybackWithAction:AnalyticsContiniousPlaybackActionCancel
+ [[AnalyticsEventObjC continuousPlaybackWithAction:AnalyticsContiniousPlaybackActionCancel
mediaUrn:upcomingMedia.URN]
send];
}
@@ -1725,7 +1720,7 @@ - (void)letterboxRestoreUserInterfaceForPictureInPictureWithCompletionHandler:(v
- (void)letterboxDidStartPictureInPicture
{
- [[AnalyticsHiddenEventObjC pictureInPictureWithUrn:self.letterboxController.fullLengthMedia.URN] send];
+ [[AnalyticsEventObjC pictureInPictureWithUrn:self.letterboxController.fullLengthMedia.URN] send];
}
- (void)letterboxDidStopPlaybackFromPictureInPicture
@@ -1955,7 +1950,7 @@ - (IBAction)toggleWatchLater:(id)sender
WatchLaterToggleMedia(mainChapterMedia, ^(BOOL added, NSError * _Nullable error) {
if (! error) {
AnalyticsListAction action = added ? AnalyticsListActionAdd : AnalyticsListActionRemove;
- [[AnalyticsHiddenEventObjC watchLaterWithAction:action source:AnalyticsListSourceButton urn:mainChapterMedia.URN] send];
+ [[AnalyticsEventObjC watchLaterWithAction:action source:AnalyticsListSourceButton urn:mainChapterMedia.URN] send];
[Banner showWatchLaterAdded:added forItemWithName:mainChapterMedia.title];
}
@@ -1982,7 +1977,7 @@ - (IBAction)toggleDownload:(id)sender
[self updateDownloadStatus];
AnalyticsListAction action = download ? AnalyticsListActionAdd : AnalyticsListActionRemove;
- [[AnalyticsHiddenEventObjC downloadWithAction:action source:AnalyticsListSourceButton urn:media.URN] send];
+ [[AnalyticsEventObjC downloadWithAction:action source:AnalyticsListSourceButton urn:media.URN] send];
};
if (! download) {
@@ -2138,7 +2133,7 @@ - (IBAction)toggleFavorite:(id)sender
BOOL isFavorite = FavoritesContainsShow(show);
AnalyticsListAction action = isFavorite ? AnalyticsListActionAdd : AnalyticsListActionRemove;
- [[AnalyticsHiddenEventObjC favoriteWithAction:action source:AnalyticsListSourceButton urn:show.URN] send];
+ [[AnalyticsEventObjC favoriteWithAction:action source:AnalyticsListSourceButton urn:show.URN] send];
[Banner showFavorite:isFavorite forItemWithName:show.title];
}
diff --git a/Application/Sources/Player/MediaPreviewViewController.m b/Application/Sources/Player/MediaPreviewViewController.m
index 54d4dfc95..0385221fe 100755
--- a/Application/Sources/Player/MediaPreviewViewController.m
+++ b/Application/Sources/Player/MediaPreviewViewController.m
@@ -107,11 +107,7 @@ - (void)viewDidLoad
};
ApplicationConfigurationApplyControllerSettings(self.letterboxController);
- [self.letterboxController prepareToPlayMedia:self.media atPosition:HistoryResumePlaybackPositionForMedia(self.media) withPreferredSettings:ApplicationSettingPlaybackSettings() completionHandler:^{
- if (![UserConsentHelper isShowingBanner]) {
- [self.letterboxController play];
- }
- }];
+ [self.letterboxController playMedia:self.media atPosition:HistoryResumePlaybackPositionForMedia(self.media) withPreferredSettings:ApplicationSettingPlaybackSettings()];
[self.letterboxView setUserInterfaceHidden:YES animated:NO togglable:NO];
[self.letterboxView setTimelineAlwaysHidden:YES animated:NO];
@@ -161,9 +157,7 @@ - (void)viewDidDisappear:(BOOL)animated
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (self.shouldRestoreServicePlayback) {
[[AVAudioSession sharedInstance] setCategory:self.previousAudioSessionCategory error:nil];
- if (![UserConsentHelper isShowingBanner]) {
- [SRGLetterboxService.sharedService.controller play];
- }
+ [SRGLetterboxService.sharedService.controller play];
}
});
}
@@ -225,6 +219,11 @@ - (NSString *)srg_pageViewTitle
return AnalyticsPageTitlePlayer;
}
+- (NSString *)srg_pageViewType
+{
+ return AnalyticsPageTypeDetail;
+}
+
- (NSArray *)srg_pageViewLevels
{
return @[ AnalyticsPageLevelPlay, AnalyticsPageLevelPreview ];
diff --git a/Application/Sources/Player/SongsViewController.m b/Application/Sources/Player/SongsViewController.m
index 4c583ca57..eaab8c25c 100644
--- a/Application/Sources/Player/SongsViewController.m
+++ b/Application/Sources/Player/SongsViewController.m
@@ -290,9 +290,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
SRGSong *song = self.items[indexPath.row];
NSDate *seekDate = [song.date dateByAddingTimeInterval:0.3];
[self.letterboxController seekToPosition:[SRGPosition positionAtDate:seekDate] withCompletionHandler:^(BOOL finished) {
- if (![UserConsentHelper isShowingBanner]) {
- [self.letterboxController play];
- }
+ [self.letterboxController play];
}];
}
diff --git a/Application/Sources/Profile/ProfileAccountHeaderView.swift b/Application/Sources/Profile/ProfileAccountHeaderView.swift
index c6ad2fdb7..54b2c76de 100644
--- a/Application/Sources/Profile/ProfileAccountHeaderView.swift
+++ b/Application/Sources/Profile/ProfileAccountHeaderView.swift
@@ -41,7 +41,7 @@ struct ProfileAccountHeaderView: View {
} label: {
HStack(spacing: spacing) {
ZStack(alignment: .topTrailing) {
- Image(decorative: model.data.decorativeName)
+ Image(model.data.icon)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: iconHeight)
@@ -83,7 +83,7 @@ struct ProfileAccountHeaderView: View {
.srgFont(.body)
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading)
- Image(decorative: "chevron")
+ Image(.chevron)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 16)
diff --git a/Application/Sources/Profile/ProfileAccountHeaderViewModel.swift b/Application/Sources/Profile/ProfileAccountHeaderViewModel.swift
index fa76ced53..aa2c2aadb 100644
--- a/Application/Sources/Profile/ProfileAccountHeaderViewModel.swift
+++ b/Application/Sources/Profile/ProfileAccountHeaderViewModel.swift
@@ -20,7 +20,7 @@ final class ProfileAccountHeaderViewModel: ObservableObject {
} else {
let lastLoggedInEmailAddress = UserDefaults.standard.string(forKey: PlaySRGSettingLastLoggedInEmailAddress)
if identityService.login(withEmailAddress: lastLoggedInEmailAddress) {
- AnalyticsHiddenEvent.identity(action: .displayLogin).send()
+ AnalyticsEvent.identity(action: .displayLogin).send()
}
}
}
@@ -71,8 +71,8 @@ extension ProfileAccountHeaderViewModel {
let isLoggedIn: Bool
let account: SRGAccount?
- var decorativeName: String {
- return isLoggedIn ? "account_logged_in_icon" : "account_logged_out_icon"
+ var icon: ImageResource {
+ return isLoggedIn ? .accountLoggedInIcon : .accountLoggedOutIcon
}
var accountDescription: String? {
diff --git a/Application/Sources/Profile/ProfileCell.swift b/Application/Sources/Profile/ProfileCell.swift
index c3ef4273c..b583ef871 100644
--- a/Application/Sources/Profile/ProfileCell.swift
+++ b/Application/Sources/Profile/ProfileCell.swift
@@ -70,7 +70,7 @@ struct ProfileCell: View {
.srgFont(.subtitle1)
}
if !model.isModalPresentation {
- Image(decorative: "chevron")
+ Image(.chevron)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 16)
diff --git a/Application/Sources/Profile/ProfileHelp.swift b/Application/Sources/Profile/ProfileHelp.swift
index fe6ccb462..f0df3371f 100644
--- a/Application/Sources/Profile/ProfileHelp.swift
+++ b/Application/Sources/Profile/ProfileHelp.swift
@@ -13,7 +13,7 @@ import SwiftUI
guard let url = ApplicationConfiguration.shared.userSuggestionUrlWithParameters else { return false }
return showSafariViewController(url: url) {
- AnalyticsHiddenEvent.openHelp(action: .feedbackApp).send()
+ AnalyticsEvent.openHelp(action: .feedbackApp).send()
}
}
@@ -21,7 +21,7 @@ import SwiftUI
guard let url = ApplicationConfiguration.shared.faqURL else { return false }
return showSafariViewController(url: url) {
- AnalyticsHiddenEvent.openHelp(action: .faq).send()
+ AnalyticsEvent.openHelp(action: .faq).send()
}
}
@@ -32,7 +32,7 @@ import SwiftUI
productViewController.loadProduct(withParameters: [SKStoreProductParameterITunesItemIdentifier: ApplicationConfiguration.shared.appStoreProductIdentifier])
tabBarController.play_top.present(productViewController, animated: true) {
- AnalyticsHiddenEvent.openHelp(action: .evaluateApp).send()
+ AnalyticsEvent.openHelp(action: .evaluateApp).send()
}
return true
}
@@ -43,12 +43,12 @@ import SwiftUI
if MailComposeView.canSendMail() {
tabBarController.play_top.present(supportEmailMailComposeViewController(supportEmailAddress), animated: true) {
- AnalyticsHiddenEvent.openHelp(action: .technicalIssue).send()
+ AnalyticsEvent.openHelp(action: .technicalIssue).send()
}
}
else {
tabBarController.play_top.present(supporEmailAlertController(supportEmailAddress), animated: true) {
- AnalyticsHiddenEvent.openHelp(action: .technicalIssue).send()
+ AnalyticsEvent.openHelp(action: .technicalIssue).send()
}
}
return true
diff --git a/Application/Sources/Profile/ProfileViewController.m b/Application/Sources/Profile/ProfileViewController.m
index e30905c97..fa5ac9fca 100755
--- a/Application/Sources/Profile/ProfileViewController.m
+++ b/Application/Sources/Profile/ProfileViewController.m
@@ -372,6 +372,11 @@ - (NSString *)srg_pageViewTitle
return AnalyticsPageTitleHome;
}
+- (NSString *)srg_pageViewType
+{
+ return AnalyticsPageTypeLandingPage;
+}
+
- (NSArray *)srg_pageViewLevels
{
return @[ AnalyticsPageLevelPlay, AnalyticsPageLevelUser ];
diff --git a/Application/Sources/ProgramGuide/ProgramCell.swift b/Application/Sources/ProgramGuide/ProgramCell.swift
index 35d96d2a2..bafa5758d 100644
--- a/Application/Sources/ProgramGuide/ProgramCell.swift
+++ b/Application/Sources/ProgramGuide/ProgramCell.swift
@@ -127,7 +127,7 @@ struct ProgramCell: View {
var body: some View {
HStack(spacing: 10) {
if !compact && model.canPlay {
- Image(decorative: "play_circle")
+ Image(.playCircle)
.foregroundColor(.srgGrayC7)
.frame(height: canPlayHeight)
}
diff --git a/Application/Sources/ProgramGuide/ProgramGuideHeaderView.swift b/Application/Sources/ProgramGuide/ProgramGuideHeaderView.swift
index a089a0e6e..51bbdfb67 100644
--- a/Application/Sources/ProgramGuide/ProgramGuideHeaderView.swift
+++ b/Application/Sources/ProgramGuide/ProgramGuideHeaderView.swift
@@ -89,7 +89,7 @@ struct ProgramGuideHeaderView: View {
var body: some View {
HStack(spacing: constant(iOS: 10, tvOS: 40)) {
#if os(iOS)
- ExpandingButton(icon: "calendar", label: NSLocalizedString("Calendar", comment: "Calendar button in program guide")) {
+ ExpandingButton(icon: .calendar, label: NSLocalizedString("Calendar", comment: "Calendar button in program guide")) {
firstResponder.sendAction(#selector(ProgramGuideHeaderViewActions.openCalendar))
}
#endif
@@ -115,7 +115,7 @@ struct ProgramGuideHeaderView: View {
var body: some View {
HStack(spacing: constant(iOS: 10, tvOS: 40)) {
- ExpandingButton(icon: "chevron_previous", accessibilityLabel: PlaySRGAccessibilityLocalizedString("Previous day", comment: "Previous day button label in program guide")) {
+ ExpandingButton(icon: .chevronPrevious, accessibilityLabel: PlaySRGAccessibilityLocalizedString("Previous day", comment: "Previous day button label in program guide")) {
AnalyticsClickEvent.tvGuidePreviousDay().send()
model.switchToPreviousDay()
}
@@ -129,7 +129,7 @@ struct ProgramGuideHeaderView: View {
DateView(model: model)
#endif
- ExpandingButton(icon: "chevron_next", accessibilityLabel: PlaySRGAccessibilityLocalizedString("Next day", comment: "Next day button label in program guide")) {
+ ExpandingButton(icon: .chevronNext, accessibilityLabel: PlaySRGAccessibilityLocalizedString("Next day", comment: "Next day button label in program guide")) {
AnalyticsClickEvent.tvGuideNextDay().send()
model.switchToNextDay()
}
diff --git a/Application/Sources/ProgramGuide/ProgramGuideViewController.swift b/Application/Sources/ProgramGuide/ProgramGuideViewController.swift
index ce2b5360d..de8588220 100644
--- a/Application/Sources/ProgramGuide/ProgramGuideViewController.swift
+++ b/Application/Sources/ProgramGuide/ProgramGuideViewController.swift
@@ -97,7 +97,7 @@ final class ProgramGuideViewController: UIViewController {
private func updateNavigationBar() {
let isGrid = (layout == .grid)
let layoutBarButtonItem = UIBarButtonItem(
- image: UIImage(named: isGrid ? "layout_grid_on" : "layout_list_on"),
+ image: UIImage(resource: isGrid ? .layoutGridOn : .layoutListOn),
style: .plain,
target: self,
action: #selector(toggleLayout(_:))
@@ -302,6 +302,10 @@ extension ProgramGuideViewController: SRGAnalyticsViewTracking {
return AnalyticsPageTitle.programGuide.rawValue
}
+ var srg_pageViewType: String {
+ return AnalyticsPageType.overview.rawValue
+ }
+
var srg_pageViewLevels: [String]? {
return [AnalyticsPageLevel.play.rawValue, AnalyticsPageLevel.video.rawValue]
}
diff --git a/Application/Sources/ProgramGuide/ProgramPreviewModel.swift b/Application/Sources/ProgramGuide/ProgramPreviewModel.swift
index a047c6351..3f0432490 100644
--- a/Application/Sources/ProgramGuide/ProgramPreviewModel.swift
+++ b/Application/Sources/ProgramGuide/ProgramPreviewModel.swift
@@ -69,7 +69,7 @@ final class ProgramPreviewModel: ObservableObject {
}
var imageUrl: URL? {
- return data?.programGuideImageUrl(size: .medium)
+ return data?.programGuideImageUrl(size: .large)
}
init() {
diff --git a/Application/Sources/ProgramGuide/ProgramView.swift b/Application/Sources/ProgramGuide/ProgramView.swift
index 6c882e0f7..b6f69f7da 100644
--- a/Application/Sources/ProgramGuide/ProgramView.swift
+++ b/Application/Sources/ProgramGuide/ProgramView.swift
@@ -71,7 +71,7 @@ struct ProgramView: View {
ZStack {
VisualView(model: model)
Color(white: 0, opacity: 0.2)
- Image(decorative: "play")
+ Image(ImageResource.play)
.foregroundColor(.white)
}
}
diff --git a/Application/Sources/ProgramGuide/ProgramViewModel.swift b/Application/Sources/ProgramGuide/ProgramViewModel.swift
index 0359ce59f..5e7d98530 100644
--- a/Application/Sources/ProgramGuide/ProgramViewModel.swift
+++ b/Application/Sources/ProgramGuide/ProgramViewModel.swift
@@ -216,7 +216,7 @@ final class ProgramViewModel: ObservableObject {
let data = self.data
let analyticsClickEvent = data != nil ? AnalyticsClickEvent.tvGuidePlayMedia(media: media, programIsLive: true, channel: data!.channel) : nil
return ButtonProperties(
- icon: "start_over",
+ icon: .startOver,
label: NSLocalizedString("Watch from start", comment: "Button to watch some program from the start"),
action: {
guard let tabBarController = UIApplication.shared.mainTabBarController else { return }
@@ -258,7 +258,7 @@ final class ProgramViewModel: ObservableObject {
guard error == nil else { return }
let action = added ? .add : .remove as AnalyticsListAction
- AnalyticsHiddenEvent.watchLater(action: action, source: .button, urn: media.urn).send()
+ AnalyticsEvent.watchLater(action: action, source: .button, urn: media.urn).send()
self.mediaData = MediaData(media: media, watchLaterAllowedAction: added ? .remove : .add, progress: self.mediaData.progress)
}
@@ -269,20 +269,20 @@ final class ProgramViewModel: ObservableObject {
switch media.mediaType {
case .audio:
return ButtonProperties(
- icon: "watch_later",
+ icon: .watchLater,
label: NSLocalizedString("Listen later", comment: "Button label in program detail view to add an audio to the later list"),
action: toggleWatchLater
)
default:
return ButtonProperties(
- icon: "watch_later",
+ icon: .watchLater,
label: NSLocalizedString("Watch later", comment: "Button label in program detail view to add a video to the later list"),
action: toggleWatchLater
)
}
case .remove:
return ButtonProperties(
- icon: "watch_later_full",
+ icon: .watchLaterFull,
label: NSLocalizedString("Later", comment: "Watch later or listen later button label in program detail view when a media is in the later list"),
action: toggleWatchLater
)
@@ -293,7 +293,7 @@ final class ProgramViewModel: ObservableObject {
var calendarButtonProperties: ButtonProperties? {
return ButtonProperties(
- icon: "calendar",
+ icon: .calendar,
label: NSLocalizedString("Add to Calendar", comment: "Button to add an event to Calendar application"),
action: {
guard let program = self.program,
@@ -476,7 +476,7 @@ extension ProgramViewModel {
/// Common button properties
struct ButtonProperties {
- let icon: String
+ let icon: ImageResource
let label: String
let action: () -> Void
}
@@ -500,7 +500,7 @@ private final class EventEditViewDelegateObject: NSObject, EKEventEditViewDelega
Banner.calendarEventAdded(withTitle: title)
if let channel = self.channel {
- AnalyticsHiddenEvent.calendarEventAdd(channel: channel).send()
+ AnalyticsEvent.calendarEventAdd(channel: channel).send()
}
}
}
diff --git a/Application/Sources/Search/SearchSettingsView.swift b/Application/Sources/Search/SearchSettingsView.swift
index e8e001cb0..313a8dd90 100644
--- a/Application/Sources/Search/SearchSettingsView.swift
+++ b/Application/Sources/Search/SearchSettingsView.swift
@@ -114,7 +114,7 @@ struct SearchSettingsView: View {
.srgFont(.body)
.navigationBarTitleDisplayMode(isVoiceOverRunning ? .inline : .large)
.navigationTitle(NSLocalizedString("Filters", comment: "Search filters page title"))
- .tracked(withTitle: analyticsPageTitle, levels: analyticsPageLevels)
+ .tracked(withTitle: analyticsPageTitle, type: AnalyticsPageType.navigationPage.rawValue, levels: analyticsPageLevels)
.onAppear {
model.query = query
model.settings = settings
diff --git a/Application/Sources/Search/SearchViewController.swift b/Application/Sources/Search/SearchViewController.swift
index f8d9feb8f..4e70e075a 100644
--- a/Application/Sources/Search/SearchViewController.swift
+++ b/Application/Sources/Search/SearchViewController.swift
@@ -248,7 +248,7 @@ final class SearchViewController: UIViewController {
}
if let filtersButton = filtersBarButtonItem?.customView as? UIButton {
- let image = !SearchViewModel.areDefaultSettings(settings) ? UIImage(named: "filter_on") : UIImage(named: "filter_off")
+ let image = !SearchViewModel.areDefaultSettings(settings) ? UIImage(resource: .filterOn) : UIImage(resource: .filterOff)
filtersButton.setImage(image, for: .normal)
}
}
@@ -387,6 +387,10 @@ extension SearchViewController: SRGAnalyticsViewTracking {
return AnalyticsPageTitle.home.rawValue
}
+ var srg_pageViewType: String {
+ return AnalyticsPageType.navigationPage.rawValue
+ }
+
var srg_pageViewLevels: [String]? {
return [AnalyticsPageLevel.play.rawValue, AnalyticsPageLevel.search.rawValue]
}
diff --git a/Application/Sources/Settings/FeaturesView.swift b/Application/Sources/Settings/FeaturesView.swift
index beecd4e1e..ac115ed92 100644
--- a/Application/Sources/Settings/FeaturesView.swift
+++ b/Application/Sources/Settings/FeaturesView.swift
@@ -29,7 +29,7 @@ struct FeaturesView: View {
OnboardingView(onboarding: onboarding)
.ignoresSafeArea()
}
- .tracked(withTitle: analyticsPageTitle, levels: analyticsPageLevels)
+ .tracked(withTitle: analyticsPageTitle, type: AnalyticsPageType.help.rawValue, levels: analyticsPageLevels)
}
private struct OnboardingCell: View {
diff --git a/Application/Sources/Settings/SettingsView.swift b/Application/Sources/Settings/SettingsView.swift
index 56a1c4eee..a894d7b90 100644
--- a/Application/Sources/Settings/SettingsView.swift
+++ b/Application/Sources/Settings/SettingsView.swift
@@ -52,6 +52,9 @@ struct SettingsView: View {
#endif
#if os(iOS) && (DEBUG || APPCENTER)
DeveloperSection()
+#endif
+#if DEBUG || NIGHTLY || BETA
+ BottomAdditionalInformationSection(model: model)
#endif
}
#if os(tvOS)
@@ -62,7 +65,7 @@ struct SettingsView: View {
.navigationBarTitleDisplayMode(isVoiceOverRunning ? .inline : .large)
#endif
.navigationTitle(NSLocalizedString("Settings", comment: "Settings view title"))
- .tracked(withTitle: analyticsPageTitle, levels: analyticsPageLevels)
+ .tracked(withTitle: analyticsPageTitle, type: AnalyticsPageType.navigationPage.rawValue, levels: analyticsPageLevels)
}
#if os(tvOS)
@@ -77,7 +80,7 @@ struct SettingsView: View {
Button(action: navigateTo(applicationSectionInfo.applicationSection)) {
HStack(spacing: 16) {
if let imageName = applicationSectionInfo.imageName {
- Image(decorative: imageName)
+ Image(imageName)
}
Text(applicationSectionInfo.title)
}
@@ -436,7 +439,7 @@ struct SettingsView: View {
}
}
- private struct VersionCell: View {
+ fileprivate struct VersionCell: View {
@ObservedObject var model: SettingsViewModel
var body: some View {
@@ -791,6 +794,22 @@ struct SettingsView: View {
}
#endif
+ // MARK: Bottom additional information section
+
+#if DEBUG || NIGHTLY || BETA
+ private struct BottomAdditionalInformationSection: View {
+ @ObservedObject var model: SettingsViewModel
+
+ var body: some View {
+ PlaySection {
+ InformationSection.VersionCell(model: model)
+ } header: {
+ Text(NSLocalizedString("Information", comment: "Information section header"))
+ }
+ }
+ }
+#endif
+
// MARK: Presentation
/**
diff --git a/Application/Sources/Settings/SettingsViewModel.swift b/Application/Sources/Settings/SettingsViewModel.swift
index 203b57087..8c7986c28 100644
--- a/Application/Sources/Settings/SettingsViewModel.swift
+++ b/Application/Sources/Settings/SettingsViewModel.swift
@@ -105,9 +105,9 @@ final class SettingsViewModel: ObservableObject {
func login() {
if let opened = SRGIdentityService.current?.login(withEmailAddress: nil), opened {
- SRGAnalyticsTracker.shared.trackPageView(withTitle: AnalyticsPageTitle.login.rawValue, levels: [AnalyticsPageLevel.play.rawValue, AnalyticsPageLevel.user.rawValue])
+ SRGAnalyticsTracker.shared.trackPageView(withTitle: AnalyticsPageTitle.login.rawValue, type: AnalyticsPageType.navigationPage.rawValue, levels: [AnalyticsPageLevel.play.rawValue, AnalyticsPageLevel.user.rawValue])
- AnalyticsHiddenEvent.identity(action: .displayLogin).send()
+ AnalyticsEvent.identity(action: .displayLogin).send()
}
}
@@ -172,7 +172,7 @@ final class SettingsViewModel: ObservableObject {
let headerText = String(format: NSLocalizedString("Please contact us at %@", comment: "Apple TV header when displayed support information"), supportEmailAdress)
let text = String(format: "%@\n\n%@", headerText, SupportInformation.generate())
navigateToText(text)
- AnalyticsHiddenEvent.openHelp(action: .technicalIssue).send()
+ AnalyticsEvent.openHelp(action: .technicalIssue).send()
}
}
@@ -205,20 +205,20 @@ final class SettingsViewModel: ObservableObject {
func removeFavorites() {
FavoritesRemoveShows(nil)
- AnalyticsHiddenEvent.favorite(action: .remove, source: .button, urn: nil).send()
+ AnalyticsEvent.favorite(action: .remove, source: .button, urn: nil).send()
}
func removeHistory() {
SRGUserData.current?.history.discardHistoryEntries(withUids: nil, completionBlock: { error in
guard error == nil else { return }
- AnalyticsHiddenEvent.historyRemove(source: .button, urn: nil).send()
+ AnalyticsEvent.historyRemove(source: .button, urn: nil).send()
})
}
func removeWatchLaterItems() {
SRGUserData.current?.playlists.discardPlaylistEntries(withUids: nil, fromPlaylistWithUid: SRGPlaylistUid.watchLater.rawValue, completionBlock: { error in
guard error == nil else { return }
- AnalyticsHiddenEvent.watchLater(action: .remove, source: .button, urn: nil).send()
+ AnalyticsEvent.watchLater(action: .remove, source: .button, urn: nil).send()
})
}
diff --git a/Application/Sources/Settings/WhatsNewView.swift b/Application/Sources/Settings/WhatsNewView.swift
index e1b1fb51c..c0f701bb8 100644
--- a/Application/Sources/Settings/WhatsNewView.swift
+++ b/Application/Sources/Settings/WhatsNewView.swift
@@ -32,7 +32,7 @@ struct WhatsNewView: View {
.onChange(of: url) { newValue in
model.url = newValue
}
- .tracked(withTitle: analyticsPageTitle, levels: analyticsPageLevels)
+ .tracked(withTitle: analyticsPageTitle, type: AnalyticsPageType.help.rawValue, levels: analyticsPageLevels)
}
}
diff --git a/Application/Sources/UI/Helpers/ContextMenu.swift b/Application/Sources/UI/Helpers/ContextMenu.swift
index f27b2f533..9d452249a 100644
--- a/Application/Sources/UI/Helpers/ContextMenu.swift
+++ b/Application/Sources/UI/Helpers/ContextMenu.swift
@@ -126,7 +126,7 @@ extension ContextMenu {
}
func image(for action: WatchLaterAction) -> UIImage {
- return (action == .add) ? UIImage(named: "watch_later")! : UIImage(named: "watch_later_full")!
+ return (action == .add) ? UIImage(resource: .watchLater) : UIImage(resource: .watchLaterFull)
}
let action = WatchLaterAllowedActionForMedia(media)
@@ -138,7 +138,7 @@ extension ContextMenu {
guard error == nil else { return }
let action = added ? .add : .remove as AnalyticsListAction
- AnalyticsHiddenEvent.watchLater(action: action, source: .contextMenu, urn: media.urn).send()
+ AnalyticsEvent.watchLater(action: action, source: .contextMenu, urn: media.urn).send()
Banner.showWatchLaterAdded(added, forItemWithName: media.title)
}
@@ -154,12 +154,12 @@ extension ContextMenu {
guard HistoryContainsMedia(media) else { return nil }
let menuAction = UIAction(title: NSLocalizedString("Delete from history", comment: "Context menu action to delete a media from the history"),
- image: UIImage(named: "history")!) { _ in
+ image: UIImage(resource: .history)) { _ in
DispatchQueue.main.asyncAfter(deadline: .now() + Self.actionDelay) {
HistoryRemoveMedias([media]) { error in
guard error == nil else { return }
- AnalyticsHiddenEvent.historyRemove(source: .contextMenu, urn: media.urn).send()
+ AnalyticsEvent.historyRemove(source: .contextMenu, urn: media.urn).send()
}
}
}
@@ -180,7 +180,7 @@ extension ContextMenu {
}
func image(for download: Download?) -> UIImage {
- return download != nil ? UIImage(named: "download_remove")! : UIImage(named: "download")!
+ return download != nil ? UIImage(resource: .downloadRemove) : UIImage(resource: .download)
}
let download = Download(for: media)
@@ -194,7 +194,7 @@ extension ContextMenu {
}
let action = (download == nil) ? .add : .remove as AnalyticsListAction
- AnalyticsHiddenEvent.download(action: action, source: .contextMenu, urn: media.urn).send()
+ AnalyticsEvent.download(action: action, source: .contextMenu, urn: media.urn).send()
Banner.showDownload(download == nil, forItemWithName: media.title)
}
@@ -208,7 +208,7 @@ extension ContextMenu {
private static func sharingAction(for media: SRGMedia, in viewController: UIViewController) -> UIAction? {
guard let sharingItem = SharingItem(for: media, at: CMTime.zero) else { return nil }
return UIAction(title: NSLocalizedString("Share", comment: "Context menu action to share a media"),
- image: UIImage(named: "share")!) { _ in
+ image: UIImage(resource: .share)) { _ in
shareItem(sharingItem, in: viewController)
}
}
@@ -222,7 +222,7 @@ extension ContextMenu {
guard !show.isEqual(displayedShow) else { return nil }
}
return UIAction(title: NSLocalizedString("More episodes", comment: "Context menu action to open more episodes associated with a media"),
- image: UIImage(named: "episodes")) { _ in
+ image: UIImage(resource: .episodes)) { _ in
let showViewController = SectionViewController.showViewController(for: show)
navigationController.pushViewController(showViewController, animated: true)
}
@@ -263,7 +263,7 @@ extension ContextMenu {
}
func image(isFavorite: Bool) -> UIImage {
- return isFavorite ? UIImage(named: "favorite_full")! : UIImage(named: "favorite")!
+ return isFavorite ? UIImage(resource: .favoriteFull) : UIImage(resource: .favorite)
}
let isFavorite = FavoritesContainsShow(show)
@@ -272,7 +272,7 @@ extension ContextMenu {
FavoritesToggleShow(show)
let action = !isFavorite ? .add : .remove as AnalyticsListAction
- AnalyticsHiddenEvent.favorite(action: action, source: .contextMenu, urn: show.urn).send()
+ AnalyticsEvent.favorite(action: action, source: .contextMenu, urn: show.urn).send()
Banner.showFavorite(!isFavorite, forItemWithName: show.title)
}
@@ -286,7 +286,7 @@ extension ContextMenu {
private static func sharingAction(for show: SRGShow, in viewController: UIViewController) -> UIAction? {
guard let sharingItem = SharingItem(for: show) else { return nil }
return UIAction(title: NSLocalizedString("Share", comment: "Context menu action to share a show"),
- image: UIImage(named: "share")!) { _ in
+ image: UIImage(resource: .share)) { _ in
shareItem(sharingItem, in: viewController)
}
}
diff --git a/Application/Sources/UI/Views/Badges.swift b/Application/Sources/UI/Views/Badges.swift
index 27fc0781a..0d972cc67 100644
--- a/Application/Sources/UI/Views/Badges.swift
+++ b/Application/Sources/UI/Views/Badges.swift
@@ -58,7 +58,7 @@ struct DurationBadge: View {
/// Behavior: h-hug, v-hug
struct SubtitlesBadge: View {
var body: some View {
- Image(decorative: "subtitles")
+ Image(.subtitles)
.resizable()
.frame(width: BadgeMetrics.length, height: BadgeMetrics.length)
.cornerRadius(BadgeMetrics.cornerRadius)
@@ -69,7 +69,7 @@ struct SubtitlesBadge: View {
/// Behavior: h-hug, v-hug
struct AudioDescriptionBadge: View {
var body: some View {
- Image(decorative: "audio_description")
+ Image(.audioDescription)
.resizable()
.frame(width: BadgeMetrics.length, height: BadgeMetrics.length)
.cornerRadius(BadgeMetrics.cornerRadius)
@@ -80,7 +80,7 @@ struct AudioDescriptionBadge: View {
/// Behavior: h-hug, v-hug
struct SignLanguageBadge: View {
var body: some View {
- Image(decorative: "sign_language")
+ Image(.signLanguage)
.resizable()
.frame(width: BadgeMetrics.length, height: BadgeMetrics.length)
.cornerRadius(BadgeMetrics.cornerRadius)
@@ -91,7 +91,7 @@ struct SignLanguageBadge: View {
/// Behavior: h-hug, v-hug
struct MultiAudioBadge: View {
var body: some View {
- Image(decorative: "multiaudio")
+ Image(.multiaudio)
.resizable()
.frame(width: BadgeMetrics.length, height: BadgeMetrics.length)
.cornerRadius(BadgeMetrics.cornerRadius)
@@ -102,7 +102,7 @@ struct MultiAudioBadge: View {
/// Behavior: h-hug, v-hug
struct DolbyDigitalBadge: View {
var body: some View {
- Image(decorative: "dolby_digital")
+ Image(.dolbyDigital)
.resizable()
.frame(width: BadgeMetrics.length, height: BadgeMetrics.length)
.cornerRadius(BadgeMetrics.cornerRadius)
@@ -113,7 +113,7 @@ struct DolbyDigitalBadge: View {
/// Behavior: h-hug, v-hug
struct ThreeSixtyBadge: View {
var body: some View {
- Image(decorative: "360_media")
+ Image(._360Media)
.resizable()
.frame(width: BadgeMetrics.length, height: BadgeMetrics.length)
.accessibilityElement(label: PlaySRGAccessibilityLocalizedString("360-degree content", comment: "Accessibility label for the 360 badge"))
diff --git a/Application/Sources/UI/Views/DownloadCell.swift b/Application/Sources/UI/Views/DownloadCell.swift
index 25784f1ce..5b0fa58a2 100644
--- a/Application/Sources/UI/Views/DownloadCell.swift
+++ b/Application/Sources/UI/Views/DownloadCell.swift
@@ -127,13 +127,13 @@ struct DownloadCell: View {
var body: some View {
switch model.state {
case .added, .suspended, .unknown:
- Image(decorative: "downloadable_stop")
+ Image(.downloadableStop)
case .downloading:
AnimatedDownloadIcon()
case .downloaded:
- Image(decorative: "downloadable_full")
+ Image(.downloadableFull)
case .downloadable, .removed:
- Image(decorative: "downloadable")
+ Image(.downloadable)
}
}
}
diff --git a/Application/Sources/UI/Views/EmptyContentView.swift b/Application/Sources/UI/Views/EmptyContentView.swift
index 365230950..f19e0dfd8 100644
--- a/Application/Sources/UI/Views/EmptyContentView.swift
+++ b/Application/Sources/UI/Views/EmptyContentView.swift
@@ -24,23 +24,23 @@ struct EmptyContentView: View {
self.insets = insets
}
- private func imageName(for type: `Type`) -> String {
+ private func largeImage(for type: `Type`) -> ImageResource {
switch type {
case .episodesFromFavorites, .favoriteShows:
- return "favorite-background"
+ return .favoriteBackground
case .generic:
- return "media-background"
+ return .mediaBackground
case .history, .resumePlayback:
- return "history-background"
- case .notifications:
- return "subscription-background"
+ return .historyBackground
case .search, .searchTutorial:
- return "search-background"
+ return .searchBackground
case .watchLater:
- return "watch_later-background"
+ return .watchLaterBackground
#if os(iOS)
+ case .notifications:
+ return .subscriptionBackground
case .downloads:
- return "download-background"
+ return .downloadBackground
#endif
}
}
@@ -51,13 +51,13 @@ struct EmptyContentView: View {
return NSLocalizedString("No favorites", comment: "Text displayed when no favorites are available")
case .history:
return NSLocalizedString("No history", comment: "Text displayed when no history is available")
- case .notifications:
- return NSLocalizedString("No notifications", comment: "Text displayed when no notifications are available")
case .search:
return NSLocalizedString("No results", comment: "Default text displayed when no results are available")
case .searchTutorial:
return NSLocalizedString("Type to start searching", comment: "Message displayed when there is no search criterium entered")
#if os(iOS)
+ case .notifications:
+ return NSLocalizedString("No notifications", comment: "Text displayed when no notifications are available")
case .downloads:
return NSLocalizedString("No downloads", comment: "Text displayed when no downloads are available")
#endif
@@ -74,14 +74,14 @@ struct EmptyContentView: View {
case let .empty(type: type):
VStack {
if layout == .standard {
- Image(decorative: imageName(for: type))
+ Image(largeImage(for: type))
}
Text(emptyTitle(for: type))
.srgFont(.H2)
}
case let .failed(error: error):
VStack {
- Image(decorative: "error-background")
+ Image(.errorBackground)
Text(error.localizedDescription)
.srgFont(.H4)
}
@@ -109,12 +109,12 @@ extension EmptyContentView {
case favoriteShows
case generic
case history
- case notifications
case resumePlayback
case search
case searchTutorial
case watchLater
#if os(iOS)
+ case notifications
case downloads
#endif
}
diff --git a/Application/Sources/UI/Views/ExpandingButton.swift b/Application/Sources/UI/Views/ExpandingButton.swift
index b9a3dfec8..ac329eba5 100644
--- a/Application/Sources/UI/Views/ExpandingButton.swift
+++ b/Application/Sources/UI/Views/ExpandingButton.swift
@@ -11,7 +11,7 @@ import SwiftUI
/// Behavior: h-exp, v-exp
struct ExpandingButton: View {
- private let icon: String?
+ private let icon: ImageResource?
private let label: String?
private let accessibilityLabel: String
private let accessibilityHint: String?
@@ -19,7 +19,7 @@ struct ExpandingButton: View {
@State private var isFocused = false
- init(icon: String, label: String, accessibilityLabel: String? = nil, accessibilityHint: String? = nil, action: @escaping () -> Void) {
+ init(icon: ImageResource, label: String, accessibilityLabel: String? = nil, accessibilityHint: String? = nil, action: @escaping () -> Void) {
self.icon = icon
self.label = label
self.accessibilityLabel = accessibilityLabel ?? label
@@ -35,7 +35,7 @@ struct ExpandingButton: View {
self.action = action
}
- init(icon: String, accessibilityLabel: String? = nil, accessibilityHint: String? = nil, action: @escaping () -> Void) {
+ init(icon: ImageResource, accessibilityLabel: String? = nil, accessibilityHint: String? = nil, action: @escaping () -> Void) {
self.icon = icon
self.label = nil
self.accessibilityLabel = accessibilityLabel ?? ""
@@ -47,7 +47,7 @@ struct ExpandingButton: View {
Button(action: action) {
HStack(spacing: 8) {
if let icon {
- Image(decorative: icon)
+ Image(icon)
}
if let label {
Text(label)
@@ -70,16 +70,16 @@ struct ExpandingButton: View {
struct ExpandingButton_Previews: PreviewProvider {
static var previews: some View {
Group {
- ExpandingButton(icon: "a_to_z", label: "A to Z", action: {})
+ ExpandingButton(icon: .watchLater, label: "Later", action: {})
.padding()
.previewLayout(.fixed(width: 240, height: 120))
- ExpandingButton(icon: "a_to_z", label: "A to Z", action: {})
+ ExpandingButton(icon: .watchLater, label: "Later", action: {})
.padding()
.previewLayout(.fixed(width: 240, height: 120))
- ExpandingButton(label: "A to Z", action: {})
+ ExpandingButton(label: "Later", action: {})
.padding()
.previewLayout(.fixed(width: 120, height: 120))
- ExpandingButton(icon: "a_to_z", action: {})
+ ExpandingButton(icon: .watchLater, action: {})
.padding()
.previewLayout(.fixed(width: 120, height: 120))
}
diff --git a/Application/Sources/UI/Views/HeaderView.swift b/Application/Sources/UI/Views/HeaderView.swift
index d025c0a07..c60836cc5 100644
--- a/Application/Sources/UI/Views/HeaderView.swift
+++ b/Application/Sources/UI/Views/HeaderView.swift
@@ -34,7 +34,7 @@ struct HeaderView: View {
.srgFont(.H3)
.lineLimit(1)
if hasDetailDisclosure {
- Image(decorative: "chevron")
+ Image(.chevron)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: SRGFont.metricsForFont(with: .H3).scaledValue(for: 18))
diff --git a/Application/Sources/UI/Views/MediaMoreButton.swift b/Application/Sources/UI/Views/MediaMoreButton.swift
index 2691d9556..72cf2818b 100644
--- a/Application/Sources/UI/Views/MediaMoreButton.swift
+++ b/Application/Sources/UI/Views/MediaMoreButton.swift
@@ -13,7 +13,7 @@ struct MediaMoreButton: UIViewRepresentable {
func makeUIView(context: Context) -> UIButton {
let button = UIButton(type: .custom)
- button.setImage(UIImage(named: "ellipsis"), for: .normal)
+ button.setImage(UIImage(resource: .ellipsis), for: .normal)
button.tintColor = .srgGrayC7
button.showsMenuAsPrimaryAction = true
diff --git a/Application/Sources/UI/Views/MoreCell.swift b/Application/Sources/UI/Views/MoreCell.swift
index e240e9e58..8aafdaca3 100644
--- a/Application/Sources/UI/Views/MoreCell.swift
+++ b/Application/Sources/UI/Views/MoreCell.swift
@@ -22,7 +22,7 @@ struct MoreCell: View {
var body: some View {
#if os(tvOS)
LabeledCardButton(aspectRatio: Self.aspectRatio(for: imageVariant), action: action) {
- Image(decorative: "chevron-large")
+ Image(.chevronLarge)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: Self.iconHeight)
@@ -35,7 +35,7 @@ struct MoreCell: View {
Color.clear
}
#else
- Image(decorative: "chevron-large")
+ Image(.chevronLarge)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: Self.iconHeight)
diff --git a/Application/Sources/UI/Views/ShowAccessCell.swift b/Application/Sources/UI/Views/ShowAccessCell.swift
index 374f6fe4c..b5cff7f3d 100644
--- a/Application/Sources/UI/Views/ShowAccessCell.swift
+++ b/Application/Sources/UI/Views/ShowAccessCell.swift
@@ -24,7 +24,7 @@ struct ShowAccessCell: View {
private var showAZButtonProperties: ButtonProperties {
return ButtonProperties(
- icon: "a_to_z",
+ icon: .aToZ,
label: NSLocalizedString("A to Z", comment: "Show A-Z short button title"),
accessibilityLabel: PlaySRGAccessibilityLocalizedString("A to Z shows", comment: "Show A-Z button label")
)
@@ -34,13 +34,13 @@ struct ShowAccessCell: View {
switch style {
case .calendar:
return ButtonProperties(
- icon: "calendar",
+ icon: .calendar,
label: NSLocalizedString("By date", comment: "Show by date short button title"),
accessibilityLabel: PlaySRGAccessibilityLocalizedString("Shows by date", comment: "Show by date button label")
)
case .programGuide:
return ButtonProperties(
- icon: "tv_guide",
+ icon: .tvGuide,
label: NSLocalizedString("TV guide", comment: "TV guide short button title")
)
}
@@ -68,11 +68,11 @@ extension ShowAccessCell {
}
private struct ButtonProperties {
- let icon: String
+ let icon: ImageResource
let label: String
let accessibilityLabel: String?
- init(icon: String, label: String, accessibilityLabel: String? = nil) {
+ init(icon: ImageResource, label: String, accessibilityLabel: String? = nil) {
self.icon = icon
self.label = label
self.accessibilityLabel = accessibilityLabel
diff --git a/Application/Sources/UI/Views/ShowButton.swift b/Application/Sources/UI/Views/ShowButton.swift
index 22a39aabf..03786511e 100644
--- a/Application/Sources/UI/Views/ShowButton.swift
+++ b/Application/Sources/UI/Views/ShowButton.swift
@@ -27,8 +27,8 @@ struct ShowButton: View {
return url(for: show.image, size: .small)
}
- private var favoriteIcon: String {
- return isFavorite ? "favorite_full" : "favorite"
+ private var favoriteIcon: ImageResource {
+ return isFavorite ? .favoriteFull : .favorite
}
private var accessibilityLabel: String {
@@ -51,7 +51,7 @@ struct ShowButton: View {
}
.padding(.vertical, 2)
.frame(maxWidth: .infinity, alignment: .leading)
- Image(decorative: favoriteIcon)
+ Image(favoriteIcon)
.padding(.trailing, 8)
}
.frame(height: 80)
diff --git a/Application/Sources/UI/Views/ShowCell.swift b/Application/Sources/UI/Views/ShowCell.swift
index a9b5d8cfd..54c887e3c 100644
--- a/Application/Sources/UI/Views/ShowCell.swift
+++ b/Application/Sources/UI/Views/ShowCell.swift
@@ -92,12 +92,14 @@ struct ShowCell: View {
.srgFont(.H4)
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .topLeading)
+#if os(iOS)
if style == .favorite, model.isSubscribed {
- Image(decorative: "subscription_full")
+ Image(.subscriptionFull)
.resizable()
.scaledToFit()
.frame(height: 12)
}
+#endif
}
.foregroundColor(.srgGrayC7)
}
diff --git a/Application/Sources/UI/Views/SimpleButton.swift b/Application/Sources/UI/Views/SimpleButton.swift
index f24cb84df..a5da64e14 100644
--- a/Application/Sources/UI/Views/SimpleButton.swift
+++ b/Application/Sources/UI/Views/SimpleButton.swift
@@ -11,7 +11,7 @@ import SwiftUI
/// Behavior: h-hug, v-hug
struct SimpleButton: View {
- private let icon: String
+ private let icon: ImageResource
private let label: String?
private let labelMinimumScaleFactor: CGFloat?
private let accessibilityLabel: String
@@ -20,7 +20,7 @@ struct SimpleButton: View {
@State private var isFocused = false
- init(icon: String, accessibilityLabel: String, accessibilityHint: String? = nil, action: @escaping () -> Void) {
+ init(icon: ImageResource, accessibilityLabel: String, accessibilityHint: String? = nil, action: @escaping () -> Void) {
self.icon = icon
self.label = nil
self.labelMinimumScaleFactor = nil
@@ -29,7 +29,7 @@ struct SimpleButton: View {
self.action = action
}
- init(icon: String, label: String, labelMinimumScaleFactor: CGFloat = 0.8, accessibilityLabel: String? = nil, accessibilityHint: String? = nil, action: @escaping () -> Void) {
+ init(icon: ImageResource, label: String, labelMinimumScaleFactor: CGFloat = 0.8, accessibilityLabel: String? = nil, accessibilityHint: String? = nil, action: @escaping () -> Void) {
self.icon = icon
self.label = label
self.labelMinimumScaleFactor = labelMinimumScaleFactor
@@ -41,7 +41,7 @@ struct SimpleButton: View {
var body: some View {
Button(action: action) {
HStack(spacing: 8) {
- Image(decorative: icon)
+ Image(icon)
if let label {
Text(label)
.srgFont(.button)
@@ -62,8 +62,8 @@ struct SimpleButton: View {
struct SimpleButton_Previews: PreviewProvider {
static var previews: some View {
Group {
- SimpleButton(icon: "favorite", label: "Add to favorites", action: {})
- SimpleButton(icon: "favorite", accessibilityLabel: "Add to favorites", action: {})
+ SimpleButton(icon: .favorite, label: "Add to favorites", action: {})
+ SimpleButton(icon: .favorite, accessibilityLabel: "Add to favorites", action: {})
}
.padding()
.previewLayout(.sizeThatFits)
diff --git a/PlaySRG.xcodeproj/project.pbxproj b/PlaySRG.xcodeproj/project.pbxproj
index 4c7f5e736..680f30574 100644
--- a/PlaySRG.xcodeproj/project.pbxproj
+++ b/PlaySRG.xcodeproj/project.pbxproj
@@ -142,16 +142,16 @@
0451ECE528742D8000E89975 /* UIWindow+PlaySRG.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0451ECE228742D8000E89975 /* UIWindow+PlaySRG.swift */; };
0451ECE628742D8000E89975 /* UIWindow+PlaySRG.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0451ECE228742D8000E89975 /* UIWindow+PlaySRG.swift */; };
0451ECE728742D8000E89975 /* UIWindow+PlaySRG.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0451ECE228742D8000E89975 /* UIWindow+PlaySRG.swift */; };
- 0456C4A12976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */; };
- 0456C4A22976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */; };
- 0456C4A32976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */; };
- 0456C4A42976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */; };
- 0456C4A52976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */; };
- 0456C4A62976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */; };
- 0456C4A72976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */; };
- 0456C4A82976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */; };
- 0456C4A92976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */; };
- 0456C4AA2976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */; };
+ 0456C4A12976EE460088508A /* AnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsEvent.swift */; };
+ 0456C4A22976EE460088508A /* AnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsEvent.swift */; };
+ 0456C4A32976EE460088508A /* AnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsEvent.swift */; };
+ 0456C4A42976EE460088508A /* AnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsEvent.swift */; };
+ 0456C4A52976EE460088508A /* AnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsEvent.swift */; };
+ 0456C4A62976EE460088508A /* AnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsEvent.swift */; };
+ 0456C4A72976EE460088508A /* AnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsEvent.swift */; };
+ 0456C4A82976EE460088508A /* AnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsEvent.swift */; };
+ 0456C4A92976EE460088508A /* AnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsEvent.swift */; };
+ 0456C4AA2976EE460088508A /* AnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0456C4A02976EE460088508A /* AnalyticsEvent.swift */; };
0463DA102A73D8B000CD6556 /* ProgramAndChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0463DA0F2A73D8B000CD6556 /* ProgramAndChannel.swift */; };
0463DA112A73D8B000CD6556 /* ProgramAndChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0463DA0F2A73D8B000CD6556 /* ProgramAndChannel.swift */; };
0463DA122A73D8B000CD6556 /* ProgramAndChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0463DA0F2A73D8B000CD6556 /* ProgramAndChannel.swift */; };
@@ -2787,7 +2787,7 @@
044B408E2A02B6B500A10DB7 /* ProfileCell+UIKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ProfileCell+UIKit.swift"; sourceTree = ""; };
044E391F29B10C9100C1768A /* SRGShow+PlaySRG.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SRGShow+PlaySRG.swift"; sourceTree = ""; };
0451ECE228742D8000E89975 /* UIWindow+PlaySRG.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+PlaySRG.swift"; sourceTree = ""; };
- 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnalyticsHiddenEvent.swift; sourceTree = ""; };
+ 0456C4A02976EE460088508A /* AnalyticsEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnalyticsEvent.swift; sourceTree = ""; };
0463DA0F2A73D8B000CD6556 /* ProgramAndChannel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgramAndChannel.swift; sourceTree = ""; };
0481D59829F41D5B00D174B3 /* SRGMedia+PlaySRG.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SRGMedia+PlaySRG.swift"; sourceTree = ""; };
0481D5A329F44D4D00D174B3 /* SRGProgram+PlaySRG.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SRGProgram+PlaySRG.swift"; sourceTree = ""; };
@@ -3949,7 +3949,7 @@
04C2DE772937C67000E85A03 /* AnalyticsClickEvent.swift */,
6FE1B4951DCB84F00094D5BA /* AnalyticsConstants.h */,
6FE1B4961DCB84F00094D5BA /* AnalyticsConstants.m */,
- 0456C4A02976EE460088508A /* AnalyticsHiddenEvent.swift */,
+ 0456C4A02976EE460088508A /* AnalyticsEvent.swift */,
087584C723A0008500FA7207 /* ApplicationSectionInfo.h */,
087584CF23A0008500FA7207 /* ApplicationSectionInfo.m */,
6F4760181EB37BD1003021EA /* Categories */,
@@ -8452,7 +8452,7 @@
6F4760791EB37D60003021EA /* UIDevice+PlaySRG.m in Sources */,
6F573D0426D644A000757CD5 /* DeepLinkAction.m in Sources */,
6F475FE11EB37BC6003021EA /* ModalTransition.m in Sources */,
- 0456C4A12976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */,
+ 0456C4A12976EE460088508A /* AnalyticsEvent.swift in Sources */,
6FD633EA1FFD151000875BE5 /* MiniPlayerView.m in Sources */,
0451ECE328742D8000E89975 /* UIWindow+PlaySRG.swift in Sources */,
082910B5239EA69C00D168F4 /* RadioChannelsViewController.m in Sources */,
@@ -8703,7 +8703,7 @@
6FD633DF1FFBC0BE00875BE5 /* GoogleCastMiniPlayerView.m in Sources */,
04D2A92C29ACFE5900E11B28 /* Handle.swift in Sources */,
6FB9B3D726CA88AD0065092F /* TransluscentHeaderView.swift in Sources */,
- 0456C4A22976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */,
+ 0456C4A22976EE460088508A /* AnalyticsEvent.swift in Sources */,
6F56F9F5247C407000B2387B /* ChannelServiceSetup.m in Sources */,
6FC0C696245FF06D00B44CAE /* ProgramHeaderView.m in Sources */,
6F73BFB126563ABD0032D742 /* DampedCollectionView.swift in Sources */,
@@ -8968,7 +8968,7 @@
6F0AF6E6267D0B0500AD2EA3 /* MediaPreviewViewController.m in Sources */,
04D2A92D29ACFE5900E11B28 /* Handle.swift in Sources */,
6FD633E01FFBC0BE00875BE5 /* GoogleCastMiniPlayerView.m in Sources */,
- 0456C4A32976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */,
+ 0456C4A32976EE460088508A /* AnalyticsEvent.swift in Sources */,
6FB9B3D826CA88AD0065092F /* TransluscentHeaderView.swift in Sources */,
6F56F9F6247C407000B2387B /* ChannelServiceSetup.m in Sources */,
6FC0C697245FF06D00B44CAE /* ProgramHeaderView.m in Sources */,
@@ -9233,7 +9233,7 @@
6F0AF6E7267D0B0500AD2EA3 /* MediaPreviewViewController.m in Sources */,
04D2A92E29ACFE5900E11B28 /* Handle.swift in Sources */,
6FD633E11FFBC0BE00875BE5 /* GoogleCastMiniPlayerView.m in Sources */,
- 0456C4A42976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */,
+ 0456C4A42976EE460088508A /* AnalyticsEvent.swift in Sources */,
6FB9B3D926CA88AD0065092F /* TransluscentHeaderView.swift in Sources */,
6F56F9F7247C407100B2387B /* ChannelServiceSetup.m in Sources */,
6FC0C698245FF06D00B44CAE /* ProgramHeaderView.m in Sources */,
@@ -9514,7 +9514,7 @@
0875852623A0025F00FA7207 /* ProfileViewController.m in Sources */,
6FA5D1611F2077B10059E4E2 /* NSString+PlaySRG.m in Sources */,
6F566E9924EEC40A0024B4CA /* ApplicationSection.m in Sources */,
- 0456C4A52976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */,
+ 0456C4A52976EE460088508A /* AnalyticsEvent.swift in Sources */,
6F72E60B26BA6B16001A890C /* SceneDelegate.m in Sources */,
6F11BADF27D60525003E59B2 /* DownloadCellViewModel.swift in Sources */,
6FE14E6F263EA9B5004AD913 /* TitleView.swift in Sources */,
@@ -9903,7 +9903,7 @@
6FDB2AC524E5923600FF286E /* MediaCell.swift in Sources */,
6FA8E2DE261C9D3C003FFDCF /* PageViewController.swift in Sources */,
6F928E7C2745140000CE54B5 /* ProgramGuideViewController.swift in Sources */,
- 0456C4A62976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */,
+ 0456C4A62976EE460088508A /* AnalyticsEvent.swift in Sources */,
6FDFD88C24E6BC9200F20382 /* TopicCell.swift in Sources */,
6FC413D024EEEDC900FDF806 /* ApplicationSection.m in Sources */,
04F184ED28F097E900B1207C /* BadgeList.swift in Sources */,
@@ -10057,7 +10057,7 @@
6FDB2AC624E5923600FF286E /* MediaCell.swift in Sources */,
6FA8E2DF261C9D3D003FFDCF /* PageViewController.swift in Sources */,
6F928E7D2745140100CE54B5 /* ProgramGuideViewController.swift in Sources */,
- 0456C4A72976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */,
+ 0456C4A72976EE460088508A /* AnalyticsEvent.swift in Sources */,
6FDFD88D24E6BC9200F20382 /* TopicCell.swift in Sources */,
6FC413D824EEEDC900FDF806 /* ApplicationSection.m in Sources */,
04F184EE28F097E900B1207C /* BadgeList.swift in Sources */,
@@ -10211,7 +10211,7 @@
6FDB2AC724E5923600FF286E /* MediaCell.swift in Sources */,
6FA8E2E0261C9D3D003FFDCF /* PageViewController.swift in Sources */,
6F928E7E2745140100CE54B5 /* ProgramGuideViewController.swift in Sources */,
- 0456C4A82976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */,
+ 0456C4A82976EE460088508A /* AnalyticsEvent.swift in Sources */,
6FDFD88E24E6BC9200F20382 /* TopicCell.swift in Sources */,
6FC413E024EEEDCA00FDF806 /* ApplicationSection.m in Sources */,
04F184EF28F097E900B1207C /* BadgeList.swift in Sources */,
@@ -10365,7 +10365,7 @@
6FDB2AC824E5923600FF286E /* MediaCell.swift in Sources */,
6FA8E2FA261C9D3E003FFDCF /* PageViewController.swift in Sources */,
6F928E7F2745140200CE54B5 /* ProgramGuideViewController.swift in Sources */,
- 0456C4A92976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */,
+ 0456C4A92976EE460088508A /* AnalyticsEvent.swift in Sources */,
6FDFD88F24E6BC9200F20382 /* TopicCell.swift in Sources */,
6FC413E824EEEDCA00FDF806 /* ApplicationSection.m in Sources */,
04F184F028F097E900B1207C /* BadgeList.swift in Sources */,
@@ -10484,7 +10484,7 @@
0858CA64271084A000EE36EA /* ProgramGuideGridViewController.swift in Sources */,
6FFF1636250A20EF0053CDA6 /* FocusTracker.swift in Sources */,
6F5A7914256ED7E000E884F2 /* History.m in Sources */,
- 0456C4AA2976EE460088508A /* AnalyticsHiddenEvent.swift in Sources */,
+ 0456C4AA2976EE460088508A /* AnalyticsEvent.swift in Sources */,
6FA14539254729DA006E8D3B /* FocusableRegion.swift in Sources */,
04C2DE812937C67000E85A03 /* AnalyticsClickEvent.swift in Sources */,
6F14B113283CA4EF00F79447 /* SettingsView.swift in Sources */,
@@ -10854,6 +10854,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
BUNDLE_DISPLAY_NAME = "${PRODUCT_NAME}$(BUNDLE_DISPLAY_NAME_SUFFIX)";
BUNDLE_DISPLAY_NAME_SUFFIX = " π";
BUNDLE_IDENTIFIER_SUFFIX = .nightly;
@@ -11951,6 +11952,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
BUNDLE_DISPLAY_NAME = "${PRODUCT_NAME}$(BUNDLE_DISPLAY_NAME_SUFFIX)";
BUNDLE_DISPLAY_NAME_SUFFIX = " π―";
BUNDLE_IDENTIFIER_SUFFIX = .beta;
@@ -13644,6 +13646,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
BUNDLE_DISPLAY_NAME = "${PRODUCT_NAME}$(BUNDLE_DISPLAY_NAME_SUFFIX)";
BUNDLE_DISPLAY_NAME_SUFFIX = " π ";
BUNDLE_IDENTIFIER_SUFFIX = .debug;
@@ -13707,6 +13710,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
BUNDLE_DISPLAY_NAME = "${PRODUCT_NAME}$(BUNDLE_DISPLAY_NAME_SUFFIX)";
BUNDLE_DISPLAY_NAME_SUFFIX = "";
BUNDLE_IDENTIFIER_SUFFIX = "";
@@ -13961,6 +13965,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
BUNDLE_DISPLAY_NAME = "${PRODUCT_NAME}$(BUNDLE_DISPLAY_NAME_SUFFIX)";
BUNDLE_DISPLAY_NAME_SUFFIX = " π―";
BUNDLE_IDENTIFIER_SUFFIX = .beta;
@@ -14121,6 +14126,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
BUNDLE_DISPLAY_NAME = "${PRODUCT_NAME}$(BUNDLE_DISPLAY_NAME_SUFFIX)";
BUNDLE_DISPLAY_NAME_SUFFIX = " π";
BUNDLE_IDENTIFIER_SUFFIX = .nightly;
@@ -19253,7 +19259,7 @@
repositoryURL = "https://github.com/SRGSSR/srganalytics-apple.git";
requirement = {
kind = upToNextMajorVersion;
- minimumVersion = 8.2.0;
+ minimumVersion = 9.0.1;
};
};
6F3AED322614C5B6007D591F /* XCRemoteSwiftPackageReference "srgappearance-apple" */ = {
@@ -19293,7 +19299,7 @@
repositoryURL = "https://github.com/SRGSSR/srgletterbox-apple.git";
requirement = {
kind = upToNextMajorVersion;
- minimumVersion = 9.1.2;
+ minimumVersion = 9.2.1;
};
};
6F6DD3A924E449D7003F9437 /* XCRemoteSwiftPackageReference "srgdataprovider-apple" */ = {
diff --git a/PlaySRG.xcworkspace/xcshareddata/swiftpm/Package.resolved b/PlaySRG.xcworkspace/xcshareddata/swiftpm/Package.resolved
index e0717304a..08c13b085 100644
--- a/PlaySRG.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/PlaySRG.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -32,8 +32,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/comScore/Comscore-Swift-Package-Manager.git",
"state" : {
- "revision" : "ede1a4aee58fc63a308e2babf3e33f55fedecb68",
- "version" : "6.10.2"
+ "revision" : "fef761279a592960243e67f2aea110c6fa097fd8",
+ "version" : "6.11.0"
}
},
{
@@ -162,6 +162,15 @@
"version" : "16.12.4"
}
},
+ {
+ "identity" : "iosv5",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/CommandersAct/iOSV5.git",
+ "state" : {
+ "revision" : "bff12bbf890409182a055999985a28b4608b9b14",
+ "version" : "5.4.2"
+ }
+ },
{
"identity" : "leveldb",
"kind" : "remoteSourceControl",
@@ -266,8 +275,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/SRGSSR/srganalytics-apple.git",
"state" : {
- "revision" : "c92014ca8838ad3cf403735ce25757afb04cd31f",
- "version" : "8.2.0"
+ "revision" : "5fbe14159af7f61c86b8e02470cea97a133040f4",
+ "version" : "9.0.1"
}
},
{
@@ -320,8 +329,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/SRGSSR/srgletterbox-apple.git",
"state" : {
- "revision" : "52f33f390ee27e6c21b7a51282e787636dcdf663",
- "version" : "9.1.2"
+ "revision" : "6fd631014a39074d4fec1dce00804fa468d833fd",
+ "version" : "9.2.1"
}
},
{
@@ -396,24 +405,6 @@
"version" : "0.12.0"
}
},
- {
- "identity" : "tccore-xcframework-apple",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/SRGSSR/TCCore-xcframework-apple.git",
- "state" : {
- "revision" : "eb686883e63af28174472a09eda97acf07179c88",
- "version" : "4.5.4-srg5"
- }
- },
- {
- "identity" : "tcsdk-xcframework-apple",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/SRGSSR/TCSDK-xcframework-apple.git",
- "state" : {
- "revision" : "c4becb0b250258b78cb46225af5e269da834db5a",
- "version" : "4.4.1-srg5"
- }
- },
{
"identity" : "uickeychainstore",
"kind" : "remoteSourceControl",
diff --git a/Podfile.lock b/Podfile.lock
index 6eff8630b..94515bf8b 100755
--- a/Podfile.lock
+++ b/Podfile.lock
@@ -64,4 +64,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: a1e77ad2481071cb2575ad02ea8084be964a3861
-COCOAPODS: 1.12.1
+COCOAPODS: 1.13.0
diff --git a/TV Application/Sources/AppDelegate.swift b/TV Application/Sources/AppDelegate.swift
index de00bb8f0..2cec36f3c 100644
--- a/TV Application/Sources/AppDelegate.swift
+++ b/TV Application/Sources/AppDelegate.swift
@@ -62,13 +62,13 @@ extension AppDelegate: UIApplicationDelegate {
NotificationCenter.default.weakPublisher(for: .SRGIdentityServiceUserDidCancelLogin, object: SRGIdentityService.current)
.sink { _ in
- AnalyticsHiddenEvent.identity(action: .cancelLogin).send()
+ AnalyticsEvent.identity(action: .cancelLogin).send()
}
.store(in: &cancellables)
NotificationCenter.default.weakPublisher(for: .SRGIdentityServiceUserDidLogin, object: SRGIdentityService.current)
.sink { _ in
- AnalyticsHiddenEvent.identity(action: .login).send()
+ AnalyticsEvent.identity(action: .login).send()
}
.store(in: &cancellables)
@@ -77,7 +77,7 @@ extension AppDelegate: UIApplicationDelegate {
let unexpectedLogout = notification.userInfo?[SRGIdentityServiceUnauthorizedKey] as? Bool ?? false
let action = unexpectedLogout ? .unexpectedLogout : .logout as AnalyticsIdentityAction
- AnalyticsHiddenEvent.identity(action: action).send()
+ AnalyticsEvent.identity(action: action).send()
}
.store(in: &cancellables)
}
@@ -88,12 +88,13 @@ extension AppDelegate: UIApplicationDelegate {
UserConsentHelper.setup()
- let analyticsConfiguration = SRGAnalyticsConfiguration(businessUnitIdentifier: configuration.analyticsBusinessUnitIdentifier,
- container: configuration.analyticsContainer,
- siteName: configuration.siteName)
-#if DEBUG || NIGHTLY || BETA
- analyticsConfiguration.environmentMode = .preProduction
-#endif
+ SRGAnalyticsTracker.applySetupAnalyticsWorkaround()
+
+ let analyticsConfiguration = SRGAnalyticsConfiguration(
+ businessUnitIdentifier: configuration.analyticsBusinessUnitIdentifier,
+ sourceKey: configuration.analyticsSourceKey,
+ siteName: configuration.siteName
+ )
SRGAnalyticsTracker.shared.start(with: analyticsConfiguration, dataSource: self, identityService: SRGIdentityService.current)
#if DEBUG || NIGHTLY || BETA
@@ -138,6 +139,6 @@ extension AppDelegate: UIApplicationDelegate {
extension AppDelegate: SRGAnalyticsTrackerDataSource {
var srg_globalLabels: SRGAnalyticsLabels {
- UserConsentHelper.srgAnalyticsLabels
+ SRGAnalyticsLabels.play_globalLabels
}
}
diff --git a/TV Application/Sources/LabeledButton.swift b/TV Application/Sources/LabeledButton.swift
index 3d3581895..9cc10f8f9 100644
--- a/TV Application/Sources/LabeledButton.swift
+++ b/TV Application/Sources/LabeledButton.swift
@@ -7,7 +7,7 @@
import SwiftUI
struct LabeledButton: View {
- let icon: String
+ let icon: ImageResource
let label: String
let accessibilityLabel: String
let accessibilityHint: String?
@@ -15,7 +15,7 @@ struct LabeledButton: View {
@State private var isFocused = false
- init(icon: String, label: String, accessibilityLabel: String? = nil, accessibilityHint: String? = nil, action: @escaping () -> Void) {
+ init(icon: ImageResource, label: String, accessibilityLabel: String? = nil, accessibilityHint: String? = nil, action: @escaping () -> Void) {
self.icon = icon
self.label = label
self.accessibilityLabel = accessibilityLabel ?? label
@@ -26,7 +26,7 @@ struct LabeledButton: View {
var body: some View {
VStack {
Button(action: action) {
- Image(decorative: icon)
+ Image(icon)
.frame(width: 68)
.foregroundColor(isFocused ? .darkGray : .white)
.onParentFocusChange { isFocused = $0 }
@@ -45,12 +45,12 @@ struct LabeledButton: View {
struct LabeledButton_Previews: PreviewProvider {
static var previews: some View {
Group {
- LabeledButton(icon: "episodes", label: "Episodes", action: {})
+ LabeledButton(icon: .episodes, label: "Episodes", action: {})
.previewLayout(PreviewLayout.sizeThatFits)
.padding()
.previewDisplayName("Short label")
- LabeledButton(icon: "favorite", label: "Watch later", action: {})
+ LabeledButton(icon: .favorite, label: "Watch later", action: {})
.previewLayout(PreviewLayout.sizeThatFits)
.padding()
.previewDisplayName("Long label")
diff --git a/TV Application/Sources/LetterboxDelegate.swift b/TV Application/Sources/LetterboxDelegate.swift
index f66d5817e..b90e5fb15 100644
--- a/TV Application/Sources/LetterboxDelegate.swift
+++ b/TV Application/Sources/LetterboxDelegate.swift
@@ -17,8 +17,8 @@ class LetterboxDelegate: NSObject {
.sink { notification in
guard let media = notification.userInfo?[SRGLetterboxMediaKey] as? SRGMedia else { return }
- AnalyticsHiddenEvent.continuousPlayback(action: .playAutomatic,
- mediaUrn: media.urn)
+ AnalyticsEvent.continuousPlayback(action: .playAutomatic,
+ mediaUrn: media.urn)
.send()
}
.store(in: &cancellables)
@@ -27,18 +27,18 @@ class LetterboxDelegate: NSObject {
extension LetterboxDelegate: SRGLetterboxViewControllerDelegate {
func letterboxViewController(_ letterboxViewController: SRGLetterboxViewController, didEngageInContinuousPlaybackWithUpcomingMedia upcomingMedia: SRGMedia) {
- AnalyticsHiddenEvent.continuousPlayback(action: .play,
- mediaUrn: upcomingMedia.urn)
+ AnalyticsEvent.continuousPlayback(action: .play,
+ mediaUrn: upcomingMedia.urn)
.send()
}
func letterboxViewController(_ letterboxViewController: SRGLetterboxViewController, didCancelContinuousPlaybackWithUpcomingMedia upcomingMedia: SRGMedia) {
- AnalyticsHiddenEvent.continuousPlayback(action: .cancel,
- mediaUrn: upcomingMedia.urn)
+ AnalyticsEvent.continuousPlayback(action: .cancel,
+ mediaUrn: upcomingMedia.urn)
.send()
}
func letterboxViewControllerDidStartPicture(inPicture letterboxViewController: SRGLetterboxViewController) {
- AnalyticsHiddenEvent.pictureInPicture(urn: letterboxViewController.controller.fullLengthMedia?.urn).send()
+ AnalyticsEvent.pictureInPicture(urn: letterboxViewController.controller.fullLengthMedia?.urn).send()
}
}
diff --git a/TV Application/Sources/MediaDetailView.swift b/TV Application/Sources/MediaDetailView.swift
index fec4ceedb..e41e73a47 100644
--- a/TV Application/Sources/MediaDetailView.swift
+++ b/TV Application/Sources/MediaDetailView.swift
@@ -46,7 +46,7 @@ struct MediaDetailView: View {
.onChange(of: media) { newValue in
model.media = newValue
}
- .tracked(withTitle: analyticsPageTitle, levels: analyticsPageLevels)
+ .tracked(withTitle: analyticsPageTitle, type: AnalyticsPageType.detail.rawValue, levels: analyticsPageLevels)
.redactedIfNil(media)
}
@@ -115,12 +115,12 @@ struct MediaDetailView: View {
}
private struct AttributeView: View {
- let icon: String
+ let icon: ImageResource
let values: [String]
var body: some View {
HStack(spacing: 10) {
- Image(decorative: icon)
+ Image(icon)
// Unbreakable spaces before / after the separator
Text(values.joined(separator: "Β -Β "))
.srgFont(.subtitle2)
@@ -143,10 +143,10 @@ struct MediaDetailView: View {
}
}
if let subtitleLanguages = model.media?.play_subtitleLanguages, !subtitleLanguages.isEmpty {
- AttributeView(icon: "subtitle_tracks", values: subtitleLanguages)
+ AttributeView(icon: .subtitleTracks, values: subtitleLanguages)
}
if let audioLanguages = model.media?.play_audioLanguages, !audioLanguages.isEmpty {
- AttributeView(icon: "audio_tracks", values: audioLanguages)
+ AttributeView(icon: .audioTracks, values: audioLanguages)
}
}
}
@@ -183,7 +183,7 @@ struct MediaDetailView: View {
var body: some View {
HStack(alignment: .top, spacing: 30) {
// TODO: 22 icon?
- LabeledButton(icon: "play", label: playButtonLabel) {
+ LabeledButton(icon: .play, label: playButtonLabel) {
if let media = model.media {
let playAnalyticsClickEvent = media.urn == model.playAnalyticsClickEventMediaUrn ? model.playAnalyticsClickEvent : nil
navigateToMedia(media, play: true, playAnalyticsClickEvent: playAnalyticsClickEvent)
@@ -192,7 +192,7 @@ struct MediaDetailView: View {
if model.watchLaterAllowedAction != .none {
// TODO: Write in a better way
let isRemoval = (model.watchLaterAllowedAction == .remove)
- LabeledButton(icon: isRemoval ? "watch_later_full" : "watch_later",
+ LabeledButton(icon: isRemoval ? .watchLaterFull : .watchLater,
label: isRemoval
? NSLocalizedString("Later", comment: "Watch later or listen later button label in media detail view when a media is in the later list")
: model.media?.mediaType == .audio
@@ -207,7 +207,7 @@ struct MediaDetailView: View {
}
}
if let show = model.media?.show {
- LabeledButton(icon: "episodes", label: NSLocalizedString("More episodes", comment: "Button to access more episodes from the media detail view")) {
+ LabeledButton(icon: .episodes, label: NSLocalizedString("More episodes", comment: "Button to access more episodes from the media detail view")) {
navigateToShow(show)
}
}
diff --git a/TV Application/Sources/MediaDetailViewModel.swift b/TV Application/Sources/MediaDetailViewModel.swift
index 743102289..0d7c8b1bb 100644
--- a/TV Application/Sources/MediaDetailViewModel.swift
+++ b/TV Application/Sources/MediaDetailViewModel.swift
@@ -71,7 +71,7 @@ final class MediaDetailViewModel: ObservableObject {
guard error == nil else { return }
let action = added ? .add : .remove as AnalyticsListAction
- AnalyticsHiddenEvent.watchLater(action: action, source: .button, urn: media.urn).send()
+ AnalyticsEvent.watchLater(action: action, source: .button, urn: media.urn).send()
self.mediaData = MediaData(media: media, watchLaterAllowedAction: added ? .remove : .add, relatedMedias: self.mediaData.relatedMedias)
}
diff --git a/TV Application/Sources/SceneDelegate.swift b/TV Application/Sources/SceneDelegate.swift
index da4b0f7db..74344e085 100644
--- a/TV Application/Sources/SceneDelegate.swift
+++ b/TV Application/Sources/SceneDelegate.swift
@@ -97,7 +97,7 @@ final class SceneDelegate: UIResponder {
viewControllers.append(searchViewController)
let profileViewController = UIHostingController(rootView: SettingsView())
- profileViewController.tabBarItem = UITabBarItem(title: nil, image: UIImage(named: "profile_tab")!.withRenderingMode(.alwaysTemplate), tag: 6)
+ profileViewController.tabBarItem = UITabBarItem(title: nil, image: UIImage(resource: .profileTab).withRenderingMode(.alwaysTemplate), tag: 6)
profileViewController.tabBarItem.accessibilityLabel = PlaySRGAccessibilityLocalizedString("Profile", comment: "Profile button label on home view")
profileViewController.tabBarItem.accessibilityIdentifier = AccessibilityIdentifier.profileTabBarItem.value
viewControllers.append(profileViewController)
@@ -129,7 +129,7 @@ final class SceneDelegate: UIResponder {
}
} receiveValue: { media in
navigateToMedia(media)
- action.analyticsHiddenEvent.send()
+ action.analyticsEvent.send()
UserConsentHelper.waitCollectingConsentRelease()
}
.store(in: &cancellables)
@@ -143,7 +143,7 @@ final class SceneDelegate: UIResponder {
}
} receiveValue: { show in
navigateToShow(show)
- action.analyticsHiddenEvent.send()
+ action.analyticsEvent.send()
UserConsentHelper.waitCollectingConsentRelease()
}
.store(in: &cancellables)
diff --git a/WhatsNew-iOS-beta.json b/WhatsNew-iOS-beta.json
index 854751279..82bb3b4b1 100755
--- a/WhatsNew-iOS-beta.json
+++ b/WhatsNew-iOS-beta.json
@@ -207,5 +207,9 @@
"3.7.6-428": "- Update Chromecast component.\n- Maintenance release.",
"3.7.7-429": "- Fix player minor issues on iOS 17.",
"3.7.8-430": "- iOS 17 support.\n- Add program to calendar autorisation adapted on iOS 17.\n- Analytic events use a new server.",
- "3.7.8-431": "- Set at first time, german subtitles on. [RTR]"
+ "3.7.8-431": "- Set at first time, german subtitles on. [RTR]",
+ "3.7.9-432": "- Maintenance build.\n- Analytic events use a new server.",
+ "3.7.9-433": "- Allow playing video and audio when displaying user consent banners.\n- Analytic events have language property.",
+ "3.7.9-434": "- Increase player skip gesture area (double taps).",
+ "3.7.9-435": "- Patch analytics migration."
}
\ No newline at end of file
diff --git a/WhatsNew-tvOS-beta.json b/WhatsNew-tvOS-beta.json
index 05a4d3ab7..91f05763c 100755
--- a/WhatsNew-tvOS-beta.json
+++ b/WhatsNew-tvOS-beta.json
@@ -74,5 +74,9 @@
"1.7.5-427": "Branch beta\n- Update SRGAnalytics with Tag Commander V5 update.\n- Page view analytics have page type property.",
"1.7.5-428": "- Maintenance release.",
"1.7.6-430": "- tvOS 17 support.\n- Update profile view to fix a tvOS 17 issue.\n- Analytic events use a new server.",
- "1.7.6-431": "- Set at first time, german subtitles on. [RTR]"
+ "1.7.6-431": "- Set at first time, german subtitles on. [RTR]",
+ "1.7.7-432": "- Maintenance build.\n- Analytic events use a new server.",
+ "1.7.7-433": "- Allow playing video and audio when displaying user consent banners.\n- Analytic events have language property.",
+ "1.7.7-434": "- Better image resolution on program guide.",
+ "1.7.7-435": "- Patch analytics migration."
}
\ No newline at end of file
diff --git a/Xcode/Shared/Common.xcconfig b/Xcode/Shared/Common.xcconfig
index fc5c0bf15..c3250f60a 100755
--- a/Xcode/Shared/Common.xcconfig
+++ b/Xcode/Shared/Common.xcconfig
@@ -2,7 +2,7 @@ PRODUCT_BUNDLE_IDENTIFIER = $(BU__BUNDLE_IDENTIFIER_PREFIX)$(BU__BUNDLE_IDENTIFI
PRODUCT_NAME = $(BU__PRODUCT_NAME)$(TARGET__PRODUCT_NAME_SUFFIX)
// Version information
-CURRENT_PROJECT_VERSION = 431
+CURRENT_PROJECT_VERSION = 435
GCC_PREPROCESSOR_DEFINITIONS[config=Beta] = BETA=1
GCC_PREPROCESSOR_DEFINITIONS[config=Beta_AppCenter] = BETA=1 APPCENTER=1
diff --git a/Xcode/Shared/Targets/iOS/Common.xcconfig b/Xcode/Shared/Targets/iOS/Common.xcconfig
index 79cafce69..fbb7d22d5 100755
--- a/Xcode/Shared/Targets/iOS/Common.xcconfig
+++ b/Xcode/Shared/Targets/iOS/Common.xcconfig
@@ -1,7 +1,7 @@
#include "Xcode/Shared/Common.xcconfig"
// Version information
-MARKETING_VERSION = 3.7.8
+MARKETING_VERSION = 3.7.9
SDKROOT = iphoneos
TARGETED_DEVICE_FAMILY=1,2
diff --git a/Xcode/Shared/Targets/tvOS/Common.xcconfig b/Xcode/Shared/Targets/tvOS/Common.xcconfig
index 16ab6b89a..e4d1ef16a 100755
--- a/Xcode/Shared/Targets/tvOS/Common.xcconfig
+++ b/Xcode/Shared/Targets/tvOS/Common.xcconfig
@@ -1,7 +1,7 @@
#include "Xcode/Shared/Common.xcconfig"
// Version information
-MARKETING_VERSION = 1.7.6
+MARKETING_VERSION = 1.7.7
SDKROOT = appletvos
TARGETED_DEVICE_FAMILY=3
diff --git a/docs/REMOTE_CONFIGURATION.md b/docs/REMOTE_CONFIGURATION.md
index d21a354d4..3d5acdffd 100755
--- a/docs/REMOTE_CONFIGURATION.md
+++ b/docs/REMOTE_CONFIGURATION.md
@@ -42,6 +42,7 @@ If a remote configuration is found to be invalid (usually a mandatory parameter
## Analytics
+* `sourceKey` (mandatory, string): The source identifier to send events to.
* `siteName` (mandatory, string): The iOS and iPadOS site name to send events to.
* `tvSiteName` (mandatory, string): The tvOS site name to send events to.