mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
live tv guide improvements
This commit is contained in:
parent
f41b336e87
commit
f4866f7344
10 changed files with 1095 additions and 173 deletions
|
@ -12,7 +12,7 @@
|
|||
}
|
||||
|
||||
.detailSectionHeader + .tvProgram {
|
||||
border-top: 1px solid #444;
|
||||
border-top: 1px solid #404040;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
|||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
border-bottom: 1px solid #444;
|
||||
border-bottom: 1px solid #404040;
|
||||
}
|
||||
|
||||
.tvProgramTimeSlotInner {
|
||||
|
@ -35,12 +35,12 @@
|
|||
.tvProgramInfo {
|
||||
vertical-align: middle;
|
||||
padding: .5em .5em;
|
||||
border-bottom: 1px solid #444;
|
||||
border-bottom: 1px solid #404040;
|
||||
}
|
||||
|
||||
.tvProgramTimeSlot + .tvProgramInfo {
|
||||
margin-left: 80px;
|
||||
border-left: 1px solid #444;
|
||||
border-left: 1px solid #404040;
|
||||
}
|
||||
|
||||
.tvProgramCurrentTimeSlot {
|
||||
|
@ -137,9 +137,23 @@
|
|||
}
|
||||
|
||||
.timeslotHeaders {
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
white-space: nowrap;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.mobileGuide .timeslotHeaders {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.programContainer {
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
margin-top: 44px;
|
||||
}
|
||||
|
||||
.mobileGuide .programContainer {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.channelPrograms {
|
||||
|
@ -157,8 +171,8 @@
|
|||
|
||||
.timeslotCell {
|
||||
display: inline-block;
|
||||
border-bottom: 1px solid #444;
|
||||
border-left: 1px solid #444;
|
||||
border-bottom: 1px solid #404040;
|
||||
border-left: 1px solid #404040;
|
||||
border-collapse: collapse;
|
||||
position: relative;
|
||||
}
|
||||
|
@ -166,9 +180,8 @@
|
|||
.channelHeaderCell, .channelTimeslotHeader {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
border-bottom: 1px solid #444;
|
||||
border-left: 1px solid #444;
|
||||
border-right: 1px solid #444;
|
||||
border-bottom: 1px solid #404040;
|
||||
border-right: 1px solid #404040;
|
||||
width: 189px;
|
||||
}
|
||||
|
||||
|
@ -183,7 +196,7 @@
|
|||
}
|
||||
|
||||
.timeslotHeader, .channelTimeslotHeader {
|
||||
height: 28px;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.channelHeaderCellInner {
|
||||
|
@ -200,16 +213,12 @@
|
|||
}
|
||||
|
||||
.channelList {
|
||||
overflow-y: hidden;
|
||||
overflow-x: scroll;
|
||||
float: left;
|
||||
border-bottom: 4px solid #3B3B3B;
|
||||
}
|
||||
|
||||
.programGrid {
|
||||
overflow-y: scroll;
|
||||
overflow-x: scroll;
|
||||
padding-bottom: 4px;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.programGrid, .timeslotHeaders {
|
||||
|
@ -271,81 +280,7 @@
|
|||
top: 7px;
|
||||
}
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: 220px;
|
||||
}
|
||||
|
||||
@media (min-height: 500px) {
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: 360px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 600px) {
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 700px) {
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 800px) {
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: 600px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 900px) {
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: 700px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 1000px) {
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: 800px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 1100px) {
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: 900px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 1200px) {
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: 1000px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 1300px) {
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: 1100px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 1400px) {
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: 1200px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
@media (max-width: 600px) {
|
||||
|
||||
.guideChannelImage {
|
||||
display: none;
|
||||
|
@ -362,4 +297,16 @@
|
|||
.programGrid, .timeslotHeaders {
|
||||
margin-left: 90px;
|
||||
}
|
||||
|
||||
.currentDate {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.currentDay {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.channelList, .programGrid {
|
||||
height: auto !important;
|
||||
}
|
|
@ -26,6 +26,24 @@
|
|||
<div class="ehsContent homeEhsContent">
|
||||
<div class="sections"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div data-role="popup" class="popupConfigureViews" data-overlay-theme="b" data-theme="a" data-dismissible="false" data-positionto="window">
|
||||
<div class="ui-bar-a" style="text-align: center; padding: 0 20px; position: relative;">
|
||||
|
||||
<h3 class="identificationHeader">${HeaderMyPreferences}</h3>
|
||||
</div>
|
||||
|
||||
<div data-role="content" style="max-width:600px;">
|
||||
|
||||
<h1>${HeaderWelcomeExclamation}</h1>
|
||||
<p>${MyPreferencesWelcomeMessage1}</p>
|
||||
<p style="margin:1.5em 0 2em;">${MyPreferencesWelcomeMessage2}</p>
|
||||
<a href="#" data-role="button" data-icon="action" data-theme="b" data-mini="true" class="btnMyPreferences">${ButtonMyPreferencesWelcomeYes}</a>
|
||||
<a href="#" data-rel="back" data-role="button" data-icon="delete" data-mini="true">${ButtonMyPreferencesWelcomeNo}</a>
|
||||
<div class="fieldDescription" style="margin-top:1em;">${ToAccessPreferencesHelp}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -15,27 +15,31 @@
|
|||
</div>
|
||||
<div data-role="content" style="padding-top: 5px;padding-left:0!important;padding-right:0!important;">
|
||||
|
||||
<div>
|
||||
<div class="viewSettings">
|
||||
<select id="selectDate" data-mini="true" data-inline="true">
|
||||
</select>
|
||||
<div style="display: inline-block; vertical-align: middle;" class="channelPaging">
|
||||
<div class="tvGuide">
|
||||
<div style="white-space: nowrap;position:fixed;top:99px;left:0;z-index:100; max-width: 100%;">
|
||||
<div class="channelTimeslotHeader">
|
||||
<div style="padding-top:4px;">
|
||||
<a href="#popupConfig" data-rel="popup" class="accentButton" style="display:block;padding-left:5px;"><i class="fa fa-calendar"></i><span class="currentDate"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div style="position: relative; margin: 0 auto; display: inline-block; text-align: left; max-width: 100%;">
|
||||
|
||||
<div style="white-space: nowrap;">
|
||||
<div class="channelTimeslotHeader"> </div>
|
||||
<div class="timeslotHeaders"></div>
|
||||
</div>
|
||||
|
||||
<div style="white-space: nowrap;">
|
||||
<div class="programContainer">
|
||||
|
||||
<div class="channelList"></div>
|
||||
<div class="programGrid"></div>
|
||||
</div>
|
||||
<div class="channelPaging"></div>
|
||||
</div>
|
||||
<div data-role="popup" id="popupConfig" data-theme="b">
|
||||
<div class="ui-bar-a" style="text-align: center; padding: 0 20px; position: relative;">
|
||||
|
||||
<h3 class="identificationHeader" style="margin:.5em 0;">${HeaderSelectDate}</h3>
|
||||
</div>
|
||||
<div data-role="content">
|
||||
<select id="selectDate" data-mini="true" data-inline="true"></select>
|
||||
<a href="#" data-rel="back" data-role="button" data-mini="true" data-icon="delete">${ButtonCancel}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div data-role="popup" class="popupLoading" data-overlay-theme="b" data-theme="b" data-dismissible="false" style="max-width: 250px;" data-history="false">
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<title>Emby</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="liveTvSuggestedPage" data-role="page" class="page libraryPage liveTvPage" data-contextname="${HeaderLiveTv}">
|
||||
<div id="liveTvSuggestedPage" data-role="page" class="page libraryPage liveTvPage backdropPage globalBackdropPage" data-contextname="${HeaderLiveTv}" data-backdroptype="series,movie">
|
||||
<div class="libraryViewNav">
|
||||
<a href="#" class="ui-btn-active">${TabSuggestions}</a>
|
||||
<a href="livetvguide.html">${TabGuide}</a>
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
return deferred.promise();
|
||||
}
|
||||
|
||||
function showBackdrop(type) {
|
||||
function showBackdrop(type, parentId) {
|
||||
|
||||
var apiClient = ConnectionManager.currentApiClient();
|
||||
|
||||
|
@ -67,9 +67,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
getBackdropItemIds(apiClient, Dashboard.getCurrentUserId(),
|
||||
type,
|
||||
LibraryMenu.getTopParentId()).done(function (images) {
|
||||
getBackdropItemIds(apiClient, Dashboard.getCurrentUserId(), type, parentId).done(function (images) {
|
||||
|
||||
if (images.length) {
|
||||
|
||||
|
@ -154,17 +152,21 @@
|
|||
|
||||
var page = this;
|
||||
|
||||
if (!$(page).hasClass('staticBackdropPage')) {
|
||||
var $page = $(page);
|
||||
|
||||
if ($(page).hasClass('backdropPage')) {
|
||||
if (!$page.hasClass('staticBackdropPage')) {
|
||||
|
||||
if ($page.hasClass('backdropPage')) {
|
||||
|
||||
if (enabled()) {
|
||||
var type = page.getAttribute('data-backdroptype');
|
||||
|
||||
showBackdrop(type);
|
||||
var parentId = $page.hasClass('globalBackdropPage') ? '' : LibraryMenu.getTopParentId();
|
||||
|
||||
showBackdrop(type, parentId);
|
||||
|
||||
} else {
|
||||
$(page).removeClass('backdropPage');
|
||||
$page.removeClass('backdropPage');
|
||||
clearBackdrop();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
|
||||
function loadlibraryButtons(elem, userId, index) {
|
||||
|
||||
getUserViews(userId).done(function (items) {
|
||||
return getUserViews(userId).done(function (items) {
|
||||
|
||||
var html = '<br/>';
|
||||
|
||||
|
@ -172,7 +172,7 @@
|
|||
UserId: userId
|
||||
};
|
||||
|
||||
ApiClient.getJSON(ApiClient.getUrl("Channels/Items/Latest", options)).done(function (result) {
|
||||
return ApiClient.getJSON(ApiClient.getUrl("Channels/Items/Latest", options)).done(function (result) {
|
||||
|
||||
var html = '';
|
||||
|
||||
|
@ -203,7 +203,7 @@
|
|||
$(elem).removeClass('hiddenSectionOnMobile');
|
||||
}
|
||||
|
||||
getUserViews(user.Id).done(function (items) {
|
||||
return getUserViews(user.Id).done(function (items) {
|
||||
|
||||
var html = '';
|
||||
|
||||
|
@ -259,7 +259,7 @@
|
|||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb"
|
||||
};
|
||||
|
||||
ApiClient.getItems(userId, options).done(function (result) {
|
||||
return ApiClient.getItems(userId, options).done(function (result) {
|
||||
|
||||
var html = '';
|
||||
|
||||
|
@ -307,7 +307,7 @@
|
|||
SupportsLatestItems: true
|
||||
});
|
||||
|
||||
ApiClient.getJSON(ApiClient.getUrl("Channels", options)).done(function (result) {
|
||||
return ApiClient.getJSON(ApiClient.getUrl("Channels", options)).done(function (result) {
|
||||
|
||||
var channels = result.Items;
|
||||
|
||||
|
@ -375,7 +375,7 @@
|
|||
|
||||
function loadLatestLiveTvRecordings(elem, userId, index) {
|
||||
|
||||
ApiClient.getLiveTvRecordings({
|
||||
return ApiClient.getLiveTvRecordings({
|
||||
|
||||
userId: userId,
|
||||
limit: 5,
|
||||
|
@ -459,36 +459,40 @@
|
|||
var elem = $('.section' + index, page);
|
||||
|
||||
if (section == 'latestmedia') {
|
||||
Sections.loadRecentlyAdded(elem, user);
|
||||
return Sections.loadRecentlyAdded(elem, user);
|
||||
}
|
||||
else if (section == 'librarytiles') {
|
||||
Sections.loadLibraryTiles(elem, user, 'backdrop', index, false, showLibraryTileNames);
|
||||
return Sections.loadLibraryTiles(elem, user, 'backdrop', index, false, showLibraryTileNames);
|
||||
}
|
||||
else if (section == 'smalllibrarytiles') {
|
||||
Sections.loadLibraryTiles(elem, user, 'homePageSmallBackdrop', index, false, showLibraryTileNames);
|
||||
return Sections.loadLibraryTiles(elem, user, 'homePageSmallBackdrop', index, false, showLibraryTileNames);
|
||||
}
|
||||
else if (section == 'smalllibrarytiles-automobile') {
|
||||
Sections.loadLibraryTiles(elem, user, 'homePageSmallBackdrop', index, true, showLibraryTileNames);
|
||||
return Sections.loadLibraryTiles(elem, user, 'homePageSmallBackdrop', index, true, showLibraryTileNames);
|
||||
}
|
||||
else if (section == 'librarytiles-automobile') {
|
||||
Sections.loadLibraryTiles(elem, user, 'backdrop', index, true, showLibraryTileNames);
|
||||
return Sections.loadLibraryTiles(elem, user, 'backdrop', index, true, showLibraryTileNames);
|
||||
}
|
||||
else if (section == 'librarybuttons') {
|
||||
Sections.loadlibraryButtons(elem, userId, index);
|
||||
return Sections.loadlibraryButtons(elem, userId, index);
|
||||
}
|
||||
else if (section == 'resume') {
|
||||
Sections.loadResume(elem, userId);
|
||||
return Sections.loadResume(elem, userId);
|
||||
}
|
||||
|
||||
else if (section == 'latesttvrecordings') {
|
||||
Sections.loadLatestLiveTvRecordings(elem, userId);
|
||||
return Sections.loadLatestLiveTvRecordings(elem, userId);
|
||||
}
|
||||
else if (section == 'latestchannelmedia') {
|
||||
Sections.loadLatestChannelMedia(elem, userId);
|
||||
return Sections.loadLatestChannelMedia(elem, userId);
|
||||
|
||||
} else {
|
||||
|
||||
elem.empty();
|
||||
|
||||
var deferred = DeferredBuilder.Deferred();
|
||||
deferred.resolve();
|
||||
return deferred.promise();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -509,13 +513,17 @@
|
|||
elem.html(html);
|
||||
}
|
||||
|
||||
var promises = [];
|
||||
|
||||
for (i = 0, length = sectionCount; i < length; i++) {
|
||||
|
||||
loadSection(page, user, displayPreferences, i);
|
||||
}
|
||||
promises.push(loadSection(page, user, displayPreferences, i));
|
||||
}
|
||||
|
||||
var homePageDismissValue = '5';
|
||||
return $.when(promises);
|
||||
}
|
||||
|
||||
var homePageDismissValue = '12';
|
||||
var homePageTourKey = 'homePageTour';
|
||||
|
||||
function dismissWelcome(page, userId) {
|
||||
|
@ -570,11 +578,25 @@
|
|||
afterClose: function () {
|
||||
dismissWelcome(page, userId);
|
||||
$('.welcomeMessage', page).hide();
|
||||
|
||||
loadConfigureViewsWelcomeMessage(page, userId);
|
||||
},
|
||||
hideBarsDelay: 30000
|
||||
});
|
||||
}
|
||||
|
||||
function loadConfigureViewsWelcomeMessage(page, userId) {
|
||||
|
||||
$('.btnMyPreferences', page).attr('href', 'mypreferencesdisplay.html?userId=' + userId);
|
||||
|
||||
// Need the timeout because previous methods in the chain have popups that will be in the act of closing
|
||||
setTimeout(function () {
|
||||
|
||||
$('.popupConfigureViews', page).popup('open');
|
||||
|
||||
}, 500);
|
||||
}
|
||||
|
||||
$(document).on('pageinit', "#indexPage", function () {
|
||||
|
||||
var page = this;
|
||||
|
@ -593,11 +615,12 @@
|
|||
|
||||
ApiClient.getDisplayPreferences('home', userId, 'webclient').done(function (result) {
|
||||
|
||||
showWelcomeIfNeeded(page, result);
|
||||
|
||||
Dashboard.getCurrentUser().done(function (user) {
|
||||
|
||||
loadSections(page, user, result);
|
||||
loadSections(page, user, result).done(function () {
|
||||
showWelcomeIfNeeded(page, result);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
var channelQuery = {
|
||||
|
||||
StartIndex: 0,
|
||||
Limit: 20,
|
||||
Limit: 50,
|
||||
EnableFavoriteSorting: true
|
||||
};
|
||||
var channelsPromise;
|
||||
|
@ -90,12 +90,6 @@
|
|||
channelQuery.StartIndex -= channelQuery.Limit;
|
||||
reloadChannels(page);
|
||||
});
|
||||
|
||||
$('.selectPageSize', page).on('change', function () {
|
||||
channelQuery.Limit = parseInt(this.value);
|
||||
channelQuery.StartIndex = 0;
|
||||
reloadChannels(page);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -269,13 +263,13 @@
|
|||
html += '<div class="guideProgramTime">';
|
||||
|
||||
if (program.IsLive) {
|
||||
html += '<span class="liveTvProgram">'+Globalize.translate('LabelLiveProgram')+' </span>';
|
||||
html += '<span class="liveTvProgram">' + Globalize.translate('LabelLiveProgram') + ' </span>';
|
||||
}
|
||||
else if (program.IsPremiere) {
|
||||
html += '<span class="premiereTvProgram">'+Globalize.translate('LabelPremiereProgram')+' </span>';
|
||||
html += '<span class="premiereTvProgram">' + Globalize.translate('LabelPremiereProgram') + ' </span>';
|
||||
}
|
||||
else if (program.IsSeries && !program.IsRepeat) {
|
||||
html += '<span class="newTvProgram">'+Globalize.translate('LabelNewProgram')+' </span>';
|
||||
html += '<span class="newTvProgram">' + Globalize.translate('LabelNewProgram') + ' </span>';
|
||||
}
|
||||
|
||||
html += LiveTvHelpers.getDisplayTime(program.StartDateLocal);
|
||||
|
@ -365,12 +359,27 @@
|
|||
renderPrograms(page, date, channels, programs);
|
||||
}
|
||||
|
||||
var gridScrolling = false;
|
||||
var headersScrolling = false;
|
||||
function onProgramGridScroll(page, elem) {
|
||||
|
||||
if (!headersScrolling) {
|
||||
gridScrolling = true;
|
||||
var grid = $(elem);
|
||||
|
||||
grid.prev().scrollTop(grid.scrollTop());
|
||||
$('.timeslotHeaders', page).scrollLeft(grid.scrollLeft());
|
||||
gridScrolling = false;
|
||||
}
|
||||
}
|
||||
|
||||
function onTimeslotHeadersScroll(page, elem) {
|
||||
|
||||
if (!gridScrolling) {
|
||||
headersScrolling = true;
|
||||
elem = $(elem);
|
||||
$('.programGrid', page).scrollLeft(elem.scrollLeft());
|
||||
headersScrolling = false;
|
||||
}
|
||||
}
|
||||
|
||||
function changeDate(page, date) {
|
||||
|
@ -385,6 +394,10 @@
|
|||
gridLocalEndDateMs = clone.getTime() - 1;
|
||||
|
||||
reloadGuide(page);
|
||||
|
||||
var text = LibraryBrowser.getFutureDateText(date);
|
||||
text = '<span class="currentDay">' + text.replace(' ', ' </span>');
|
||||
$('.currentDate', page).html(text);
|
||||
}
|
||||
|
||||
function setDateRange(page, guideInfo) {
|
||||
|
@ -446,9 +459,21 @@
|
|||
date.setTime(parseInt(this.value));
|
||||
|
||||
changeDate(page, date);
|
||||
|
||||
$('#popupConfig', page).popup('close');
|
||||
});
|
||||
|
||||
if ($.browser.mobile) {
|
||||
$('.tvGuide', page).addClass('mobileGuide');
|
||||
} else {
|
||||
|
||||
$('.tvGuide', page).removeClass('mobileGuide');
|
||||
|
||||
$('.timeslotHeaders', page).on('scroll', function () {
|
||||
|
||||
onTimeslotHeadersScroll(page, this);
|
||||
});
|
||||
}
|
||||
|
||||
}).on('pagebeforeshow', "#liveTvGuidePage", function () {
|
||||
|
||||
var page = this;
|
||||
|
|
|
@ -118,10 +118,10 @@
|
|||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Playlist",
|
||||
Recursive: true,
|
||||
ParentId: parentId,
|
||||
Fields: "PrimaryImageAspectRatio,SortName,CumulativeRunTimeTicks,CanDelete,SyncInfo",
|
||||
StartIndex: 0,
|
||||
Limit: 9
|
||||
Limit: 9,
|
||||
MediaTypes: "Audio"
|
||||
};
|
||||
|
||||
ApiClient.getItems(Dashboard.getCurrentUserId(), options).done(function (result) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<title>Emby</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="songsPage" data-role="page" class="page libraryPage">
|
||||
<div id="songsPage" data-role="page" class="page libraryPage backdropPage" data-backdroptype="musicartist">
|
||||
<div class="libraryViewNav scopedLibraryViewNav">
|
||||
<a href="musicrecommended.html">${TabSuggestions}</a>
|
||||
<a href="#" class="ui-btn-active">${TabSongs}</a>
|
||||
|
|
907
dashboard-ui/thirdparty/browser.js
vendored
907
dashboard-ui/thirdparty/browser.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue