diff --git a/Application/Application-Info.plist b/Application/Application-Info.plist
index 367b5e4fe..78f64e93a 100755
--- a/Application/Application-Info.plist
+++ b/Application/Application-Info.plist
@@ -242,5 +242,7 @@
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
+ UIUserInterfaceStyle
+ Dark
diff --git a/Application/Resources/Data/parsePlayUrl.js b/Application/Resources/Data/parsePlayUrl.js
index dbedfd104..df9ac4f7c 100644
--- a/Application/Resources/Data/parsePlayUrl.js
+++ b/Application/Resources/Data/parsePlayUrl.js
@@ -1,60 +1,20 @@
// parsePlayUrl
-var parsePlayUrlVersion = 19;
+var parsePlayUrlVersion = 22;
var parsePlayUrlBuild = "mmf";
-function parsePlayUrl(urlString) {
- var url = urlString;
- try {
- url = new URL(urlString);
- }
- catch(error) {
- console.log("Can't read URL: " + error);
- return null;
- }
-
- var queryParams = {};
- for (var queryItem of url.searchParams) {
- queryParams[queryItem[0]] = queryItem[1];
- }
-
- return parseForPlayApp(url.protocol.replace(':', ''), url.hostname, url.pathname, queryParams, url.hash.replace('#', ''));
+if(! console) {
+ var console = {
+ log:function(){}
+ }
}
function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
-
// fix path issue
pathname = pathname.replace("//", "/");
// Get BU
- var bu = null;
- switch (true) {
- case hostname.endsWith("tp.srgssr.ch") || hostname.endsWith("player.rts.ch") || hostname.endsWith("player.rsi.ch") || hostname.endsWith("player.rtr.ch") || hostname.endsWith("player.swissinfo.ch") || hostname.endsWith("player.srf.ch"):
- bu = "tp";
- break;
- case hostname.includes("rts.ch") || hostname.includes("srgplayer-rts") || (hostname.includes("play-mmf") && pathname.startsWith("/rts/")):
- bu = "rts";
- break;
- case hostname.includes("rsi.ch") || hostname.includes("srgplayer-rsi") || (hostname.includes("play-mmf") && pathname.startsWith("/rsi/")):
- bu = "rsi";
- break;
- case hostname.includes("rtr.ch") || hostname.includes("srgplayer-rtr") || (hostname.includes("play-mmf") && pathname.startsWith("/rtr/")):
- bu = "rtr";
- break;
- case hostname.includes("swissinfo.ch") || hostname.includes("srgplayer-swi") || (hostname.includes("play-mmf") && pathname.startsWith("/swi/")):
- bu = "swi";
- break;
- case hostname.includes("srf.ch") || hostname.includes("srgplayer-srf") || (hostname.includes("play-mmf") && pathname.startsWith("/srf/")):
- bu = "srf";
- break;
- case hostname.includes("play-mmf") && pathname.startsWith("/mmf/"):
- bu = "mmf";
- break;
- case hostname.includes("radioswisspop.ch") || hostname.includes("radioswissclassic.ch") || hostname.includes("radioswissjazz.ch"):
- bu = "radioswiss";
- break;
- }
-
+ var bu = getBuFromHostname(hostname,pathname);
if (! bu) {
console.log("This URL is not a Play SRG URL.");
return null;
@@ -91,7 +51,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
redirectBu = "swi";
break;
}
- var startTime = queryParams["start"];
+ var startTime = queryParams["start"];
return openMediaURN(server, redirectBu, mediaURN, startTime);
}
}
@@ -135,7 +95,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
}
// Returns default TV homepage
- return openPage(server, bu, "tv:home", null, null);
+ return openTvHomePage(server,bu);
}
if (hostname.includes("play-mmf") && ! pathname.startsWith("/mmf/")) {
@@ -163,7 +123,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
}
else if (pathname.startsWith("/video")) {
// Returns default TV homepage
- return openPage(server, bu, "tv:home", null, null);
+ return openTvHomePage(server,bu);
}
else {
var channelId = null;
@@ -186,7 +146,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
}
}
// Returns default radio homepage
- return openPage(server, bu, "radio:home", channelId, null);
+ return openRadioHomePage(server, bu, channelId);
}
}
@@ -213,7 +173,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
if (mediaType) {
var mediaId = queryParams["id"];
if (mediaId) {
- var startTime = queryParams["startTime"];
+ var startTime = queryParams["startTime"];
return openMedia(server, bu, mediaType, mediaId, startTime);
}
else {
@@ -238,7 +198,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
if (mediaType) {
var mediaId = pathname.substr(pathname.lastIndexOf('/') + 1);
if (mediaId) {
- var startTime = queryParams["startTime"];
+ var startTime = queryParams["startTime"];
return openMedia(server, bu, mediaType, mediaId, startTime);
}
else {
@@ -258,7 +218,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
}
else {
// Returns default TV homepage
- return openPage(server, bu, "tv:home", null, null);
+ return openTvHomePage(server,bu);
}
}
@@ -334,7 +294,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
}
else {
// Returns default radio homepage
- return openPage(server, bu, "radio:home", null, null);
+ return openRadioHomePage(server, bu, null);
}
}
@@ -350,7 +310,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
}
else {
// Returns default TV homepage
- return openPage(server, bu, "tv:home", null, null);
+ return openTvHomePage(server,bu);
}
}
@@ -409,7 +369,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
* Ex: https://www.srf.ch/play/tv
*/
if (pathname.endsWith("/tv")) {
- return openPage(server, bu, "tv:home", null, null);
+ return openTvHomePage(server,bu);
}
/**
@@ -419,7 +379,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
*/
if (pathname.endsWith("/radio")) {
var channelId = queryParams["station"];
- return openPage(server, bu, "radio:home", channelId, null);
+ return openRadioHomePage(server, bu,channelId);
}
/**
@@ -433,8 +393,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
index = index.toLowerCase();
index = (index.length > 1) ? null : index;
}
- var options = new Array( { key: "index", value: index } );
- return openPage(server, bu, "tv:az", null, options);
+ return openAtoZ(server, bu, null, index);
}
/**
@@ -449,8 +408,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
index = index.toLowerCase();
index = (index.length > 1) ? null : index;
}
- var options = new Array( { key: "index", value: index } );
- return openPage(server, bu, "radio:az", channelId, options);
+ return openRadioAtoZ(server, bu, channelId, index);
}
/**
@@ -464,14 +422,13 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
// Returns an ISO format
var dateArray = date.split("-");
if (dateArray.length == 3 && dateArray[2].length == 4 && dateArray[1].length == 2 && dateArray[0].length == 2) {
- date = dateArray[2] + "-" + dateArray[1] + "-" + dateArray[0];
+ date = dateArray[2] + "-" + dateArray[1] + "-" + dateArray[0];
}
else {
date = null;
}
}
- var options = new Array( { key: "date", value: date } );
- return openPage(server, bu, "tv:bydate", null, options);
+ return openByDate(server, bu, null, date);
}
/**
@@ -486,14 +443,13 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
// Returns an ISO format
var dateArray = date.split("-");
if (dateArray.length == 3 && dateArray[2].length == 4 && dateArray[1].length == 2 && dateArray[0].length == 2) {
- date = dateArray[2] + "-" + dateArray[1] + "-" + dateArray[0];
+ date = dateArray[2] + "-" + dateArray[1] + "-" + dateArray[0];
}
else {
date = null;
}
}
- var options = new Array( { key: "date", value: date } );
- return openPage(server, bu, "radio:bydate", channelId, options);
+ return openRadioByDate(server, bu, channelId, date);
}
/**
@@ -505,16 +461,13 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
if (pathname.endsWith("/suche") || pathname.endsWith("/recherche") || pathname.endsWith("/ricerca") || pathname.endsWith("/retschertga") || pathname.endsWith("/search")) {
var query = queryParams["query"];
var mediaType = queryParams["mediaType"];
- var transmission = null;
if (mediaType) {
mediaType = mediaType.toLowerCase();
if (mediaType != "video" && mediaType != "audio") {
mediaType = null;
}
}
- var transmissionComponent = (transmission != null) ? transmission + ":" : "";
- var options = new Array( { key: "query", value: query }, { key: "mediaType", value: mediaType } );
- return openPage(server, bu, transmissionComponent + "search", null, options);
+ return openSearch(server, bu, query, mediaType);
}
/**
@@ -523,10 +476,10 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
* Ex: https://www.rts.ch/play/tv/categories/info
*/
if (pathname.endsWith("/tv/themen") || pathname.endsWith("/tv/categories") || pathname.endsWith("/tv/categorie") || pathname.endsWith("/tv/tematicas") || pathname.endsWith("/tv/topics")) {
- return openPage(server, bu, "tv:home", null, null);
+ return openTvHomePage(server,bu);
}
else if (pathname.includes("/tv/themen") || pathname.includes("/tv/categories") || pathname.includes("/tv/categorie") || pathname.includes("/tv/tematicas") || pathname.includes("/tv/topics")) {
- var lastPathComponent = pathname.split("/").slice(-1)[0];
+ var lastPathComponent = pathname.split("/").slice(-1)[0];
var topicId = null;
@@ -540,7 +493,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
return openTopic(server, bu, "tv", topicId);
}
else {
- return openPage(server, bu, "tv:home", null, null);
+ return openTvHomePage(server,bu);
}
}
@@ -551,10 +504,10 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
*. Ex: https://www.rsi.ch/play/tv/event/event-playrsi-8858482
*/
if (pathname.endsWith("/tv/event")) {
- return openPage(server, bu, "tv:home", null, null);
+ return openTvHomePage(server,bu);
}
else if (pathname.includes("/tv/event")) {
- var lastPathComponent = pathname.split("/").slice(-1)[0];
+ var lastPathComponent = pathname.split("/").slice(-1)[0];
var eventId = null;
@@ -568,7 +521,7 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
return openModule(server, bu, "event", eventId);
}
else {
- return openPage(server, bu, "tv:home", null, null);
+ return openTvHomePage(server,bu);
}
}
@@ -579,85 +532,149 @@ function parseForPlayApp(scheme, hostname, pathname, queryParams, anchor) {
*. Ex: https://www.rsi.ch/play
*/
if (pathname.endsWith("/play/") || pathname.endsWith("/play")) {
- return openPage(server, bu, "tv:home", null, null);
+ return openTvHomePage(server,bu);
+ }
+
+ /**
+ * Catch play help urls
+ *
+ * Ex: https://www.srf.ch/play/tv/hilfe
+ * Ex: https://www.rts.ch/play/tv/aide
+ * Ex: https://www.rsi.ch/play/tv/guida
+ * Ex: https://www.rtr.ch/play/tv/agid
+ * Ex: https://play.swissinfo.ch/play/tv/help
+ */
+ if (pathname.endsWith("/hilfe") || pathname.endsWith("/aide") || pathname.endsWith("/guida") || pathname.endsWith("/agid") || pathname.endsWith("/help")) {
+ return openURL(server, bu, scheme, hostname, pathname, queryParams, anchor);
}
// Redirect fallback.
console.log("Can't parse Play URL. Unsupported URL.");
return schemeForBu(bu) + "://unsupported?server=" + server;
};
+
+// ---- Open functions
+
function openMedia(server, bu, mediaType, mediaId, startTime) {
- var redirect = schemeForBu(bu) + "://open?media=urn:" + bu + ":" + mediaType + ":" + mediaId;
- if (startTime) {
- redirect = redirect + "&start-time=" + startTime;
- }
- if (server) {
- redirect = redirect + "&server=" + encodeURIComponent(server);
- }
- return redirect;
+ var urn="urn:" + bu + ":" + mediaType + ":" + mediaId;
+ return openMediaURN(server,bu,urn,startTime);
}
function openMediaURN(server, bu, mediaURN, startTime) {
- var redirect = schemeForBu(bu) + "://open?media=" + mediaURN;
+ var options = {};
if (startTime) {
- redirect = redirect + "&start-time=" + startTime;
+ options['start_time'] = startTime;
}
if (server) {
- redirect = redirect + "&server=" + encodeURIComponent(server);
+ options['server'] = server;
}
- return redirect;
+ return buildBuUri(bu,"media",mediaURN,options);
}
function openShow(server, bu, showTransmission, showId) {
- var redirect = schemeForBu(bu) + "://open?show=urn:" + bu + ":show:" + showTransmission + ":" + showId;
+ var showUrn="urn:" + bu + ":show:" + showTransmission + ":" + showId;
+ var options = {};
if (server) {
- redirect = redirect + "&server=" + encodeURIComponent(server);
+ options['server'] = server;
}
- return redirect;
+ return buildBuUri(bu,"show",showUrn,options);
}
function openTopic(server, bu, topicTransmission, topicId) {
- var redirect = schemeForBu(bu) + "://open?topic=urn:" + bu + ":topic:" + topicTransmission + ":" + topicId;
+ var topicUrn="urn:" + bu + ":topic:" + topicTransmission + ":" + topicId;
+ var options = {};
if (server) {
- redirect = redirect + "&server=" + encodeURIComponent(server);
+ options['server'] = server;
}
- return redirect;
+ return buildBuUri(bu,"topic",topicUrn,options);
}
function openModule(server, bu, moduleType, moduleId) {
- var redirect = schemeForBu(bu) + "://open?module=urn:" + bu + ":module:" + moduleType + ":" + moduleId;
+ var topicUrn="urn:" + bu + ":module:" + moduleType + ":" + moduleId;
+ var options = {};
if (server) {
- redirect = redirect + "&server=" + encodeURIComponent(server);
+ options['server'] = server;
}
- return redirect;
+ return buildBuUri(bu,"module",topicUrn,options);
}
-function openPage(server, bu, page, channelId, options) {
- if (! page) {
- page = "tv:home";
- }
+function openTvHomePage(server,bu){
+ var options = {};
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"home",null,options);
+}
- var pageUid = page.split(":").slice(-1)[0];
+function openRadioHomePage(server,bu,channelId){
+ if (!channelId) {
+ channelId = primaryChannelUidForBu(bu);
+ }
+ var options={};
+ if(channelId){
+ options["channel_id"] = channelId;
+ }
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"home",null,options);
+}
- if (page.startsWith("radio:") && ! channelId) {
- channelId = primaryChannelUidForBu(bu);
- }
-
- var redirect = schemeForBu(bu) + "://open?page=urn:" + bu + ":page:" + page + "&page-id=" + pageUid;
- if (channelId) {
- redirect = redirect + "&channel-id=" + channelId;
- }
- if (options && Array.isArray(options)) {
- options.forEach(function(option) {
- if (option.key && option.value) {
- redirect = redirect + "&" + option.key + "=" + encodeURIComponent(option.value);
- }
- });
- }
- if (server) {
- redirect = redirect + "&server=" + encodeURIComponent(server);
- }
- return redirect;
+function openAtoZ(server,bu,channelId,index){
+ var options = {};
+ if(channelId) {
+ options['channel_id'] = channelId;
+ }
+ if(index) {
+ options['index'] = index;
+ }
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"az",null,options);
+}
+
+function openRadioAtoZ(server,bu,channelId,index){
+ if (!channelId) {
+ channelId = primaryChannelUidForBu(bu);
+ }
+ return openAtoZ(server,bu,channelId,index);
+}
+
+function openByDate(server,bu,channelId,date){
+ var options = {};
+ if(channelId) {
+ options['channel_id'] = channelId;
+ }
+
+ if(date) {
+ options['date'] = date;
+ }
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu, "bydate", null, options);
+}
+
+function openRadioByDate(server,bu,channelId,date) {
+ if (!channelId) {
+ channelId = primaryChannelUidForBu(bu);
+ }
+ return openByDate(server,bu,channelId,date);
+}
+
+function openSearch(server, bu, query, mediaType){
+ var options = {};
+ if(query) {
+ options['query'] = query;
+ }
+ if(mediaType) {
+ options['media_type'] = mediaType;
+ }
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"search", null, options);
}
function openURL(server, bu, scheme, hostname, pathname, queryParams, anchor) {
@@ -681,14 +698,16 @@ function openURL(server, bu, scheme, hostname, pathname, queryParams, anchor) {
}
var url = scheme + "://" + hostname + pathname + queryParamsString + anchorString;
-
- var redirect = schemeForBu(bu) + "://open?url=" + encodeURIComponent(url);
- if (server) {
- redirect = redirect + "&server=" + encodeURIComponent(server);
- }
- return redirect;
+ var options = {};
+ options['url'] = url;
+ if (server) {
+ options['server'] = server;
+ }
+ return buildBuUri(bu,"link",null,options)
}
+// --- parsing functions
+
function primaryChannelUidForBu(bu) {
switch (bu) {
case "srf":
@@ -747,21 +766,68 @@ function serverForUrl(hostname, pathname, queryParams) {
server = "play mmf";
}
else {
- var server = queryParams["server"];
- switch (server) {
- case "production":
- server = "production";
- break;
+ var serverParam = queryParams["server"];
+ switch (serverParam) {
case "stage":
server = "stage";
break;
case "test":
server = "test";
break;
- default:
- server = null;
}
}
}
return server;
}
+
+function getBuFromHostname(hostname, pathname) {
+ switch (true) {
+ case hostname.endsWith("tp.srgssr.ch") || hostname.endsWith("player.rts.ch") || hostname.endsWith("player.rsi.ch") || hostname.endsWith("player.rtr.ch") || hostname.endsWith("player.swissinfo.ch") || hostname.endsWith("player.srf.ch"):
+ return "tp";
+ case hostname.includes("rts.ch") || hostname.includes("srgplayer-rts") || (hostname.includes("play-mmf") && pathname.startsWith("/rts/")):
+ return "rts";
+ case hostname.includes("rsi.ch") || hostname.includes("srgplayer-rsi") || (hostname.includes("play-mmf") && pathname.startsWith("/rsi/")):
+ return "rsi";
+ case hostname.includes("rtr.ch") || hostname.includes("srgplayer-rtr") || (hostname.includes("play-mmf") && pathname.startsWith("/rtr/")):
+ return "rtr";
+ case hostname.includes("swissinfo.ch") || hostname.includes("srgplayer-swi") || (hostname.includes("play-mmf") && pathname.startsWith("/swi/")):
+ return "swi";
+ case hostname.includes("srf.ch") || hostname.includes("srgplayer-srf") || (hostname.includes("play-mmf") && pathname.startsWith("/srf/")):
+ return "srf";
+ case hostname.includes("play-mmf") && pathname.startsWith("/mmf/"):
+ return "mmf";
+ case hostname.includes("radioswisspop.ch") || hostname.includes("radioswissclassic.ch") || hostname.includes("radioswissjazz.ch"):
+ return "radioswiss";
+ }
+ return null;
+ }
+
+/**
+* Build scheme://host[/path][?queryParams[0]&...&queryParams[n-1]]
+* Sample:
+* playrts://media/urn:xxx?position=0&server=mmf
+*/
+function buildUri(scheme, host, path, queryParams) {
+ var uri = scheme + "://" + host;
+ if (path) {
+ uri = uri + "/" + path;
+ }
+ if (queryParams && queryParams !== {}) {
+ uri = uri + "?";
+ var optionIndex = 0;
+ for (var option in queryParams) {
+ if(queryParams[option]) {
+ if(optionIndex > 0) {
+ uri = uri + "&";
+ }
+ uri = uri + option + "=" + encodeURIComponent(queryParams[option]);
+ optionIndex++;
+ }
+ }
+ }
+ return uri;
+}
+
+function buildBuUri(bu, host, path, queryParams) {
+ return buildUri(schemeForBu(bu), host, path, queryParams);
+}
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 7203fd36f..c02124ff6 100755
--- a/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.latest_result.txt
+++ b/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.latest_result.txt
@@ -474,7 +474,7 @@ name: Mantle, nameSpecified: , owner: Mantle, version: 2.1.0
name: Masonry, nameSpecified: , owner: SRGSSR, version: v1.1.0_srg1
-name: srganalytics-ios, nameSpecified: , owner: SRGSSR, version: 3.7.4
+name: srganalytics-ios, nameSpecified: , owner: SRGSSR, version: 3.7.5
name: srgappearance-ios, nameSpecified: , owner: SRGSSR, version: 1.1.10
@@ -482,9 +482,9 @@ name: srgdataprovider-ios, nameSpecified: , owner: SRGSSR, version: 6.8
name: srgdiagnostics-ios, nameSpecified: , owner: SRGSSR, version: 1.0.1
-name: srgidentity-ios, nameSpecified: , owner: SRGSSR, version: 1.0.4
+name: srgidentity-ios, nameSpecified: , owner: SRGSSR, version: 1.0.5
-name: srgletterbox-ios, nameSpecified: , owner: SRGSSR, version: 1.14.4
+name: srgletterbox-ios, nameSpecified: , owner: SRGSSR, version: 1.14.5
name: srglogger-ios, nameSpecified: , owner: SRGSSR, version: 1.1
@@ -492,7 +492,7 @@ name: srgmediaplayer-ios, nameSpecified: , owner: SRGSSR, version: 2.8
name: srgnetwork-ios, nameSpecified: , owner: SRGSSR, version: 1.0.3
-name: srguserdata-ios, nameSpecified: , owner: SRGSSR, version: 1.1.3
+name: srguserdata-ios, nameSpecified: , owner: SRGSSR, version: 1.1.4
name: tagcommander-ios, nameSpecified: , owner: SRGSSR, version: 4.3.3_4.3.1
diff --git a/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.plist b/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.plist
index b3505ff29..224816c7e 100755
--- a/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.plist
+++ b/Application/Resources/Settings.bundle/com.mono0926.LicensePlist.plist
@@ -224,7 +224,7 @@
File
com.mono0926.LicensePlist/srganalytics-ios
Title
- srganalytics-ios (3.7.4)
+ srganalytics-ios (3.7.5)
Type
PSChildPaneSpecifier
@@ -256,7 +256,7 @@
File
com.mono0926.LicensePlist/srgidentity-ios
Title
- srgidentity-ios (1.0.4)
+ srgidentity-ios (1.0.5)
Type
PSChildPaneSpecifier
@@ -264,7 +264,7 @@
File
com.mono0926.LicensePlist/srgletterbox-ios
Title
- srgletterbox-ios (1.14.4)
+ srgletterbox-ios (1.14.5)
Type
PSChildPaneSpecifier
@@ -296,7 +296,7 @@
File
com.mono0926.LicensePlist/srguserdata-ios
Title
- srguserdata-ios (1.1.3)
+ srguserdata-ios (1.1.4)
Type
PSChildPaneSpecifier
diff --git a/Application/Sources/Application/PlayAppDelegate.m b/Application/Sources/Application/PlayAppDelegate.m
index c285bca47..489762fd6 100755
--- a/Application/Sources/Application/PlayAppDelegate.m
+++ b/Application/Sources/Application/PlayAppDelegate.m
@@ -261,28 +261,34 @@ - (void)application:(UIApplication *)application performActionForShortcutItem:(U
}
// See URL_SCHEMES.md
-// Open [scheme]://open?media=[media_urn] (optional query parameters: channel-id=[channel_id], start-time=[start_position_seconds])
-// Open [scheme]://open?show=[show_urn] (optional query parameter: channel-id=[channel_id])
-// Open [scheme]://open?topic=[topic_urn]
-// Open [scheme]://open?module=[module_urn]
-// Open [scheme]://open?page-id=[home] (optional query parameters: channel-id=[channel_id])
-// Open [scheme]://open?page-id=[az] (optional query parameters: channel-id=[channel_id], index=[index_letter])
-// Open [scheme]://open?page-id=[bydate] (optional query parameters: channel-id=[channel_id], date=[date] with format yyyy-MM-dd)
-// Open [scheme]://open?page-id=[search] (optional query parameters: query=[query], mediaType=[audio|video])
-// Open [scheme]://open?url=[url]
-// Open [scheme]://[play website url] (use "parsePlayUrl.js" to attempt transforming the URL)
+// Open [scheme]://media/[media_urn] (optional query parameters: channel_id=[channel_id], start_time=[start_position_seconds])
+// Open [scheme]://show/[show_urn] (optional query parameter: channel_id=[channel_id])
+// Open [scheme]://topic/[topic_urn]
+// Open [scheme]://module/[module_urn]
+// Open [scheme]://home (optional query parameters: channel_id=[channel_id])
+// Open [scheme]://az (optional query parameters: channel_id=[channel_id], index=[index_letter])
+// Open [scheme]://bydate (optional query parameters: channel_id=[channel_id], date=[date] with format yyyy-MM-dd)
+// Open [scheme]://search (optional query parameters: query=[query], media_type=[audio|video])
+// Open [scheme]://link?url=[url]
+// Open [scheme]://[play_website_url] (use "parsePlayUrl.js" to attempt transforming the URL)
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL options:(NSDictionary *)options
{
AnalyticsSource analyticsSource = ([URL.scheme isEqualToString:@"http"] || [URL.scheme isEqualToString:@"https"]) ? AnalyticsSourceDeepLink : AnalyticsSourceSchemeURL;
- NSURLComponents *URLComponents = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO];
- if (! [URLComponents.host.lowercaseString isEqualToString:@"open"]) {
+
+ NSArray *supportedActions = @[ DeeplinkActionMedia, DeeplinkActionShow, DeeplinkActionTopic, DeeplinkActionModule,
+ DeeplinkActionHome, DeeplinkActionAZ, DeeplinkActionByDate, DeeplinkActionSearch,
+ DeeplinkActionLink ];
+
+ NSURLComponents *URLComponents = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:YES];
+ if (! [supportedActions containsObject:URLComponents.host.lowercaseString]) {
NSURL *deepLinkURL = [DeepLinkService.sharedService schemeURLFromWebURL:URL];
if (deepLinkURL) {
- URLComponents = [NSURLComponents componentsWithURL:deepLinkURL resolvingAgainstBaseURL:NO];
+ URLComponents = [NSURLComponents componentsWithURL:deepLinkURL resolvingAgainstBaseURL:YES];
}
}
- if ([URLComponents.host.lowercaseString isEqualToString:@"open"]) {
+ if ([supportedActions containsObject:URLComponents.host.lowercaseString]) {
+ DeeplinkAction action = URLComponents.host.lowercaseString;
#if defined(DEBUG) || defined(NIGHTLY) || defined(BETA)
NSString *server = [self valueFromURLComponents:URLComponents withParameterName:@"server"];
@@ -300,10 +306,10 @@ - (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL options:(N
}
#endif
- NSString *mediaURN = [self valueFromURLComponents:URLComponents withParameterName:@"media"];
- if (mediaURN) {
- NSString *channelUid = [self valueFromURLComponents:URLComponents withParameterName:@"channel-id"];
- NSInteger startTime = [[self valueFromURLComponents:URLComponents withParameterName:@"start-time"] integerValue];
+ NSString *mediaURN = URLComponents.path.lastPathComponent;
+ if ([action isEqualToString:DeeplinkActionMedia] && mediaURN) {
+ NSString *channelUid = [self valueFromURLComponents:URLComponents withParameterName:@"channel_id"];
+ NSInteger startTime = [[self valueFromURLComponents:URLComponents withParameterName:@"start_time"] integerValue];
[self openMediaWithURN:mediaURN startTime:startTime channelUid:channelUid fromPushNotification:NO completionBlock:^{
SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init];
labels.source = analyticsSource;
@@ -315,9 +321,9 @@ - (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL options:(N
return YES;
}
- NSString *showURN = [self valueFromURLComponents:URLComponents withParameterName:@"show"];
- if (showURN) {
- NSString *channelUid = [self valueFromURLComponents:URLComponents withParameterName:@"channel-id"];
+ NSString *showURN = URLComponents.path.lastPathComponent;
+ if ([action isEqualToString:DeeplinkActionShow] && showURN) {
+ NSString *channelUid = [self valueFromURLComponents:URLComponents withParameterName:@"channel_id"];
[self openShowWithURN:showURN channelUid:channelUid fromPushNotification:NO completionBlock:^{
SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init];
labels.source = analyticsSource;
@@ -329,8 +335,8 @@ - (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL options:(N
return YES;
}
- NSString *topicURN = [self valueFromURLComponents:URLComponents withParameterName:@"topic"];
- if (topicURN) {
+ NSString *topicURN = URLComponents.path.lastPathComponent;
+ if ([action isEqualToString:DeeplinkActionTopic] && topicURN) {
[self openTopicWithURN:topicURN completionBlock:^{
SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init];
labels.source = analyticsSource;
@@ -342,8 +348,8 @@ - (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL options:(N
return YES;
}
- NSString *moduleURN = [self valueFromURLComponents:URLComponents withParameterName:@"module"];
- if (moduleURN) {
+ NSString *moduleURN = URLComponents.path.lastPathComponent;
+ if ([action isEqualToString:DeeplinkActionModule] && moduleURN) {
[self openModuleWithURN:moduleURN completionBlock:^{
SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init];
labels.source = analyticsSource;
@@ -355,14 +361,14 @@ - (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL options:(N
return YES;
}
- NSString *pageUid = [self valueFromURLComponents:URLComponents withParameterName:@"page-id"];
- if (pageUid) {
- NSString *channelUid = [self valueFromURLComponents:URLComponents withParameterName:@"channel-id"];
- [self openPageWithUid:pageUid channelUid:channelUid URLComponents:URLComponents completionBlock:^{
+ NSArray *pageActions = @[ DeeplinkActionHome, DeeplinkActionAZ, DeeplinkActionByDate, DeeplinkActionSearch ];
+ if ([pageActions containsObject:action]) {
+ NSString *channelUid = [self valueFromURLComponents:URLComponents withParameterName:@"channel_id"];
+ [self openPageWithAction:action channelUid:channelUid URLComponents:URLComponents completionBlock:^{
SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init];
labels.source = analyticsSource;
labels.type = AnalyticsTypeActionDisplayPage;
- labels.value = pageUid;
+ labels.value = action;
labels.extraValue1 = options[UIApplicationOpenURLOptionsSourceApplicationKey];
[SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:AnalyticsTitleOpenURL labels:labels];
}];
@@ -371,7 +377,7 @@ - (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL options:(N
NSString *URLString = [self valueFromURLComponents:URLComponents withParameterName:@"url"];
NSURL *URL = (URLString) ? [NSURL URLWithString:URLString] : nil;
- if (URL) {
+ if ([action isEqualToString:DeeplinkActionLink] && URL) {
[UIApplication.sharedApplication play_openURL:URL withCompletionHandler:^(BOOL success) {
SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init];
labels.source = analyticsSource;
@@ -501,20 +507,20 @@ - (void)openHomeWithChannelUid:(NSString *)channelUid completionBlock:(void (^)(
[self resetWithMenuItemInfo:menuItemInfo completionBlock:completionBlock];
}
-- (void)openPageWithUid:(NSString *)pageUid channelUid:(NSString *)channelUid URLComponents:(NSURLComponents *)URLComponents completionBlock:(void (^)(void))completionBlock
+- (void)openPageWithAction:(DeeplinkAction)action channelUid:(NSString *)channelUid URLComponents:(NSURLComponents *)URLComponents completionBlock:(void (^)(void))completionBlock
{
- NSParameterAssert(pageUid);
+ NSParameterAssert(action);
- if ([pageUid isEqualToString:@"az"]) {
+ if ([action isEqualToString:DeeplinkActionAZ]) {
NSString *index = [self valueFromURLComponents:URLComponents withParameterName:@"index"];
[self openShowListAtIndex:index withChannelUid:channelUid completionBlock:completionBlock];
}
- else if ([pageUid isEqualToString:@"bydate"]) {
+ else if ([action isEqualToString:DeeplinkActionByDate]) {
NSString *dateString = [self valueFromURLComponents:URLComponents withParameterName:@"date"];
NSDate *date = dateString ? [NSDateFormatter.play_URLOptionDateFormatter dateFromString:dateString] : nil;
[self openCalendarAtDate:date withChannelUid:channelUid completionBlock:completionBlock];
}
- else if ([pageUid isEqualToString:@"search"]) {
+ else if ([action isEqualToString:DeeplinkActionSearch]) {
NSString *query = [self valueFromURLComponents:URLComponents withParameterName:@"query"];
static NSDictionary *s_mediaTypes;
@@ -524,12 +530,12 @@ - (void)openPageWithUid:(NSString *)pageUid channelUid:(NSString *)channelUid UR
@"audio" : @(SRGMediaTypeAudio) };
});
- NSString *mediaTypeName = [self valueFromURLComponents:URLComponents withParameterName:@"mediaType"];
+ NSString *mediaTypeName = [self valueFromURLComponents:URLComponents withParameterName:@"media_type"];
SRGMediaType mediaType = s_mediaTypes[mediaTypeName].integerValue;
[self openSearchWithQuery:query mediaType:mediaType completionBlock:completionBlock];
}
- else if ([pageUid isEqualToString:@"home"]) {
+ else if ([action isEqualToString:DeeplinkActionHome]) {
[self openHomeWithChannelUid:channelUid completionBlock:completionBlock];
}
}
diff --git a/Application/Sources/Helpers/DeepLinkService.h b/Application/Sources/Helpers/DeepLinkService.h
index d7b3370fd..af1a175c7 100755
--- a/Application/Sources/Helpers/DeepLinkService.h
+++ b/Application/Sources/Helpers/DeepLinkService.h
@@ -8,6 +8,21 @@
NS_ASSUME_NONNULL_BEGIN
+typedef NSString * DeeplinkAction NS_STRING_ENUM;
+
+/**
+ * Actions
+ */
+OBJC_EXPORT DeeplinkAction const DeeplinkActionMedia;
+OBJC_EXPORT DeeplinkAction const DeeplinkActionShow;
+OBJC_EXPORT DeeplinkAction const DeeplinkActionTopic;
+OBJC_EXPORT DeeplinkAction const DeeplinkActionModule;
+OBJC_EXPORT DeeplinkAction const DeeplinkActionHome;
+OBJC_EXPORT DeeplinkAction const DeeplinkActionAZ;
+OBJC_EXPORT DeeplinkAction const DeeplinkActionByDate;
+OBJC_EXPORT DeeplinkAction const DeeplinkActionSearch;
+OBJC_EXPORT DeeplinkAction const DeeplinkActionLink;
+
/**
* Service responsible for retrieving the deep link conversion file, and to convert web URLs into scheme URLs.
*/
diff --git a/Application/Sources/Helpers/DeepLinkService.m b/Application/Sources/Helpers/DeepLinkService.m
index 58ef4ab0b..f0c9a0200 100755
--- a/Application/Sources/Helpers/DeepLinkService.m
+++ b/Application/Sources/Helpers/DeepLinkService.m
@@ -18,6 +18,16 @@
NSString * const DeepLinkDiagnosticsServiceName = @"DeepLinkDiagnosticsServiceName";
+DeeplinkAction const DeeplinkActionMedia = @"media";
+DeeplinkAction const DeeplinkActionShow = @"show";
+DeeplinkAction const DeeplinkActionTopic = @"topic";
+DeeplinkAction const DeeplinkActionModule = @"module";
+DeeplinkAction const DeeplinkActionHome = @"home";
+DeeplinkAction const DeeplinkActionAZ = @"az";
+DeeplinkAction const DeeplinkActionByDate = @"bydate";
+DeeplinkAction const DeeplinkActionSearch = @"search";
+DeeplinkAction const DeeplinkActionLink = @"link";
+
@interface DeepLinkService ()
@property (nonatomic, weak) SRGRequest *request;
@@ -135,7 +145,7 @@ - (void)updateDeepLinkScript
{
if ([FXReachability sharedInstance].reachable && !self.request.running) {
NSURL *middlewareURL = ApplicationConfiguration.sharedApplicationConfiguration.middlewareURL;
- NSURL *URL = [NSURL URLWithString:@"api/v1/deeplink/parsePlayUrl.js" relativeToURL:middlewareURL];
+ NSURL *URL = [NSURL URLWithString:@"api/v2/deeplink/parsePlayUrl.js" relativeToURL:middlewareURL];
SRGRequest *request = [SRGRequest dataRequestWithURLRequest:[NSURLRequest requestWithURL:URL] session:NSURLSession.sharedSession completionBlock:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (data) {
diff --git a/Application/Sources/Search/SearchViewController.h b/Application/Sources/Search/SearchViewController.h
index 6af9b8e1b..bf6127992 100755
--- a/Application/Sources/Search/SearchViewController.h
+++ b/Application/Sources/Search/SearchViewController.h
@@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
* Create a search view controller with optional query and settings.
*
* @param query The query.
- * @param settings The search settings. Only set if the application can use them (@see `searchSettingsDisabled` in `ApplicationConfiguration`).
+ * @param settings The search settings. Only used if search settings is enabled (@see `searchSettingsDisabled` in `ApplicationConfiguration`).
*/
- (instancetype)initWithQuery:(nullable NSString *)query settings:(nullable SRGMediaSearchSettings *)settings;
diff --git a/Application/Sources/Search/SearchViewController.m b/Application/Sources/Search/SearchViewController.m
index c170edf5e..accbbe07f 100755
--- a/Application/Sources/Search/SearchViewController.m
+++ b/Application/Sources/Search/SearchViewController.m
@@ -47,7 +47,9 @@ @implementation SearchViewController
+ (BOOL)containsAdvancedSettings:(SRGMediaSearchSettings *)settings
{
- NSParameterAssert(settings);
+ if (! settings) {
+ return NO;
+ }
SRGMediaSearchSettings *defaultSettings = SearchSettingsViewController.defaultSettings;
defaultSettings.aggregationsEnabled = NO;
@@ -61,11 +63,16 @@ - (instancetype)initWithQuery:(NSString *)query settings:(SRGMediaSearchSettings
if (self = [super init]) {
self.query = query;
+ // A BU supporting aggregation but not displaying search settings can lead to longer response times.
+ // (@see `-mediasForVendor:matchingQuery:withSettings:completionBlock:` in `SRGDataProvider`).
ApplicationConfiguration *applicationConfiguration = ApplicationConfiguration.sharedApplicationConfiguration;
if (! applicationConfiguration.searchSettingsDisabled) {
self.settings = settings ?: SearchSettingsViewController.defaultSettings;
self.settings.aggregationsEnabled = NO;
}
+ else {
+ self.settings = nil;
+ }
}
return self;
}
@@ -333,7 +340,8 @@ - (UIViewController *)previewContextViewController
- (void)updateSearchSettingsButton
{
- if (self.settings) {
+ ApplicationConfiguration *applicationConfiguration = ApplicationConfiguration.sharedApplicationConfiguration;
+ if (! applicationConfiguration.searchSettingsDisabled) {
UIButton *filtersButton = [UIButton buttonWithType:UIButtonTypeCustom];
[filtersButton addTarget:self action:@selector(showSettings:) forControlEvents:UIControlEventTouchUpInside];
@@ -363,20 +371,6 @@ - (void)updateSearchSettingsButton
}
}
-#pragma mark Settings management
-
-- (SRGMediaType)mediaTypeForScopeButtonIndex:(NSInteger)index
-{
- static dispatch_once_t s_onceToken;
- static NSDictionary *s_mediaTypes;
- dispatch_once(&s_onceToken, ^{
- s_mediaTypes = @{ @0 : @(SRGMediaTypeNone),
- @1 : @(SRGMediaTypeVideo),
- @2 : @(SRGMediaTypeAudio) };
- });
- return [s_mediaTypes[@(index)] integerValue];
-}
-
#pragma mark Search
- (void)search
@@ -552,7 +546,12 @@ - (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementa
if (self.items != 0) {
ApplicationConfiguration *applicationConfiguration = ApplicationConfiguration.sharedApplicationConfiguration;
if (applicationConfiguration.searchSettingsDisabled) {
- headerView.title = NSLocalizedString(@"Videos", @"Header for video search results");
+ if (applicationConfiguration.radioChannels.count == 0) {
+ headerView.title = NSLocalizedString(@"Videos", @"Header for video search results");
+ }
+ else {
+ headerView.title = NSLocalizedString(@"Videos and audios", @"Header for video and audio search results");
+ }
}
else {
static dispatch_once_t s_onceToken;
@@ -673,7 +672,9 @@ - (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NS
- (void)showSettings:(id)sender
{
- SearchSettingsViewController *searchSettingsViewController = [[SearchSettingsViewController alloc] initWithQuery:self.query settings:self.settings];
+ [self.searchController.searchBar resignFirstResponder];
+
+ SearchSettingsViewController *searchSettingsViewController = [[SearchSettingsViewController alloc] initWithQuery:self.query settings:self.settings ?: SearchSettingsViewController.defaultSettings];
searchSettingsViewController.delegate = self;
UIColor *backgroundColor = (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) ? UIColor.play_popoverGrayColor : nil;
@@ -721,10 +722,6 @@ - (void)updateSearchResultsForSearchController:(UISearchController *)searchContr
NSTimeInterval delay = (searchBar.text.length == 0) ? 0. : kTypingSpeedThreshold;
[self performSelector:@selector(search) withObject:nil afterDelay:delay inModes:@[ NSRunLoopCommonModes ]];
}
- // Instantaneous search triggered when the selected scope button changed
- else if ([self mediaTypeForScopeButtonIndex:searchBar.selectedScopeButtonIndex] != self.settings.mediaType) {
- [self search];
- }
}
#pragma mark UIScrollViewDelegate protocol
diff --git a/Application/Sources/UI/Controllers/SideMenuController.m b/Application/Sources/UI/Controllers/SideMenuController.m
index 106585700..3709a174c 100755
--- a/Application/Sources/UI/Controllers/SideMenuController.m
+++ b/Application/Sources/UI/Controllers/SideMenuController.m
@@ -363,10 +363,9 @@ - (void)setSelectedMenuItemInfo:(MenuItemInfo *)selectedMenuItemInfo animated:(B
switch (selectedMenuItemInfo.menuItem) {
case MenuItemSearch: {
NSString *query = selectedMenuItemInfo.options[MenuItemOptionSearchQueryKey];
- SRGMediaType mediaType = [selectedMenuItemInfo.options[MenuItemOptionSearchMediaTypeOptionKey] integerValue];
-
SRGMediaSearchSettings *settings = [[SRGMediaSearchSettings alloc] init];
- settings.mediaType = mediaType;
+ settings.mediaType = [selectedMenuItemInfo.options[MenuItemOptionSearchMediaTypeOptionKey] integerValue];
+
viewController = [[SearchViewController alloc] initWithQuery:query settings:settings];
break;
}
diff --git a/Cartfile b/Cartfile
index 829114d5e..6b8ecb58d 100755
--- a/Cartfile
+++ b/Cartfile
@@ -2,5 +2,5 @@ github "defagos/CoconutKit" "3.3.8"
github "Flipboard/FLEX" "6d489e72c52401839386ee41aeefe1f5105c212e"
github "mapbox/Fingertips" "cdffabac5506103a2c7cc5aedeed4021df2501da"
github "SRGSSR/DZNEmptyDataSet" "v1.8.1_srg1"
-github "SRGSSR/srgletterbox-ios" "1.14.4"
-github "SRGSSR/srguserdata-ios" "1.1.3"
\ No newline at end of file
+github "SRGSSR/srgletterbox-ios" "1.14.5"
+github "SRGSSR/srguserdata-ios" "1.1.4"
\ No newline at end of file
diff --git a/Cartfile.resolved.proprietary b/Cartfile.resolved.proprietary
index eb682b098..1b80c22a8 100755
--- a/Cartfile.resolved.proprietary
+++ b/Cartfile.resolved.proprietary
@@ -8,17 +8,17 @@ github "SRGSSR/Masonry" "v1.1.0_srg1"
github "SRGSSR/UICKeyChainStore" "v2.1.2_srg1"
github "SRGSSR/YYWebImage" "1.0.5_srg1"
github "SRGSSR/libextobjc" "0.6_srg1"
-github "SRGSSR/srganalytics-ios" "3.7.4"
+github "SRGSSR/srganalytics-ios" "3.7.5"
github "SRGSSR/srgappearance-ios" "1.1.10"
github "SRGSSR/srgcontentprotection-ios" "1.2.3"
github "SRGSSR/srgdataprovider-ios" "6.8"
github "SRGSSR/srgdiagnostics-ios" "1.0.1"
-github "SRGSSR/srgidentity-ios" "1.0.4"
-github "SRGSSR/srgletterbox-ios" "1.14.4"
+github "SRGSSR/srgidentity-ios" "1.0.5"
+github "SRGSSR/srgletterbox-ios" "1.14.5"
github "SRGSSR/srglogger-ios" "1.1"
github "SRGSSR/srgmediaplayer-ios" "2.8"
github "SRGSSR/srgnetwork-ios" "1.0.3"
-github "SRGSSR/srguserdata-ios" "1.1.3"
+github "SRGSSR/srguserdata-ios" "1.1.4"
github "SRGSSR/tagcommander-ios" "4.3.3_4.3.1"
github "defagos/CoconutKit" "3.3.8"
github "mapbox/Fingertips" "cdffabac5506103a2c7cc5aedeed4021df2501da"
diff --git a/Cartfile.resolved.public b/Cartfile.resolved.public
index 807c6599f..0b28bf172 100755
--- a/Cartfile.resolved.public
+++ b/Cartfile.resolved.public
@@ -8,17 +8,17 @@ github "SRGSSR/Masonry" "v1.1.0_srg1"
github "SRGSSR/UICKeyChainStore" "v2.1.2_srg1"
github "SRGSSR/YYWebImage" "1.0.5_srg1"
github "SRGSSR/libextobjc" "0.6_srg1"
-github "SRGSSR/srganalytics-ios" "3.7.4"
+github "SRGSSR/srganalytics-ios" "3.7.5"
github "SRGSSR/srgappearance-ios" "1.1.10"
github "SRGSSR/srgcontentprotection-fake-ios" "1.2.3"
github "SRGSSR/srgdataprovider-ios" "6.8"
github "SRGSSR/srgdiagnostics-ios" "1.0.1"
-github "SRGSSR/srgidentity-ios" "1.0.4"
-github "SRGSSR/srgletterbox-ios" "1.14.4"
+github "SRGSSR/srgidentity-ios" "1.0.5"
+github "SRGSSR/srgletterbox-ios" "1.14.5"
github "SRGSSR/srglogger-ios" "1.1"
github "SRGSSR/srgmediaplayer-ios" "2.8"
github "SRGSSR/srgnetwork-ios" "1.0.3"
-github "SRGSSR/srguserdata-ios" "1.1.3"
+github "SRGSSR/srguserdata-ios" "1.1.4"
github "SRGSSR/tagcommander-ios" "4.3.3_4.3.1"
github "defagos/CoconutKit" "3.3.8"
github "mapbox/Fingertips" "cdffabac5506103a2c7cc5aedeed4021df2501da"
diff --git a/PlaySRG.xcodeproj/project.pbxproj b/PlaySRG.xcodeproj/project.pbxproj
index a3a9d6a5a..a62109e07 100644
--- a/PlaySRG.xcodeproj/project.pbxproj
+++ b/PlaySRG.xcodeproj/project.pbxproj
@@ -2617,13 +2617,6 @@
path = Helpers;
sourceTree = "";
};
- 0865F60F223C7506007DE03B /* Recovered References */ = {
- isa = PBXGroup;
- children = (
- );
- name = "Recovered References";
- sourceTree = "";
- };
0865F616223C7684007DE03B /* Data */ = {
isa = PBXGroup;
children = (
@@ -2697,7 +2690,6 @@
E65311E31D3E6FD100B4B8BB /* Frameworks */,
45D67F958D75253E27BCDE9C /* Pods */,
08C68D501D38D49600BB8AAA /* Products */,
- 0865F60F223C7506007DE03B /* Recovered References */,
);
sourceTree = "";
};
@@ -5224,7 +5216,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:0:CFBundleURLSchemes: string srfplayer${MARKETING_VERSION_SUFFIX}\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Info.plist\"";
+ shellScript = "/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:0:CFBundleURLSchemes: string srfplayer${MARKETING_VERSION_SUFFIX}\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Info.plist\"\n";
};
6FE1B4A01DCBC8270094D5BA /* Embed Debugging Frameworks */ = {
isa = PBXShellScriptBuildPhase;
@@ -6695,7 +6687,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 313;
+ CURRENT_PROJECT_VERSION = 317;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -6714,7 +6706,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- MARKETING_VERSION = 2.9.5;
+ MARKETING_VERSION = 2.9.6;
MARKETING_VERSION_SUFFIX = "-debug";
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -6763,7 +6755,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 313;
+ CURRENT_PROJECT_VERSION = 317;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -6776,7 +6768,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- MARKETING_VERSION = 2.9.5;
+ MARKETING_VERSION = 2.9.6;
MARKETING_VERSION_SUFFIX = "";
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
@@ -6829,7 +6821,7 @@
CODE_SIGN_ENTITLEMENTS = "$(PROJECT_DIR)/Application/Application.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEVELOPMENT_TEAM = VMGRRW6SG7;
+ DEVELOPMENT_TEAM = JA876HZNN2;
DOMAIN = "*.srf.ch";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -6888,7 +6880,7 @@
CODE_SIGN_ENTITLEMENTS = "$(PROJECT_DIR)/Application/Application.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEVELOPMENT_TEAM = VMGRRW6SG7;
+ DEVELOPMENT_TEAM = 8779C367VK;
DOMAIN = "*.rts.ch";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -6947,7 +6939,7 @@
CODE_SIGN_ENTITLEMENTS = "$(PROJECT_DIR)/Application/Application.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEVELOPMENT_TEAM = VMGRRW6SG7;
+ DEVELOPMENT_TEAM = Y7342J76KH;
DOMAIN = "*.rsi.ch";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -7006,7 +6998,7 @@
CODE_SIGN_ENTITLEMENTS = "$(PROJECT_DIR)/Application/Application.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEVELOPMENT_TEAM = VMGRRW6SG7;
+ DEVELOPMENT_TEAM = ABW92QGFZ7;
DOMAIN = "*.rtr.ch";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -7063,7 +7055,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "$(PROJECT_DIR)/Application/Application.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
- DEVELOPMENT_TEAM = VMGRRW6SG7;
+ DEVELOPMENT_TEAM = R36WF3S37T;
DOMAIN = "*.swissinfo.ch";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -7118,7 +7110,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 313;
+ CURRENT_PROJECT_VERSION = 317;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -7132,7 +7124,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- MARKETING_VERSION = 2.9.5;
+ MARKETING_VERSION = 2.9.6;
MARKETING_VERSION_SUFFIX = "-beta";
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
@@ -7325,7 +7317,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 313;
+ CURRENT_PROJECT_VERSION = 317;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -7339,7 +7331,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- MARKETING_VERSION = 2.9.5;
+ MARKETING_VERSION = 2.9.6;
MARKETING_VERSION_SUFFIX = "-nightly";
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
@@ -7569,7 +7561,7 @@
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- DEVELOPMENT_TEAM = VMGRRW6SG7;
+ DEVELOPMENT_TEAM = JA876HZNN2;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = (
@@ -7796,7 +7788,7 @@
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- DEVELOPMENT_TEAM = VMGRRW6SG7;
+ DEVELOPMENT_TEAM = 8779C367VK;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = (
@@ -8023,7 +8015,7 @@
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- DEVELOPMENT_TEAM = VMGRRW6SG7;
+ DEVELOPMENT_TEAM = Y7342J76KH;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = (
@@ -8250,7 +8242,7 @@
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- DEVELOPMENT_TEAM = VMGRRW6SG7;
+ DEVELOPMENT_TEAM = ABW92QGFZ7;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = (
@@ -8475,7 +8467,7 @@
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- DEVELOPMENT_TEAM = VMGRRW6SG7;
+ DEVELOPMENT_TEAM = R36WF3S37T;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = (
diff --git a/WhatsNew-beta.json b/WhatsNew-beta.json
index c4d71cec6..ffd4d707e 100755
--- a/WhatsNew-beta.json
+++ b/WhatsNew-beta.json
@@ -89,5 +89,9 @@
"2.9.4-310": "- Fix filters incorrectly set when opening the search from the left menu.",
"2.9.4-311": "- New search period filters in search.\n- Channel logo in TV livestream player page.\n- Application version in settings view and iOS Settings application.\n- Date and time spelling improvements for accessibility.",
"2.9.4-312": "- The player track selection interface has been updated.\n- iOS 13 preliminary support.",
- "2.9.5-313": "- New RTS TV logos."
+ "2.9.5-313": "- New RTS TV logos.",
+ "2.9.6-314": "- Search filters popup on iPad tiny update.\n- New Play scheme URL supported.",
+ "2.9.6-315": "- Dark mode support for iOS 13 (always).",
+ "2.9.6-316": "- AppStore release for iOS 13.",
+ "2.9.6-317": "- AppStore release for iOS 13 (Xcode GM Seed 2)"
}
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
index c010f7ea2..3affa7039 100755
--- a/docs/README.md
+++ b/docs/README.md
@@ -31,7 +31,7 @@ Depending on the business unit, some functionalities might not be available (e.g
## Compatibility
-The project runs on iOS 9 and above and must be opened with the latest Xcode version (currently Xcode 10).
+The project runs on iOS 9 and above and must be opened with the latest Xcode version.
## Contributing
diff --git a/docs/URL_SCHEMES.md b/docs/URL_SCHEMES.md
index 325ab64fb..f1d6a360f 100755
--- a/docs/URL_SCHEMES.md
+++ b/docs/URL_SCHEMES.md
@@ -2,7 +2,7 @@
Play applications can be opened with a custom URL scheme having the following format: `play(srf|rts|rsi|rtr|swi)(-beta|-nightly|-debug)`.
-## Actions
+## Actions (v2 seen 2.9.6 release)
The application supports Apple universal links. Replacing the `http`or `https` scheme of a Play website URL with the corresponding application scheme yields a link which can be opened with the application:
@@ -10,18 +10,17 @@ The application supports Apple universal links. Replacing the `http`or `https` s
The available actions are:
-* Open a media within the player: `[scheme]://open?media=[media_urn]`. An optional `&start-time=[start_time]` parameter can be added to start VOD / AOD playback at the specified position in second.
-* Open a show page: `[scheme]://open?show=[show_urn]`.
-* Open a topic page: `[scheme]://open?topic=[topic_urn]`.
-* Open a module page: `[scheme]://open?module=[module_urn]`.
-* Open a page: `[scheme]://open?page-id=[page_id]`.
- * Home page: `home`.
- * Search page: `search`. Optional `query` and `mediaType` (with `video` or `audio` values) parameters can be provided.
- * Shows A to Z page: `az`. An optional `index` single character parameter can be provided to open the page at the specified index.
- * Shows by date page: `bydate`. An optional `date` parameter with the `yyyy-MM-dd` format can be provided.
-* Open a URL: `[scheme]://open?url=[url]`.
+* Open a media within the player: `[scheme]://media/[media_urn]`. An optional `&start_time=[start_time]` parameter can be added to start VOD / AOD playback at the specified position in second.
+* Open a show page: `[scheme]://show/[show_urn]`.
+* Open a topic page: `[scheme]://topic/[topic_urn]`.
+* Open a module page: `[scheme]://module/[module_urn]`.
+* Open a home page: `[scheme]://home`.
+* Open shows A to Z page: `[scheme]://az`. An optional `index` single character parameter can be provided to open the page at the specified index.
+* Open shows by date page: `[scheme]://bydate`. An optional `date` parameter with the `yyyy-MM-dd` format can be provided.
+* Open search page: `[scheme]://search`. Optional `query` and `media_type` (with `video` or `audio` values) parameters can be provided.
+* Open a URL: `[scheme]://link?url=[url]`.
-For media, show and page links, an optional `&channel-id=[channel_id]` parameter can be added, which resets the homepage to the specified radio channel homepage. If this parameter is not specified or does not match a valid channel, the homepage is reset to the TV one instead.
+For media, show and page links, an optional `&channel_id=[channel_id]` parameter can be added, which resets the homepage to the specified radio channel homepage. If this parameter is not specified or does not match a valid channel, the homepage is reset to the TV one instead.
For a `Debug`, `Nightly` or a `Beta` build, `&server=[server_title]` parameter can be added to force a server selection update. The available server list can be found under *Settings* > *Advanced features* > *Server*.
@@ -37,32 +36,32 @@ Open one of the following links on a mobile device to open the corresponding ite
| Item | Type | Production link | Beta link | Nightly link | Debug link |
|:--:|:--:|:--:|:--:|:--:|:--:|
-| Telegiornale (2018/10/03) | Video | `playrsi://open?media=urn:rsi:video:10889069` | `playrsi-beta://open?media=urn:rsi:video:10889069` | `playrsi-nightly://open?media=urn:rsi:video:10889069` | `playrsi-debug://open?media=urn:rsi:video:10889069` |
-| Radiogiornale | Radio show | `playrsi://open?show=urn:rsi:show:radio:2100980` | `playrsi-beta://open?show=urn:rsi:show:radio:2100980` | `playrsi-nightly://open?show=urn:rsi:show:radio:2100980` | `playrsi-debug://open?show=urn:rsi:show:radio:2100980` |
+| Telegiornale (2018/10/03) | Video | `playrsi://media/urn:rsi:video:10889069` | `playrsi-beta://media/urn:rsi:video:10889069` | `playrsi-nightly://media/urn:rsi:video:10889069` | `playrsi-debug://media/urn:rsi:video:10889069` |
+| Radiogiornale | Radio show | `playrsi://show/urn:rsi:show:radio:2100980` | `playrsi-beta://show/urn:rsi:show:radio:2100980` | `playrsi-nightly://show/urn:rsi:show:radio:2100980` | `playrsi-debug://show/urn:rsi:show:radio:2100980` |
### RTR
| Item | Type | Production link | Beta link | Nightly link | Debug link |
|:--:|:--:|:--:|:--:|:--:|:--:|
-| Telesguard (2018/10/03) | Video | `playrtr://open?media=urn:rtr:video:8e0c23b1-5ea6-463a-b48e-7d474158e992` | `playrtr-beta://open?media=urn:rtr:video:8e0c23b1-5ea6-463a-b48e-7d474158e992` | `playrtr-nightly://open?media=urn:rtr:video:8e0c23b1-5ea6-463a-b48e-7d474158e992` | `playrtr-debug://open?media=urn:rtr:video:8e0c23b1-5ea6-463a-b48e-7d474158e992` |
-| Gratulaziuns | Radio show | `playrtr://open?show=urn:rtr:show:radio:a8b76055-1621-4d01-88c9-421e2ac14828` | `playrtr-beta://open?show=urn:rtr:show:radio:a8b76055-1621-4d01-88c9-421e2ac14828` | `playrtr-nightly://open?show=urn:rtr:show:radio:a8b76055-1621-4d01-88c9-421e2ac14828` | `playrtr-debug://open?show=urn:rtr:show:radio:a8b76055-1621-4d01-88c9-421e2ac14828` |
+| Telesguard (2018/10/03) | Video | `playrtr://media/urn:rtr:video:8e0c23b1-5ea6-463a-b48e-7d474158e992` | `playrtr-beta://media/urn:rtr:video:8e0c23b1-5ea6-463a-b48e-7d474158e992` | `playrtr-nightly://media/urn:rtr:video:8e0c23b1-5ea6-463a-b48e-7d474158e992` | `playrtr-debug://media/urn:rtr:video:8e0c23b1-5ea6-463a-b48e-7d474158e992` |
+| Gratulaziuns | Radio show | `playrtr://show/urn:rtr:show:radio:a8b76055-1621-4d01-88c9-421e2ac14828` | `playrtr-beta://show/urn:rtr:show:radio:a8b76055-1621-4d01-88c9-421e2ac14828` | `playrtr-nightly://show/urn:rtr:show:radio:a8b76055-1621-4d01-88c9-421e2ac14828` | `playrtr-debug://show/urn:rtr:show:radio:a8b76055-1621-4d01-88c9-421e2ac14828` |
### RTS
| Item | Type | Production link | Beta link | Nightly link | Debug link |
|:--:|:--:|:--:|:--:|:--:|:--:|
-| 19h30 (2018/10/03) | Video | `playrts://open?media=urn:rts:video:9890897` | `playrts-beta://open?media=urn:rts:video:9890897` | `playrts-nightly://open?media=urn:rts:video:9890897` | `playrts-debug://open?urn=urn:rts:video:9890897` |
-| Sexomax | Radio show | `playrts://open?show=urn:rts:show:radio:8864883` | `playrts-beta://open?show=urn:rts:show:radio:8864883` | `playrts-nightly://open?show=urn:rts:show:radio:8864883` | `playrts-debug://open?show=urn:rts:show:radio:8864883` |
+| 19h30 (2018/10/03) | Video | `playrts://media/urn:rts:video:9890897` | `playrts-beta://media/urn:rts:video:9890897` | `playrts-nightly://media/urn:rts:video:9890897` | `playrts-debug://open?urn=urn:rts:video:9890897` |
+| Sexomax | Radio show | `playrts://show/urn:rts:show:radio:8864883` | `playrts-beta://show/urn:rts:show:radio:8864883` | `playrts-nightly://show/urn:rts:show:radio:8864883` | `playrts-debug://show/urn:rts:show:radio:8864883` |
### SRF
| Item | Type | Production link | Beta link | Nightly link | Debug link |
|:--:|:--:|:--:|:--:|:--:|:--:|
-| 10vor10 (2018/10/03) | Video | `playsrf://open?media=urn:srf:video:da6fdf91-3e91-46fb-be50-914e47203e45` | `playsrf-beta://open?media=urn:srf:video:da6fdf91-3e91-46fb-be50-914e47203e45` | `playsrf-nightly://open?media=urn:srf:video:da6fdf91-3e91-46fb-be50-914e47203e45` | `playsrf-debug://open?media=urn:srf:video:da6fdf91-3e91-46fb-be50-914e47203e45` |
-| Buchzeichen | Radio show | `playsrf://open?show=urn:srf:show:radio:132857ed-76c6-4659-9e36-ab1e5bdf6e7f` | `playsrf-beta://open?show=urn:srf:show: radio:132857ed-76c6-4659-9e36-ab1e5bdf6e7f` | `playsrf-nightly://open?show=urn:srf:show: radio:132857ed-76c6-4659-9e36-ab1e5bdf6e7f` | `playsrf-debug://open?show=urn:srf:show: radio:132857ed-76c6-4659-9e36-ab1e5bdf6e7f` |
+| 10vor10 (2018/10/03) | Video | `playsrf://media/urn:srf:video:da6fdf91-3e91-46fb-be50-914e47203e45` | `playsrf-beta://media/urn:srf:video:da6fdf91-3e91-46fb-be50-914e47203e45` | `playsrf-nightly://media/urn:srf:video:da6fdf91-3e91-46fb-be50-914e47203e45` | `playsrf-debug://media/urn:srf:video:da6fdf91-3e91-46fb-be50-914e47203e45` |
+| Buchzeichen | Radio show | `playsrf://show/urn:srf:show:radio:132857ed-76c6-4659-9e36-ab1e5bdf6e7f` | `playsrf-beta://show/urn:srf:show: radio:132857ed-76c6-4659-9e36-ab1e5bdf6e7f` | `playsrf-nightly://show/urn:srf:show: radio:132857ed-76c6-4659-9e36-ab1e5bdf6e7f` | `playsrf-debug://show/urn:srf:show: radio:132857ed-76c6-4659-9e36-ab1e5bdf6e7f` |
### SWI
| Item | Type | Production link | Beta link | Nightly link | Debug link |
|:--:|:--:|:--:|:--:|:--:|:--:|
-| Zermatt’s new tri-cable car system | Video | `playswi://open?media=urn:swi:video:44438410` | `playswi-beta://open?media=urn:swi:video:44438410` | `playswi-nightly://open?media=urn:swi:video:44438410` | `playswi-debug://open?media=urn:swi:video:44438410` |
\ No newline at end of file
+| Zermatt’s new tri-cable car system | Video | `playswi://media/urn:swi:video:44438410` | `playswi-beta://media/urn:swi:video:44438410` | `playswi-nightly://media/urn:swi:video:44438410` | `playswi-debug://media/urn:swi:video:44438410` |
\ No newline at end of file