Merge branch 'master' into master
|
@ -5,12 +5,11 @@
|
|||
<div class="verticalSection">
|
||||
<div class="sectionTitleContainer flex align-items-center">
|
||||
<h1 class="sectionTitle pluginName"></h1>
|
||||
<a is="emby-linkbutton" class="raised button-alt headerHelpButton" target="_blank" href="https://docs.jellyfin.org/general/server/plugins/index.html">${Help}</a>
|
||||
<a is="emby-linkbutton" rel="noopener noreferrer" class="raised button-alt headerHelpButton" target="_blank" href="https://docs.jellyfin.org/general/server/plugins/index.html">${Help}</a>
|
||||
</div>
|
||||
|
||||
<p id="tagline" style="font-style: italic;"></p>
|
||||
<p id="pPreviewImage"></p>
|
||||
<p id="overview"></p>
|
||||
<p id="overview" style="font-style: italic;"></p>
|
||||
<p id="description"></p>
|
||||
</div>
|
||||
|
||||
<div class="verticalSection">
|
||||
|
@ -28,7 +27,6 @@
|
|||
</button>
|
||||
<div class="fieldDescription">${ServerRestartNeededAfterPluginInstall}</div>
|
||||
</div>
|
||||
<p id="nonServerMsg"></p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -37,9 +35,6 @@
|
|||
<div is="emby-collapse" title="${HeaderDeveloperInfo}">
|
||||
<div class="collapseContent">
|
||||
<p id="developer"></p>
|
||||
<p id="pViewWebsite" style="display: none;">
|
||||
<a is="emby-linkbutton" class="button-link" href="#" target="_blank">${ButtonViewWebsite}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<form class="addServerForm" style="margin: 0 auto;">
|
||||
<h1>${HeaderConnectToServer}</h1>
|
||||
<div class="inputContainer">
|
||||
<input is="emby-input" type="text" id="txtServerHost" required="required" label="${LabelServerHost}" autocomplete="off" spellcheck="false" autocapitalize="none" autocorrect="off" />
|
||||
<input is="emby-input" type="url" id="txtServerHost" required="required" label="${LabelServerHost}"/>
|
||||
<div class="fieldDescription">${LabelServerHostHelp}</div>
|
||||
</div>
|
||||
<br />
|
||||
|
|
|
@ -4,18 +4,19 @@
|
|||
<div class="detailSectionHeader">
|
||||
<h2 style="margin:.6em 0;vertical-align:middle;display:inline-block;">${HeaderApiKeys}</h2>
|
||||
<button is="emby-button" type="button" class="fab btnNewKey submit" style="margin-left:1em;" title="${ButtonAdd}">
|
||||
<i class="md-icon">add</i>
|
||||
<span class="material-icons add" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<p>${HeaderApiKeysHelp}</p>
|
||||
<br />
|
||||
<table class="tblApiKeys detailTable">
|
||||
<caption class="clipForScreenReader">${ApiKeysCaption}</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="detailTableHeaderCell"></th>
|
||||
<th class="detailTableHeaderCell">${HeaderApiKey}</th>
|
||||
<th class="detailTableHeaderCell">${HeaderApp}</th>
|
||||
<th class="detailTableHeaderCell">${HeaderDateIssued}</th>
|
||||
<th scope="col" class="detailTableHeaderCell"></th>
|
||||
<th scope="col" class="detailTableHeaderCell">${HeaderApiKey}</th>
|
||||
<th scope="col" class="detailTableHeaderCell">${HeaderApp}</th>
|
||||
<th scope="col" class="detailTableHeaderCell">${HeaderDateIssued}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="resultBody"></tbody>
|
||||
|
|
|
@ -9,4 +9,4 @@
|
|||
vertical-align: middle;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,262 +1,318 @@
|
|||
.dashboardColumn,
|
||||
.dashboardSections {
|
||||
flex-direction: column;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
}
|
||||
|
||||
.dashboardFooter {
|
||||
margin-top: 3.5em;
|
||||
text-align: center
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dashboardFooter a {
|
||||
margin: 0 .7em
|
||||
margin: 0 0.7em;
|
||||
}
|
||||
|
||||
progress {
|
||||
appearance: none;
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
background: #ccc !important
|
||||
background: #ccc !important;
|
||||
}
|
||||
|
||||
progress[role]:after {
|
||||
background-image: none
|
||||
progress[role]::after {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
progress::-webkit-progress-bar {
|
||||
background: #ccc
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
progress::-moz-progress-bar {
|
||||
background-color: #00a4dc
|
||||
background-color: #00a4dc;
|
||||
}
|
||||
|
||||
progress::-webkit-progress-value {
|
||||
background-color: #00a4dc
|
||||
background-color: #00a4dc;
|
||||
}
|
||||
|
||||
progress[aria-valuenow]:before {
|
||||
border-radius: .4em;
|
||||
background-color: #00a4dc
|
||||
progress[aria-valuenow]::before {
|
||||
border-radius: 0.4em;
|
||||
background-color: #00a4dc;
|
||||
}
|
||||
|
||||
.localnav {
|
||||
margin-bottom: 2.2em !important
|
||||
margin-bottom: 2.2em !important;
|
||||
}
|
||||
|
||||
@media all and (min-width:50em) {
|
||||
|
||||
.type-interior>.ui-panel-content-wrap>div[data-role=content],
|
||||
.type-interior>div[data-role=content] {
|
||||
@media all and (min-width: 50em) {
|
||||
.type-interior > div[data-role=content],
|
||||
.type-interior > .ui-panel-content-wrap > div[data-role=content] {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
padding-top: 0;
|
||||
overflow: hidden
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboardDocument .dashboardEntryHeaderButton,
|
||||
.dashboardDocument .lnkManageServer {
|
||||
display: none !important
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.adminDrawerLogo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.layout-mobile .adminDrawerLogo {
|
||||
padding: 1.5em 1em 1.2em;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
margin-bottom: 1em;
|
||||
display: block
|
||||
display: block;
|
||||
}
|
||||
|
||||
.adminDrawerLogo img {
|
||||
height: 4em
|
||||
height: 4em;
|
||||
}
|
||||
|
||||
a[data-role=button] {
|
||||
background: #292929 !important;
|
||||
background-clip: padding-box;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-user-select: none;
|
||||
-webkit-background-clip: padding-box;
|
||||
cursor: pointer !important;
|
||||
font-family: inherit !important;
|
||||
font-weight: 500 !important;
|
||||
margin: 0 0.25em !important;
|
||||
display: inline-block;
|
||||
padding: 0.8em 1em;
|
||||
text-align: center;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
div[data-role=controlgroup] a[data-role=button] {
|
||||
display: inline-block !important;
|
||||
margin: 0 !important;
|
||||
-webkit-box-shadow: none !important;
|
||||
box-shadow: none !important;
|
||||
border-radius: 0
|
||||
-webkit-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
div[data-role=controlgroup] a[data-role=button]:first-child {
|
||||
border-bottom-left-radius: .3125em;
|
||||
border-top-left-radius: .3125em
|
||||
-webkit-border-bottom-left-radius: 0.3125em;
|
||||
border-bottom-left-radius: 0.3125em;
|
||||
-webkit-border-top-left-radius: 0.3125em;
|
||||
border-top-left-radius: 0.3125em;
|
||||
}
|
||||
|
||||
div[data-role=controlgroup] a[data-role=button]:last-child {
|
||||
border-bottom-right-radius: .3125em;
|
||||
border-top-right-radius: .3125em
|
||||
-webkit-border-bottom-right-radius: 0.3125em;
|
||||
border-bottom-right-radius: 0.3125em;
|
||||
-webkit-border-top-right-radius: 0.3125em;
|
||||
border-top-right-radius: 0.3125em;
|
||||
}
|
||||
|
||||
div[data-role=controlgroup] a[data-role=button]+a[data-role=button] {
|
||||
div[data-role=controlgroup] a[data-role=button] + a[data-role=button] {
|
||||
border-left-width: 0 !important;
|
||||
margin: 0 0 0 -.4em !important
|
||||
margin: 0 0 0 -0.4em !important;
|
||||
}
|
||||
|
||||
div[data-role=controlgroup] a.ui-btn-active {
|
||||
background: #00a4dc !important;
|
||||
color: #292929 !important
|
||||
color: #292929 !important;
|
||||
}
|
||||
|
||||
.header .imageLink {
|
||||
display: inline-block
|
||||
.sessionAppInfo img {
|
||||
max-width: 40px;
|
||||
max-height: 40px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.header .imageLink img {
|
||||
height: 2.1em;
|
||||
vertical-align: middle
|
||||
}
|
||||
|
||||
.content-primary {
|
||||
padding-top: 6em;
|
||||
padding-right: 1em;
|
||||
padding-left: 1em
|
||||
}
|
||||
|
||||
.withTabs .content-primary {
|
||||
padding-top: 9em !important
|
||||
}
|
||||
|
||||
@media all and (min-width:40em) {
|
||||
.content-primary {
|
||||
padding-top: 7em
|
||||
}
|
||||
|
||||
.withTabs .content-primary {
|
||||
padding-top: 10em !important
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width:84em) {
|
||||
.withTabs .content-primary {
|
||||
padding-top: 7em !important
|
||||
}
|
||||
}
|
||||
|
||||
.content-primary ul:first-child {
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
.dashboardSections {
|
||||
display: flex;
|
||||
flex-direction: column
|
||||
}
|
||||
|
||||
.dashboardColumn {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 1
|
||||
}
|
||||
|
||||
.activeSession:not(.playingSession) .sessionNowPlayingContent {
|
||||
display: none
|
||||
}
|
||||
|
||||
.dashboardSection {
|
||||
flex-shrink: 0;
|
||||
margin: 0 0 2em
|
||||
}
|
||||
|
||||
.dashboardSection h3 {
|
||||
margin-top: .5em;
|
||||
margin-bottom: .5em
|
||||
}
|
||||
|
||||
.activeRecordingItems>.card {
|
||||
width: 50%
|
||||
}
|
||||
|
||||
@media all and (min-width:70em) {
|
||||
.dashboardSections {
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row
|
||||
}
|
||||
|
||||
.dashboardColumn-2-60 {
|
||||
width: 46%
|
||||
}
|
||||
|
||||
.dashboardColumn-2-40 {
|
||||
width: 27%
|
||||
}
|
||||
|
||||
.dashboardSection {
|
||||
padding: 0 1.5em
|
||||
}
|
||||
|
||||
.activeRecordingItems>.card {
|
||||
width: 25%
|
||||
}
|
||||
}
|
||||
|
||||
.premiumBanner img {
|
||||
position: absolute;
|
||||
text-align: right;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 4.4em;
|
||||
height: 4.4em
|
||||
}
|
||||
|
||||
.wizardContent {
|
||||
max-width: 62em;
|
||||
padding: .5em 2em 1em;
|
||||
margin: 0 auto;
|
||||
background: #fff
|
||||
}
|
||||
|
||||
.wizardNavigation {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.wizardContent form {
|
||||
max-width: 100%
|
||||
.appLinks img {
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.wizardContent h2 img {
|
||||
height: 2.5em;
|
||||
vertical-align: middle;
|
||||
margin-right: .5em;
|
||||
margin-right: 0.5em;
|
||||
position: relative;
|
||||
top: -.3em
|
||||
top: -0.3em;
|
||||
}
|
||||
|
||||
.scheduledTaskPaperIconItem {
|
||||
outline: 0 !important
|
||||
.header .imageLink {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.activeSession {
|
||||
width: 100% !important
|
||||
.header .imageLink img {
|
||||
height: 2.1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.activitylogUserPhoto {
|
||||
height:1.71em;
|
||||
width:1.71em;
|
||||
border-radius:100%;
|
||||
margin-right:.5em;
|
||||
background-size:cover;
|
||||
background-repeat:no-repeat;
|
||||
background-position:center;
|
||||
.content-primary {
|
||||
padding-top: 6em;
|
||||
padding-right: 1em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
@media all and (min-width:40em) {
|
||||
.activeSession {
|
||||
width: 100% !important
|
||||
.withTabs .content-primary {
|
||||
padding-top: 9em !important;
|
||||
}
|
||||
|
||||
@media all and (min-width: 40em) {
|
||||
.content-primary {
|
||||
padding-top: 4.6em;
|
||||
}
|
||||
|
||||
.withTabs .content-primary {
|
||||
padding-top: 10em !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width:50em) {
|
||||
@media all and (min-width: 84em) {
|
||||
.withTabs .content-primary {
|
||||
padding-top: 7em !important;
|
||||
}
|
||||
}
|
||||
|
||||
.content-primary ul:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.dashboardSections {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.dashboardColumn {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-flex-shrink: 0;
|
||||
flex-shrink: 0;
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-flex-grow: 1;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.sessionNowPlayingContent {
|
||||
-webkit-background-size: cover;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.activeSession:not(.playingSession) .sessionNowPlayingContent {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dashboardSection {
|
||||
-webkit-flex-shrink: 0;
|
||||
flex-shrink: 0;
|
||||
margin: 0 0 2em;
|
||||
}
|
||||
|
||||
.dashboardSection h3 {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.activeRecordingItems > .card {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
@media all and (min-width: 70em) {
|
||||
.dashboardSections {
|
||||
-webkit-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-flex-direction: row;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.dashboardColumn-2-60 {
|
||||
width: 46%;
|
||||
}
|
||||
|
||||
.dashboardColumn-2-40 {
|
||||
width: 27%;
|
||||
}
|
||||
|
||||
.dashboardSection {
|
||||
padding: 0 1.5em;
|
||||
}
|
||||
|
||||
.activeRecordingItems > .card {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
.wizardContent {
|
||||
max-width: 62em;
|
||||
padding: 0.5em 2em 1em;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.wizardNavigation {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.wizardContent form {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.scheduledTaskPaperIconItem {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
.activeSession {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.activitylogUserPhoto {
|
||||
height: 1.71em;
|
||||
width: 1.71em;
|
||||
border-radius: 100%;
|
||||
margin-right: 0.5em;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
@media all and (min-width: 40em) {
|
||||
.activeSession {
|
||||
width: 50% !important
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 50em) {
|
||||
.activeSession {
|
||||
width: 50% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sessionCardFooter {
|
||||
padding-top: .5em !important;
|
||||
padding-top: 0.5em !important;
|
||||
padding-bottom: 1em !important;
|
||||
border-top: 1px solid #eee;
|
||||
text-align: center;
|
||||
position: relative
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sessionAppInfo {
|
||||
|
@ -265,22 +321,11 @@ div[data-role=controlgroup] a.ui-btn-active {
|
|||
}
|
||||
|
||||
.sessionCardButtons {
|
||||
min-height: 2.7em
|
||||
min-height: 2.7em;
|
||||
}
|
||||
|
||||
.sessionCardButton {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.sessionNowPlayingContent {
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sessionNowPlayingInnerContent {
|
||||
|
@ -289,23 +334,23 @@ div[data-role=controlgroup] a.ui-btn-active {
|
|||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
font-weight: 400
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.sessionNowPlayingContent-withbackground+.sessionNowPlayingInnerContent {
|
||||
.sessionNowPlayingContent-withbackground + .sessionNowPlayingInnerContent {
|
||||
color: #fff !important;
|
||||
background: rgba(0, 0, 0, .7)
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
.sessionAppName {
|
||||
vertical-align: top;
|
||||
max-width: 200px
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.sessionNowPlayingDetails {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
@ -315,12 +360,6 @@ div[data-role=controlgroup] a.ui-btn-active {
|
|||
padding: 0.8em 0.5em;
|
||||
}
|
||||
|
||||
.sessionAppInfo img {
|
||||
max-width: 40px;
|
||||
max-height: 40px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.sessionNowPlayingTime {
|
||||
flex-shrink: 0;
|
||||
align-self: flex-end;
|
||||
|
@ -332,6 +371,13 @@ div[data-role=controlgroup] a.ui-btn-active {
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.playbackProgress,
|
||||
.transcodingProgress {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.activeSession .playbackProgress,
|
||||
.activeSession .transcodingProgress {
|
||||
position: absolute;
|
||||
|
@ -342,13 +388,6 @@ div[data-role=controlgroup] a.ui-btn-active {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.playbackProgress,
|
||||
.transcodingProgress {
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.playbackProgress > div {
|
||||
z-index: 1000;
|
||||
background-color: #00a4dc;
|
||||
|
@ -358,70 +397,70 @@ div[data-role=controlgroup] a.ui-btn-active {
|
|||
background-color: #dd4919;
|
||||
}
|
||||
|
||||
@media all and (max-width:34.375em) {
|
||||
@media all and (max-width: 34.375em) {
|
||||
.sessionAppName {
|
||||
max-width: 160px
|
||||
max-width: 160px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width:31.25em) {
|
||||
@media all and (max-width: 31.25em) {
|
||||
.sessionAppName {
|
||||
max-width: 150px
|
||||
max-width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.disabledUser {
|
||||
filter: grayscale(100%)
|
||||
-webkit-filter: grayscale(100%);
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
.disabledUserBanner {
|
||||
margin: 0 0 2em
|
||||
margin: 0 0 2em;
|
||||
}
|
||||
|
||||
.appLinks a {
|
||||
text-decoration: none !important
|
||||
}
|
||||
|
||||
.appLinks a+a {
|
||||
margin-left: 5px
|
||||
}
|
||||
|
||||
.appLinks img {
|
||||
height: 36px
|
||||
}
|
||||
|
||||
a[data-role=button] {
|
||||
background-clip: padding-box;
|
||||
cursor: pointer !important;
|
||||
font-family: inherit !important;
|
||||
font-weight: 500 !important;
|
||||
margin: 0 .25em !important;
|
||||
display: inline-block;
|
||||
padding: .8em 1em;
|
||||
text-align: center;
|
||||
text-decoration: none !important;
|
||||
background: #292929 !important;
|
||||
}
|
||||
|
||||
.appLinks a + a {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
@-webkit-keyframes rotating {
|
||||
from {
|
||||
-webkit-transform: rotate(0);
|
||||
transform: rotate(0);
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotating {
|
||||
from {
|
||||
transform: rotate(0)
|
||||
-webkit-transform: rotate(0);
|
||||
transform: rotate(0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg)
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.rotatingCircle {
|
||||
animation: rotating 2s linear infinite
|
||||
-webkit-animation: rotating 2s linear infinite;
|
||||
animation: rotating 2s linear infinite;
|
||||
}
|
||||
|
||||
.pluginPreviewImg {
|
||||
box-shadow: 0 .0725em .29em 0 rgba(0, 0, 0, .37)
|
||||
-webkit-box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
|
||||
box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
|
||||
}
|
||||
|
||||
.ui-bar-a{
|
||||
.ui-bar-a {
|
||||
text-align: center;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.detailTableBodyCell,
|
||||
.detailTableHeaderCell {
|
||||
border-spacing: 0;
|
||||
padding: .4em
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
.detailTable {
|
||||
|
@ -9,11 +9,11 @@
|
|||
border-spacing: 0;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
margin: 0 auto
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.detailTableHeaderCell {
|
||||
font-weight: 700;
|
||||
text-align: left;
|
||||
vertical-align: top
|
||||
}
|
||||
vertical-align: top;
|
||||
}
|
||||
|
|
|
@ -44,4 +44,4 @@
|
|||
|
||||
.align-self-flex-end {
|
||||
align-self: flex-end;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,35 @@
|
|||
html {
|
||||
font-family: -apple-system, "Helvetica", system-ui, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", 'Open Sans', sans-serif;
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: "Noto Sans", sans-serif;
|
||||
font-size: 93%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
text-size-adjust: 100%;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
/* For better bolding, since Helvetica does not support 500 weight, and 600 is too thick */
|
||||
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", 'Open Sans', sans-serif;
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
font-family: "Noto Sans", sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 500;
|
||||
font-weight: 400;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 500;
|
||||
font-weight: 400;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 500;
|
||||
font-weight: 400;
|
||||
font-size: 1.17em;
|
||||
}
|
||||
|
||||
.layout-tv {
|
||||
font-size: 2.5vh;
|
||||
font-size: 130%;
|
||||
}
|
||||
|
||||
.layout-mobile {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
h1 {
|
||||
font-weight: 500;
|
||||
font-weight: 400;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
|
@ -8,12 +8,12 @@ h1 {
|
|||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 500;
|
||||
font-weight: 400;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 500;
|
||||
font-weight: 400;
|
||||
font-size: 1.17em;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
html {
|
||||
font-size: 82% !important
|
||||
font-size: 82% !important;
|
||||
}
|
||||
|
||||
.formDialogFooter {
|
||||
position: static !important;
|
||||
margin: 0 -1em !important
|
||||
}
|
||||
margin: 0 -1em !important;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
.guideVerticalScroller {
|
||||
padding-bottom: 15em
|
||||
padding-bottom: 15em;
|
||||
}
|
||||
|
||||
@media all and (min-width:62.5em) {
|
||||
@media all and (min-width: 62.5em) {
|
||||
#guideTab {
|
||||
padding-left: .5em
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
@font-face {
|
||||
font-family: 'Material Icons';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Material Icons'), local('MaterialIcons-Regular'), url(flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2) format('woff2'), url(flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff) format('woff');
|
||||
}
|
||||
|
||||
.md-icon {
|
||||
font-family: 'Material Icons';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-feature-settings: 'liga';
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: "liga" 1;
|
||||
line-height: 1;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
|
@ -1,53 +1,57 @@
|
|||
.editPageSidebar {
|
||||
display: block
|
||||
display: block;
|
||||
}
|
||||
|
||||
.editPageSidebar-withcontent {
|
||||
display: none
|
||||
display: none;
|
||||
}
|
||||
|
||||
.libraryTree {
|
||||
margin-left: .25em
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
|
||||
.offlineEditorNode {
|
||||
color: #c33
|
||||
color: #c33;
|
||||
}
|
||||
|
||||
.editorNode img {
|
||||
height: 18px;
|
||||
margin: 0 .35em;
|
||||
margin: 0 0.35em;
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
top: -2px
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.jstree-anchor {
|
||||
font-weight: 400 !important
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
.jstree-wholerow-hovered {
|
||||
background: #38c !important;
|
||||
-webkit-border-radius: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
box-shadow: none !important
|
||||
-webkit-box-shadow: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.jstree-default .jstree-hovered {
|
||||
background: 0 0 !important;
|
||||
-webkit-border-radius: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
-webkit-box-shadow: none !important;
|
||||
box-shadow: none !important;
|
||||
color: #fff !important
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.jstree-default .jstree-wholerow-clicked {
|
||||
background: #00a4dc !important
|
||||
background: #00a4dc !important;
|
||||
}
|
||||
|
||||
.metadataSidebarIcon {
|
||||
margin-right: .4em
|
||||
margin-right: 0.4em;
|
||||
}
|
||||
|
||||
@media all and (min-width:50em) {
|
||||
@media all and (min-width: 50em) {
|
||||
.editPageSidebar {
|
||||
position: fixed;
|
||||
top: 5.2em;
|
||||
|
@ -55,21 +59,21 @@
|
|||
left: 0;
|
||||
width: 30%;
|
||||
border-right: 1px solid #555;
|
||||
display: block
|
||||
display: block;
|
||||
}
|
||||
|
||||
.editPageInnerContent {
|
||||
float: right;
|
||||
width: 68.5%
|
||||
width: 68.5%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width:112.5em) {
|
||||
@media all and (min-width: 112.5em) {
|
||||
.editPageSidebar {
|
||||
width: 25%
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.editPageInnerContent {
|
||||
width: 73.5%
|
||||
width: 73.5%;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
.scrollX {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overflow-y: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -8,39 +9,50 @@
|
|||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
.hiddenScrollX, .layout-tv .scrollX {
|
||||
scrollbar-width: none;
|
||||
.hiddenScrollX,
|
||||
.layout-tv .scrollX {
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.hiddenScrollX-forced {
|
||||
scrollbar-width: none;
|
||||
overflow: -moz-scrollbars-none;
|
||||
}
|
||||
|
||||
.hiddenScrollX::-webkit-scrollbar, .layout-tv .scrollX::-webkit-scrollbar {
|
||||
.hiddenScrollX::-webkit-scrollbar,
|
||||
.layout-tv .scrollX::-webkit-scrollbar {
|
||||
height: 0 !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.scrollY {
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.smoothScrollY {
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overflow-x: hidden;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
.hiddenScrollY, .layout-tv .smoothScrollY {
|
||||
scrollbar-width: none;
|
||||
.hiddenScrollY,
|
||||
.layout-tv .smoothScrollY {
|
||||
-ms-overflow-style: none;
|
||||
|
||||
/* Can't do this because it not only hides the scrollbar, but also prevents scrolling */
|
||||
|
||||
/* overflow: -moz-scrollbars-none; */
|
||||
}
|
||||
|
||||
.hiddenScrollY-forced {
|
||||
scrollbar-width: none;
|
||||
overflow: -moz-scrollbars-none;
|
||||
}
|
||||
|
||||
.hiddenScrollY::-webkit-scrollbar, .layout-tv .smoothScrollY::-webkit-scrollbar, .layout-tv .scrollY::-webkit-scrollbar {
|
||||
.hiddenScrollY::-webkit-scrollbar,
|
||||
.layout-tv .smoothScrollY::-webkit-scrollbar,
|
||||
.layout-tv .scrollY::-webkit-scrollbar {
|
||||
width: 0 !important;
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,23 @@ body,
|
|||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.clipForScreenReader {
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
clip-path: inset(50%);
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
/* Fix font ligatures on older WebOS versions */
|
||||
-webkit-font-feature-settings: "liga";
|
||||
}
|
||||
|
||||
.backgroundContainer {
|
||||
|
@ -11,52 +27,58 @@ html {
|
|||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
contain: strict
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
html {
|
||||
line-height: 1.35
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.layout-mobile,
|
||||
.layout-tv {
|
||||
user-select: none
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
background-color: transparent !important;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.mainAnimatedPage {
|
||||
contain: style size !important
|
||||
contain: style size !important;
|
||||
}
|
||||
|
||||
.pageContainer {
|
||||
overflow-x: visible !important
|
||||
overflow-x: visible !important;
|
||||
}
|
||||
|
||||
.bodyWithPopupOpen {
|
||||
overflow-y: hidden !important
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
|
||||
div[data-role=page] {
|
||||
outline: 0
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.pageTitle {
|
||||
margin-top: 0;
|
||||
font-family: inherit
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.fieldDescription {
|
||||
padding-left: .15em;
|
||||
padding-left: 0.15em;
|
||||
font-weight: 400;
|
||||
white-space: normal !important
|
||||
white-space: normal !important;
|
||||
}
|
||||
|
||||
.fieldDescription+.fieldDescription {
|
||||
margin-top: .3em
|
||||
.fieldDescription + .fieldDescription {
|
||||
margin-top: 0.3em;
|
||||
}
|
||||
|
||||
.content-primary,
|
||||
|
@ -67,21 +89,34 @@ div[data-role=page] {
|
|||
padding-bottom: 5em !important;
|
||||
}
|
||||
|
||||
@media all and (min-width:50em) {
|
||||
@media all and (min-width: 50em) {
|
||||
.readOnlyContent,
|
||||
form {
|
||||
max-width: 54em
|
||||
max-width: 54em;
|
||||
}
|
||||
}
|
||||
|
||||
.headerHelpButton {
|
||||
margin-left: 1.25em !important;
|
||||
padding-bottom: .4em !important;
|
||||
padding-top: .4em !important
|
||||
padding-bottom: 0.4em !important;
|
||||
padding-top: 0.4em !important;
|
||||
}
|
||||
|
||||
.mediaInfoContent {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 85%
|
||||
width: 85%;
|
||||
}
|
||||
|
||||
.headroom {
|
||||
will-change: transform;
|
||||
transition: transform 200ms linear;
|
||||
}
|
||||
|
||||
.headroom--pinned {
|
||||
transform: translateY(0%);
|
||||
}
|
||||
|
||||
.headroom--unpinned {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
.chapterThumbTextContainer,
|
||||
.videoOsdBottom {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
.osdPoster img,
|
||||
|
@ -8,52 +11,59 @@
|
|||
.videoOsdBottom {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.osdHeader {
|
||||
transition: opacity .3s ease-out;
|
||||
-webkit-transition: opacity 0.3s ease-out;
|
||||
-o-transition: opacity 0.3s ease-out;
|
||||
transition: opacity 0.3s ease-out;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
background: rgba(0, 0, 0, 0.7) !important;
|
||||
-webkit-backdrop-filter: none !important;
|
||||
backdrop-filter: none !important;
|
||||
color: #eee !important;
|
||||
}
|
||||
|
||||
.osdHeader-hidden {
|
||||
opacity: 0
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.osdHeader .headerButton:not(.headerBackButton):not(.headerCastButton) {
|
||||
display: none
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chapterThumbContainer {
|
||||
-webkit-box-shadow: 0 0 1.9vh #000;
|
||||
box-shadow: 0 0 1.9vh #000;
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-flex-grow: 1;
|
||||
flex-grow: 1;
|
||||
position: relative
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.chapterThumb {
|
||||
background-position: center center;
|
||||
-webkit-background-size: contain;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
border: 0;
|
||||
height: 20vh;
|
||||
min-width: 20vh
|
||||
min-width: 20vh;
|
||||
}
|
||||
|
||||
@media all and (orientation:portrait) {
|
||||
@media all and (orientation: portrait) {
|
||||
.chapterThumb {
|
||||
height: 30vw;
|
||||
min-width: 30vw
|
||||
min-width: 30vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-height:50em) and (orientation:landscape) {
|
||||
@media all and (max-height: 50em) and (orientation: landscape) {
|
||||
.chapterThumb {
|
||||
height: 30vh;
|
||||
min-width: 30vh
|
||||
min-width: 30vh;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,161 +72,218 @@
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, .7);
|
||||
padding: .25em .5em;
|
||||
user-select: none
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
padding: 0.25em 0.5em;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.chapterThumbText {
|
||||
padding: .25em 0;
|
||||
padding: 0.25em 0;
|
||||
margin: 0;
|
||||
opacity: 1
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.chapterThumbText-dim {
|
||||
opacity: .6
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.videoOsdBottom {
|
||||
position: fixed;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
padding: 1%;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-flex-direction: row;
|
||||
flex-direction: row;
|
||||
will-change: opacity;
|
||||
-webkit-transition: opacity 0.3s ease-out;
|
||||
-o-transition: opacity 0.3s ease-out;
|
||||
transition: opacity 0.3s ease-out;
|
||||
color: #fff;
|
||||
user-select: none
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
}
|
||||
|
||||
.videoOsdBottom-hidden {
|
||||
opacity: 0
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.osdControls {
|
||||
flex-grow: 1
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-flex-grow: 1;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.videoOsdBottom .buttons {
|
||||
padding: .25em 0 0;
|
||||
padding: 0.25em 0 0;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
align-items: center
|
||||
-webkit-box-align: center;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.osdVolumeSliderContainer {
|
||||
width: 9em;
|
||||
flex-grow: 1
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-flex-grow: 1;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.osdMediaInfo,
|
||||
.volumeButtons {
|
||||
display: flex;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
align-items: center;
|
||||
-webkit-box-align: center;
|
||||
}
|
||||
|
||||
.volumeButtons {
|
||||
margin: 0 .5em 0 auto;
|
||||
margin: 0 0.5em 0 auto;
|
||||
display: flex;
|
||||
align-items: center
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.osdTimeText {
|
||||
margin-left: 1em;
|
||||
user-select: none
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.osdPoster {
|
||||
width: 10%;
|
||||
position: relative;
|
||||
margin-right: .5em
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.osdPoster img {
|
||||
position: absolute;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
-webkit-box-shadow: 0 0 1.9vh #000;
|
||||
box-shadow: 0 0 1.9vh #000;
|
||||
border: .08em solid #222;
|
||||
border: 0.08em solid #222;
|
||||
user-drag: none;
|
||||
user-select: none
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
.osdTitle,
|
||||
.osdTitleSmall {
|
||||
margin: 0 1em 0 0
|
||||
margin: 0 1em 0 0;
|
||||
}
|
||||
|
||||
.osdMediaInfo {
|
||||
display: flex;
|
||||
align-items: center
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.osdSecondaryMediaInfo {
|
||||
padding-left: .6em !important
|
||||
padding-left: 0.6em !important;
|
||||
}
|
||||
|
||||
.osdTextContainer {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
margin-bottom: .7em;
|
||||
padding-left: .5em
|
||||
margin-bottom: 0.7em;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.osdMainTextContainer {
|
||||
align-items: baseline
|
||||
-webkit-box-align: baseline;
|
||||
-webkit-align-items: baseline;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.osdMediaStatus {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
@-moz-keyframes spin {
|
||||
100% {
|
||||
-moz-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes spin {
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
100% {
|
||||
transform:rotate(360deg);
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.osdMediaStatus .animate {
|
||||
animation:spin 4s linear infinite;
|
||||
-webkit-animation: spin 4s linear infinite;
|
||||
-moz-animation: spin 4s linear infinite;
|
||||
animation: spin 4s linear infinite;
|
||||
}
|
||||
|
||||
.pageContainer {
|
||||
top: 0;
|
||||
position: fixed
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
@media all and (max-width:30em) {
|
||||
|
||||
@media all and (max-width: 30em) {
|
||||
.btnFastForward,
|
||||
.btnRewind,
|
||||
.osdMediaInfo,
|
||||
.osdPoster {
|
||||
display: none !important
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width:33.75em) {
|
||||
@media all and (max-width: 33.75em) {
|
||||
.videoOsdBottom .paper-icon-button-light {
|
||||
margin: 0
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width:43em) {
|
||||
@media all and (max-width: 43em) {
|
||||
.videoOsdBottom .volumeButtons,
|
||||
.osdMediaStatus span {
|
||||
display: none !important
|
||||
}
|
||||
}
|
||||
@media all and (max-width:50em) {
|
||||
.videoOsdBottom .btnFastForward, .videoOsdBottom .btnRewind {
|
||||
display: none !important
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width:75em) {
|
||||
.videoOsdBottom .endsAtText {
|
||||
display: none !important
|
||||
@media all and (max-width: 50em) {
|
||||
.videoOsdBottom .btnFastForward,
|
||||
.videoOsdBottom .btnRewind {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 75em) {
|
||||
.videoOsdBottom .endsAtText {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24 19H0a13.6 13.6 0 0 1 2.21-6.07A11.2 11.2 0 0 1 5.87 9.4l.41-.23-2.02-3.41a.51.51 0 0 1 .17-.7.5.5 0 0 1 .69.18l2.08 3.5a12.62 12.62 0 0 1 4.84-.9 12.2 12.2 0 0 1 4.75.9l2.07-3.5a.5.5 0 0 1 .7-.17.51.51 0 0 1 .16.7L17.7 9.19l.5.28a11.38 11.38 0 0 1 3.63 3.62A14.48 14.48 0 0 1 24 19zm-7.5-4.48a1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1 1 1 0 0 0-1 1zm-11 0a1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1 1 1 0 0 0-1 1z"/>
|
||||
<path d="M24 19H0a13.6 13.6 0 0 1 2.21-6.07A11.2 11.2 0 0 1 5.87 9.4l.41-.23-2.02-3.41a.51.51 0 0 1 .17-.7.5.5 0 0 1 .69.18l2.08 3.5a12.62 12.62 0 0 1 4.84-.9 12.2 12.2 0 0 1 4.75.9l2.07-3.5a.5.5 0 0 1 .7-.17.51.51 0 0 1 .16.7L17.7 9.19l.5.28a11.38 11.38 0 0 1 3.63 3.62A14.48 14.48 0 0 1 24 19zm-7.5-4.48a1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1 1 1 0 0 0-1 1zm-11 0a1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1 1 1 0 0 0-1 1z" fill="#fff"/>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 551 B After Width: | Height: | Size: 563 B |
20
src/assets/img/fresh.svg
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg id="svg3390" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="141.25" viewBox="0 0 138.75 141.25" width="138.75" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<metadata id="metadata3396">
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g id="layer1" fill="#f93208">
|
||||
<path id="path3412" d="m20.154 40.829c-28.149 27.622-13.657 61.011-5.734 71.931 35.254 41.954 92.792 25.339 111.89-5.9071 4.7608-8.2027 22.554-53.467-23.976-78.009z"/>
|
||||
<path id="path3471" d="m39.613 39.265 4.7778-8.8607 28.406-5.0384 11.119 9.2082z"/>
|
||||
</g>
|
||||
<g id="layer2">
|
||||
<path id="path3437" d="m39.436 8.5696 8.9682-5.2826 6.7569 15.479c3.7925-6.3226 13.79-16.316 24.939-4.6684-4.7281 1.2636-7.5161 3.8553-7.7397 8.4768 15.145-4.1697 31.343 3.2127 33.539 9.0911-10.951-4.314-27.695 10.377-41.771 2.334 0.009 15.045-12.617 16.636-19.902 17.076 2.077-4.996 5.591-9.994 1.474-14.987-7.618 8.171-13.874 10.668-33.17 4.668 4.876-1.679 14.843-11.39 24.448-11.425-6.775-2.467-12.29-2.087-17.814-1.475 2.917-3.961 12.149-15.197 28.625-8.476z" fill="#02902e"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
1
src/assets/img/rotten.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="145" height="140"><path fill="#0fc755" d="M47.4 35.342c-13.607-7.935-12.32-25.203 2.097-31.88 26.124-6.531 29.117 13.78 22.652 30.412-6.542 24.11 18.095 23.662 19.925 10.067 3.605-18.412 19.394-26.695 31.67-16.359 12.598 12.135 7.074 36.581-17.827 34.187-16.03-1.545-19.552 19.585.839 21.183 32.228 1.915 42.49 22.167 31.04 35.865-15.993 15.15-37.691-4.439-45.512-19.505-6.8-9.307-17.321.11-13.423 6.502 12.983 19.465 2.923 31.229-10.906 30.62-13.37-.85-20.96-9.06-13.214-29.15 3.897-12.481-8.595-15.386-16.57-5.45-11.707 19.61-28.865 13.68-33.976 4.19-3.243-7.621-2.921-25.846 24.119-23.696 16.688 4.137 11.776-12.561-.63-13.633-9.245-.443-30.501-7.304-22.86-24.54 7.34-11.056 24.958-11.768 33.348 6.293 3.037 4.232 8.361 11.042 18.037 5.033 3.51-5.197 1.21-13.9-8.809-20.135z"/></svg>
|
After Width: | Height: | Size: 833 B |
|
@ -5,4 +5,4 @@
|
|||
<div id="pluginTiles" style="text-align:left;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
168
src/bundle.js
|
@ -5,94 +5,174 @@
|
|||
var _define = window.define;
|
||||
|
||||
// document-register-element
|
||||
var docRegister = require("document-register-element");
|
||||
_define("document-register-element", function() {
|
||||
var docRegister = require('document-register-element');
|
||||
_define('document-register-element', function() {
|
||||
return docRegister;
|
||||
});
|
||||
|
||||
// fetch
|
||||
var fetch = require("whatwg-fetch");
|
||||
_define("fetch", function() {
|
||||
return fetch
|
||||
var fetch = require('whatwg-fetch');
|
||||
_define('fetch', function() {
|
||||
return fetch;
|
||||
});
|
||||
|
||||
// query-string
|
||||
var query = require('query-string');
|
||||
_define('queryString', function() {
|
||||
return query;
|
||||
});
|
||||
|
||||
// flvjs
|
||||
var flvjs = require("flv.js").default;
|
||||
_define("flvjs", function() {
|
||||
var flvjs = require('flv.js/dist/flv').default;
|
||||
_define('flvjs', function() {
|
||||
return flvjs;
|
||||
});
|
||||
|
||||
// jstree
|
||||
var jstree = require("jstree");
|
||||
require("jstree/dist/themes/default/style.css");
|
||||
_define("jstree", function() {
|
||||
var jstree = require('jstree');
|
||||
require('jstree/dist/themes/default/style.css');
|
||||
_define('jstree', function() {
|
||||
return jstree;
|
||||
});
|
||||
|
||||
// jquery
|
||||
var jquery = require("jquery");
|
||||
_define("jQuery", function() {
|
||||
var jquery = require('jquery');
|
||||
_define('jQuery', function() {
|
||||
return jquery;
|
||||
});
|
||||
|
||||
// hlsjs
|
||||
var hlsjs = require("hls.js");
|
||||
_define("hlsjs", function() {
|
||||
var hlsjs = require('hls.js');
|
||||
_define('hlsjs', function() {
|
||||
return hlsjs;
|
||||
});
|
||||
|
||||
// howler
|
||||
var howler = require("howler");
|
||||
_define("howler", function() {
|
||||
var howler = require('howler');
|
||||
_define('howler', function() {
|
||||
return howler;
|
||||
});
|
||||
|
||||
// native-promise-only
|
||||
var nativePromise = require("native-promise-only");
|
||||
_define("native-promise-only", function() {
|
||||
return nativePromise;
|
||||
});
|
||||
|
||||
// resize-observer-polyfill
|
||||
var resize = require("resize-observer-polyfill").default;
|
||||
_define("resize-observer-polyfill", function() {
|
||||
var resize = require('resize-observer-polyfill').default;
|
||||
_define('resize-observer-polyfill', function() {
|
||||
return resize;
|
||||
});
|
||||
|
||||
// shaka
|
||||
var shaka = require("shaka-player");
|
||||
_define("shaka", function() {
|
||||
var shaka = require('shaka-player');
|
||||
_define('shaka', function() {
|
||||
return shaka;
|
||||
});
|
||||
|
||||
// swiper
|
||||
var swiper = require("swiper");
|
||||
require("swiper/dist/css/swiper.min.css");
|
||||
_define("swiper", function() {
|
||||
var swiper = require('swiper/js/swiper');
|
||||
require('swiper/css/swiper.min.css');
|
||||
_define('swiper', function() {
|
||||
return swiper;
|
||||
});
|
||||
|
||||
// sortable
|
||||
var sortable = require("sortablejs").default;
|
||||
_define("sortable", function() {
|
||||
var sortable = require('sortablejs').default;
|
||||
_define('sortable', function() {
|
||||
return sortable;
|
||||
});
|
||||
|
||||
// webcomponents
|
||||
var webcomponents = require("webcomponents.js/webcomponents-lite");
|
||||
_define("webcomponents", function() {
|
||||
return webcomponents
|
||||
});
|
||||
|
||||
// libjass
|
||||
var libjass = require("libjass");
|
||||
require("libjass/libjass.css");
|
||||
_define("libjass", function() {
|
||||
return libjass;
|
||||
var webcomponents = require('webcomponents.js/webcomponents-lite');
|
||||
_define('webcomponents', function() {
|
||||
return webcomponents;
|
||||
});
|
||||
|
||||
// libass-wasm
|
||||
var libass_wasm = require("libass-wasm");
|
||||
_define("JavascriptSubtitlesOctopus", function() {
|
||||
return libass_wasm;
|
||||
var libassWasm = require('libass-wasm');
|
||||
_define('JavascriptSubtitlesOctopus', function() {
|
||||
return libassWasm;
|
||||
});
|
||||
|
||||
// material-icons
|
||||
var materialIcons = require('material-design-icons-iconfont/dist/material-design-icons.css');
|
||||
_define('material-icons', function() {
|
||||
return materialIcons;
|
||||
});
|
||||
|
||||
// noto font
|
||||
var noto = require('jellyfin-noto');
|
||||
_define('jellyfin-noto', function () {
|
||||
return noto;
|
||||
});
|
||||
|
||||
// page.js
|
||||
var page = require('page');
|
||||
_define('page', function() {
|
||||
return page;
|
||||
});
|
||||
|
||||
// core-js
|
||||
var polyfill = require('@babel/polyfill/dist/polyfill');
|
||||
_define('polyfill', function () {
|
||||
return polyfill;
|
||||
});
|
||||
|
||||
// domtokenlist-shim
|
||||
var classlist = require('classlist.js');
|
||||
_define('classlist-polyfill', function () {
|
||||
return classlist;
|
||||
});
|
||||
|
||||
// Date-FNS
|
||||
var dateFns = require('date-fns');
|
||||
_define('date-fns', function () {
|
||||
return dateFns;
|
||||
});
|
||||
|
||||
var dateFnsLocale = require('date-fns/locale');
|
||||
_define('date-fns/locale', function () {
|
||||
return dateFnsLocale;
|
||||
});
|
||||
|
||||
var fast_text_encoding = require('fast-text-encoding');
|
||||
_define('fast-text-encoding', function () {
|
||||
return fast_text_encoding;
|
||||
});
|
||||
|
||||
// intersection-observer
|
||||
var intersection_observer = require('intersection-observer');
|
||||
_define('intersection-observer', function () {
|
||||
return intersection_observer;
|
||||
});
|
||||
|
||||
// screenfull
|
||||
var screenfull = require('screenfull');
|
||||
_define('screenfull', function () {
|
||||
return screenfull;
|
||||
});
|
||||
|
||||
// headroom.js
|
||||
var headroom = require('headroom.js/dist/headroom');
|
||||
_define('headroom', function () {
|
||||
return headroom;
|
||||
});
|
||||
|
||||
// apiclient
|
||||
var apiclient = require('jellyfin-apiclient');
|
||||
|
||||
_define('apiclient', function () {
|
||||
return apiclient.ApiClient;
|
||||
});
|
||||
|
||||
_define('events', function () {
|
||||
return apiclient.Events;
|
||||
});
|
||||
|
||||
_define('credentialprovider', function () {
|
||||
return apiclient.Credentials;
|
||||
});
|
||||
|
||||
_define('connectionManagerFactory', function () {
|
||||
return apiclient.ConnectionManager;
|
||||
});
|
||||
|
||||
_define('appStorage', function () {
|
||||
return apiclient.AppStorage;
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "formDialogStyle"], function (dialogHelper, datetime) {
|
||||
"use strict";
|
||||
define(['dialogHelper', 'datetime', 'globalize', 'emby-select', 'paper-icon-button-light', 'formDialogStyle'], function (dialogHelper, datetime, globalize) {
|
||||
'use strict';
|
||||
|
||||
function getDisplayTime(hours) {
|
||||
var minutes = 0;
|
||||
|
@ -13,32 +13,32 @@ define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "f
|
|||
}
|
||||
|
||||
function populateHours(context) {
|
||||
var html = "";
|
||||
var html = '';
|
||||
|
||||
for (var i = 0; i < 24; i++) {
|
||||
html += '<option value="' + i + '">' + getDisplayTime(i) + "</option>";
|
||||
html += '<option value="' + i + '">' + getDisplayTime(i) + '</option>';
|
||||
}
|
||||
|
||||
html += '<option value="24">' + getDisplayTime(0) + "</option>";
|
||||
context.querySelector("#selectStart").innerHTML = html;
|
||||
context.querySelector("#selectEnd").innerHTML = html;
|
||||
html += '<option value="24">' + getDisplayTime(0) + '</option>';
|
||||
context.querySelector('#selectStart').innerHTML = html;
|
||||
context.querySelector('#selectEnd').innerHTML = html;
|
||||
}
|
||||
|
||||
function loadSchedule(context, schedule) {
|
||||
context.querySelector("#selectDay").value = schedule.DayOfWeek || "Sunday";
|
||||
context.querySelector("#selectStart").value = schedule.StartHour || 0;
|
||||
context.querySelector("#selectEnd").value = schedule.EndHour || 0;
|
||||
context.querySelector('#selectDay').value = schedule.DayOfWeek || 'Sunday';
|
||||
context.querySelector('#selectStart').value = schedule.StartHour || 0;
|
||||
context.querySelector('#selectEnd').value = schedule.EndHour || 0;
|
||||
}
|
||||
|
||||
function submitSchedule(context, options) {
|
||||
var updatedSchedule = {
|
||||
DayOfWeek: context.querySelector("#selectDay").value,
|
||||
StartHour: context.querySelector("#selectStart").value,
|
||||
EndHour: context.querySelector("#selectEnd").value
|
||||
DayOfWeek: context.querySelector('#selectDay').value,
|
||||
StartHour: context.querySelector('#selectStart').value,
|
||||
EndHour: context.querySelector('#selectEnd').value
|
||||
};
|
||||
|
||||
if (parseFloat(updatedSchedule.StartHour) >= parseFloat(updatedSchedule.EndHour)) {
|
||||
return void alert(Globalize.translate("ErrorMessageStartHourGreaterThanEnd"));
|
||||
return void alert(globalize.translate('ErrorMessageStartHourGreaterThanEnd'));
|
||||
}
|
||||
|
||||
context.submitted = true;
|
||||
|
@ -50,32 +50,32 @@ define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "f
|
|||
show: function (options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "components/accessschedule/accessschedule.template.html", true);
|
||||
xhr.open('GET', 'components/accessschedule/accessschedule.template.html', true);
|
||||
|
||||
xhr.onload = function (e) {
|
||||
var template = this.response;
|
||||
var dlg = dialogHelper.createDialog({
|
||||
removeOnClose: true,
|
||||
size: "small"
|
||||
size: 'small'
|
||||
});
|
||||
dlg.classList.add("formDialog");
|
||||
var html = "";
|
||||
html += Globalize.translateDocument(template);
|
||||
dlg.classList.add('formDialog');
|
||||
var html = '';
|
||||
html += globalize.translateDocument(template);
|
||||
dlg.innerHTML = html;
|
||||
populateHours(dlg);
|
||||
loadSchedule(dlg, options.schedule);
|
||||
dialogHelper.open(dlg);
|
||||
dlg.addEventListener("close", function () {
|
||||
dlg.addEventListener('close', function () {
|
||||
if (dlg.submitted) {
|
||||
resolve(options.schedule);
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
dlg.querySelector(".btnCancel").addEventListener("click", function (e) {
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
dlg.querySelector("form").addEventListener("submit", function (e) {
|
||||
dlg.querySelector('form').addEventListener('submit', function (e) {
|
||||
submitSchedule(dlg, options);
|
||||
e.preventDefault();
|
||||
return false;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="formDialogHeader">
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1">
|
||||
<i class="md-icon">arrow_back</i>
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" title="${LabelPrevious}" tabindex="-1">
|
||||
<span class="material-icons arrow_back" aria-hidden="true"></span>
|
||||
</button>
|
||||
<h3 class="formDialogHeaderTitle">
|
||||
${HeaderAccessSchedule}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
padding: 0;
|
||||
border: none;
|
||||
max-height: 84%;
|
||||
border-radius: .1em !important;
|
||||
border-radius: 0.1em !important;
|
||||
}
|
||||
|
||||
.actionsheet-not-fullscreen {
|
||||
|
@ -24,7 +24,7 @@
|
|||
|
||||
.actionSheetContent {
|
||||
margin: 0 !important;
|
||||
padding: .4em 0 !important;
|
||||
padding: 0.4em 0 !important;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -45,7 +45,7 @@
|
|||
}
|
||||
|
||||
.actionsheetListItemBody {
|
||||
padding: .4em 1em .4em .6em !important;
|
||||
padding: 0.4em 1em 0.4em 0.6em !important;
|
||||
}
|
||||
|
||||
.actionSheetItemText {
|
||||
|
@ -59,13 +59,13 @@
|
|||
}
|
||||
|
||||
.actionSheetItemAsideText {
|
||||
opacity: .7;
|
||||
opacity: 0.7;
|
||||
font-size: 90%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-shrink: 0;
|
||||
margin-left: 5em;
|
||||
margin-right: .5em;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.actionSheetScroller {
|
||||
|
@ -83,14 +83,14 @@
|
|||
}
|
||||
|
||||
.actionsheetDivider {
|
||||
height: .07em;
|
||||
margin: .25em 0;
|
||||
height: 0.07em;
|
||||
margin: 0.25em 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.actionSheetTitle {
|
||||
margin: .6em 0 .7em !important;
|
||||
padding: 0 .9em;
|
||||
margin: 0.6em 0 0.7em !important;
|
||||
padding: 0 0.9em;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@
|
|||
}
|
||||
|
||||
.actionsheetMenuItemIcon {
|
||||
margin: 0 .85em 0 .45em !important;
|
||||
margin: 0 0.85em 0 0.45em !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,6 @@
|
|||
|
||||
.btnCloseActionSheet {
|
||||
position: fixed;
|
||||
top: .75em;
|
||||
left: .5em;
|
||||
top: 0.75em;
|
||||
left: 0.5em;
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-bu
|
|||
// Admittedly a hack but right now the scrollbar is being factored into the width which is causing truncation
|
||||
if (options.items.length > 20) {
|
||||
var minWidth = dom.getWindowSize().innerWidth >= 300 ? 240 : 200;
|
||||
style += "min-width:" + minWidth + "px;";
|
||||
style += 'min-width:' + minWidth + 'px;';
|
||||
}
|
||||
|
||||
var i;
|
||||
|
@ -158,7 +158,7 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-bu
|
|||
}
|
||||
|
||||
if (layoutManager.tv) {
|
||||
html += '<button is="paper-icon-button-light" class="btnCloseActionSheet hide-mouse-idle-tv" tabindex="-1"><i class="md-icon">arrow_back</i></button>';
|
||||
html += '<button is="paper-icon-button-light" class="btnCloseActionSheet hide-mouse-idle-tv" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
}
|
||||
|
||||
// If any items have an icon, give them all an icon just to make sure they're all lined up evenly
|
||||
|
@ -226,9 +226,9 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-bu
|
|||
|
||||
if (itemIcon) {
|
||||
|
||||
html += '<i class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent md-icon">' + itemIcon + '</i>';
|
||||
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons ' + itemIcon + '"></span>';
|
||||
} else if (renderIcon && !center) {
|
||||
html += '<i class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent md-icon" style="visibility:hidden;">check</i>';
|
||||
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons check" style="visibility:hidden;"></span>';
|
||||
}
|
||||
|
||||
html += '<div class="listItemBody actionsheetListItemBody">';
|
||||
|
|
|
@ -1,60 +1,59 @@
|
|||
define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotifications", "connectionManager", "emby-button", "listViewStyle"], function (events, globalize, dom, datetime, userSettings, serverNotifications, connectionManager) {
|
||||
"use strict";
|
||||
define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', 'serverNotifications', 'connectionManager', 'emby-button', 'listViewStyle'], function (events, globalize, dom, datefns, dfnshelper, userSettings, serverNotifications, connectionManager) {
|
||||
'use strict';
|
||||
|
||||
function getEntryHtml(entry, apiClient) {
|
||||
var html = "";
|
||||
var html = '';
|
||||
html += '<div class="listItem listItem-border">';
|
||||
var color = "#00a4dc";
|
||||
var icon = "notifications";
|
||||
var color = '#00a4dc';
|
||||
var icon = 'notifications';
|
||||
|
||||
if ("Error" == entry.Severity || "Fatal" == entry.Severity || "Warn" == entry.Severity) {
|
||||
color = "#cc0000";
|
||||
icon = "notification_important";
|
||||
if ('Error' == entry.Severity || 'Fatal' == entry.Severity || 'Warn' == entry.Severity) {
|
||||
color = '#cc0000';
|
||||
icon = 'notification_important';
|
||||
}
|
||||
|
||||
if (entry.UserId && entry.UserPrimaryImageTag) {
|
||||
html += '<i class="listItemIcon md-icon" style="width:2em!important;height:2em!important;padding:0;color:transparent;background-color:' + color + ";background-image:url('" + apiClient.getUserImageUrl(entry.UserId, {
|
||||
type: "Primary",
|
||||
html += '<span class="listItemIcon material-icons dvr" style="width:2em!important;height:2em!important;padding:0;color:transparent;background-color:' + color + ";background-image:url('" + apiClient.getUserImageUrl(entry.UserId, {
|
||||
type: 'Primary',
|
||||
tag: entry.UserPrimaryImageTag
|
||||
}) + "');background-repeat:no-repeat;background-position:center center;background-size: cover;\">dvr</i>"
|
||||
}) + "');background-repeat:no-repeat;background-position:center center;background-size: cover;\"></span>";
|
||||
} else {
|
||||
html += '<i class="listItemIcon md-icon" style="background-color:' + color + '">' + icon + '</i>';
|
||||
html += '<span class="listItemIcon material-icons ' + icon + '" style="background-color:' + color + '"></span>';
|
||||
}
|
||||
|
||||
html += '<div class="listItemBody three-line">';
|
||||
html += '<div class="listItemBodyText">';
|
||||
html += entry.Name;
|
||||
html += "</div>";
|
||||
html += '</div>';
|
||||
html += '<div class="listItemBodyText secondary">';
|
||||
var date = datetime.parseISO8601Date(entry.Date, true);
|
||||
html += datetime.toLocaleString(date).toLowerCase();
|
||||
html += "</div>";
|
||||
html += datefns.formatRelative(Date.parse(entry.Date), Date.parse(new Date()), { locale: dfnshelper.getLocale() });
|
||||
html += '</div>';
|
||||
html += '<div class="listItemBodyText secondary listItemBodyText-nowrap">';
|
||||
html += entry.ShortOverview || "";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += entry.ShortOverview || '';
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
|
||||
if (entry.Overview) {
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnEntryInfo" data-id="' + entry.Id + '" title="' + globalize.translate("Info") + '"><i class="md-icon">info</i></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnEntryInfo" data-id="' + entry.Id + '" title="' + globalize.translate('Info') + '"><span class="material-icons info"></span></button>';
|
||||
}
|
||||
|
||||
return html += "</div>";
|
||||
return html += '</div>';
|
||||
}
|
||||
|
||||
function renderList(elem, apiClient, result, startIndex, limit) {
|
||||
elem.innerHTML = result.Items.map(function (i) {
|
||||
return getEntryHtml(i, apiClient);
|
||||
}).join("");
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function reloadData(instance, elem, apiClient, startIndex, limit) {
|
||||
if (null == startIndex) {
|
||||
startIndex = parseInt(elem.getAttribute("data-activitystartindex") || "0");
|
||||
startIndex = parseInt(elem.getAttribute('data-activitystartindex') || '0');
|
||||
}
|
||||
|
||||
limit = limit || parseInt(elem.getAttribute("data-activitylimit") || "7");
|
||||
limit = limit || parseInt(elem.getAttribute('data-activitylimit') || '7');
|
||||
var minDate = new Date();
|
||||
var hasUserId = "false" !== elem.getAttribute("data-useractivity");
|
||||
var hasUserId = 'false' !== elem.getAttribute('data-useractivity');
|
||||
|
||||
if (hasUserId) {
|
||||
minDate.setTime(minDate.getTime() - 24 * 60 * 60 * 1000); // one day back
|
||||
|
@ -62,22 +61,22 @@ define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotific
|
|||
minDate.setTime(minDate.getTime() - 7 * 24 * 60 * 60 * 1000); // one week back
|
||||
}
|
||||
|
||||
ApiClient.getJSON(ApiClient.getUrl("System/ActivityLog/Entries", {
|
||||
ApiClient.getJSON(ApiClient.getUrl('System/ActivityLog/Entries', {
|
||||
startIndex: startIndex,
|
||||
limit: limit,
|
||||
minDate: minDate.toISOString(),
|
||||
hasUserId: hasUserId
|
||||
})).then(function (result) {
|
||||
elem.setAttribute("data-activitystartindex", startIndex);
|
||||
elem.setAttribute("data-activitylimit", limit);
|
||||
elem.setAttribute('data-activitystartindex', startIndex);
|
||||
elem.setAttribute('data-activitylimit', limit);
|
||||
if (!startIndex) {
|
||||
var activityContainer = dom.parentWithClass(elem, "activityContainer");
|
||||
var activityContainer = dom.parentWithClass(elem, 'activityContainer');
|
||||
|
||||
if (activityContainer) {
|
||||
if (result.Items.length) {
|
||||
activityContainer.classList.remove("hide");
|
||||
activityContainer.classList.remove('hide');
|
||||
} else {
|
||||
activityContainer.classList.add("hide");
|
||||
activityContainer.classList.add('hide');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,10 +95,10 @@ define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotific
|
|||
}
|
||||
|
||||
function onListClick(e) {
|
||||
var btnEntryInfo = dom.parentWithClass(e.target, "btnEntryInfo");
|
||||
var btnEntryInfo = dom.parentWithClass(e.target, 'btnEntryInfo');
|
||||
|
||||
if (btnEntryInfo) {
|
||||
var id = btnEntryInfo.getAttribute("data-id");
|
||||
var id = btnEntryInfo.getAttribute('data-id');
|
||||
var items = this.items;
|
||||
|
||||
if (items) {
|
||||
|
@ -115,7 +114,7 @@ define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotific
|
|||
}
|
||||
|
||||
function showItemOverview(item) {
|
||||
require(["alert"], function (alert) {
|
||||
require(['alert'], function (alert) {
|
||||
alert({
|
||||
text: item.Overview
|
||||
});
|
||||
|
@ -125,28 +124,28 @@ define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotific
|
|||
function ActivityLog(options) {
|
||||
this.options = options;
|
||||
var element = options.element;
|
||||
element.classList.add("activityLogListWidget");
|
||||
element.addEventListener("click", onListClick.bind(this));
|
||||
element.classList.add('activityLogListWidget');
|
||||
element.addEventListener('click', onListClick.bind(this));
|
||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
||||
reloadData(this, element, apiClient);
|
||||
var onUpdate = onActivityLogUpdate.bind(this);
|
||||
this.updateFn = onUpdate;
|
||||
events.on(serverNotifications, "ActivityLogEntry", onUpdate);
|
||||
apiClient.sendMessage("ActivityLogEntryStart", "0,1500");
|
||||
events.on(serverNotifications, 'ActivityLogEntry', onUpdate);
|
||||
apiClient.sendMessage('ActivityLogEntryStart', '0,1500');
|
||||
}
|
||||
|
||||
ActivityLog.prototype.destroy = function () {
|
||||
var options = this.options;
|
||||
|
||||
if (options) {
|
||||
options.element.classList.remove("activityLogListWidget");
|
||||
connectionManager.getApiClient(options.serverId).sendMessage("ActivityLogEntryStop", "0,1500");
|
||||
options.element.classList.remove('activityLogListWidget');
|
||||
connectionManager.getApiClient(options.serverId).sendMessage('ActivityLogEntryStop', '0,1500');
|
||||
}
|
||||
|
||||
var onUpdate = this.updateFn;
|
||||
|
||||
if (onUpdate) {
|
||||
events.off(serverNotifications, "ActivityLogEntry", onUpdate);
|
||||
events.off(serverNotifications, 'ActivityLogEntry', onUpdate);
|
||||
}
|
||||
|
||||
this.items = null;
|
||||
|
|
|
@ -42,4 +42,4 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize)
|
|||
|
||||
return Promise.resolve();
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -67,7 +67,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
|||
|
||||
html += '<div class="' + rowClassName + '">';
|
||||
if (options.mode === 'keyboard') {
|
||||
html += '<button data-value=" " is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><i class="md-icon alphaPickerButtonIcon">space_bar</i></button>';
|
||||
html += '<button data-value=" " is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><span class="material-icons alphaPickerButtonIcon space_bar"></span></button>';
|
||||
} else {
|
||||
letters = ['#'];
|
||||
html += mapLetters(letters, vertical).join('');
|
||||
|
@ -77,7 +77,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
|||
html += mapLetters(letters, vertical).join('');
|
||||
|
||||
if (options.mode === 'keyboard') {
|
||||
html += '<button data-value="backspace" is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><i class="md-icon alphaPickerButtonIcon">backspace</i></button>';
|
||||
html += '<button data-value="backspace" is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><span class="material-icons alphaPickerButtonIcon backspace"></span></button>';
|
||||
html += '</div>';
|
||||
|
||||
letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
||||
|
@ -132,7 +132,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
|||
if (alphaPickerButton) {
|
||||
var value = alphaPickerButton.getAttribute('data-value');
|
||||
|
||||
element.dispatchEvent(new CustomEvent("alphavalueclicked", {
|
||||
element.dispatchEvent(new CustomEvent('alphavalueclicked', {
|
||||
cancelable: false,
|
||||
detail: {
|
||||
value: value
|
||||
|
@ -241,7 +241,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
|||
try {
|
||||
btn = element.querySelector('.alphaPickerButton[data-value=\'' + value + '\']');
|
||||
} catch (err) {
|
||||
console.log('Error in querySelector: ' + err);
|
||||
console.error('error in querySelector: ' + err);
|
||||
}
|
||||
|
||||
if (btn && btn !== selected) {
|
||||
|
@ -262,7 +262,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
|||
}
|
||||
|
||||
if (applyValue) {
|
||||
element.dispatchEvent(new CustomEvent("alphavaluechanged", {
|
||||
element.dispatchEvent(new CustomEvent('alphavaluechanged', {
|
||||
cancelable: false,
|
||||
detail: {
|
||||
value: value
|
||||
|
|
|
@ -35,16 +35,15 @@
|
|||
font-size: inherit;
|
||||
min-width: initial;
|
||||
margin: 0;
|
||||
padding: .1em .4em;
|
||||
padding: 0.1em 0.4em;
|
||||
width: auto;
|
||||
border-radius: .1em;
|
||||
border-radius: 0.1em;
|
||||
font-weight: normal;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
@media all and (max-height: 50em) {
|
||||
|
||||
.alphaPicker-fixed {
|
||||
bottom: 5em;
|
||||
}
|
||||
|
@ -56,14 +55,12 @@
|
|||
}
|
||||
|
||||
@media all and (max-height: 49em) {
|
||||
|
||||
.alphaPicker-vertical {
|
||||
font-size: 94%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-height: 44em) {
|
||||
|
||||
.alphaPicker-vertical {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
@ -75,14 +72,12 @@
|
|||
}
|
||||
|
||||
@media all and (max-height: 37em) {
|
||||
|
||||
.alphaPicker-vertical {
|
||||
font-size: 82%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-height: 32em) {
|
||||
|
||||
.alphaPicker-vertical {
|
||||
font-size: 74%;
|
||||
}
|
||||
|
@ -112,27 +107,17 @@
|
|||
bottom: 1%;
|
||||
}
|
||||
|
||||
.alphaPicker-fixed-left {
|
||||
left: .4em;
|
||||
}
|
||||
|
||||
.alphaPicker-fixed-right {
|
||||
right: .4em;
|
||||
right: 0.4em;
|
||||
}
|
||||
|
||||
@media all and (min-width: 62.5em) {
|
||||
|
||||
.alphaPicker-fixed-left {
|
||||
left: 1em;
|
||||
}
|
||||
|
||||
.alphaPicker-fixed-right {
|
||||
right: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-height: 31.25em) {
|
||||
|
||||
.alphaPicker-fixed {
|
||||
display: none !important;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
},
|
||||
showSettings: function () {
|
||||
show('/settings/settings.html');
|
||||
},
|
||||
showNowPlaying: function () {
|
||||
show('/nowplaying.html');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -197,8 +200,8 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
|
||||
var apiClient = this;
|
||||
|
||||
if (data.status === 401) {
|
||||
if (data.errorCode === "ParentalControl") {
|
||||
if (data.status === 403) {
|
||||
if (data.errorCode === 'ParentalControl') {
|
||||
|
||||
var isCurrentAllowed = currentRouteInfo ? (currentRouteInfo.route.anonymous || currentRouteInfo.route.startup) : true;
|
||||
|
||||
|
@ -265,6 +268,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
}
|
||||
|
||||
function getMaxBandwidth() {
|
||||
/* eslint-disable compat/compat */
|
||||
if (navigator.connection) {
|
||||
var max = navigator.connection.downlinkMax;
|
||||
if (max && max > 0 && max < Number.POSITIVE_INFINITY) {
|
||||
|
@ -276,6 +280,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
return max;
|
||||
}
|
||||
}
|
||||
/* eslint-enable compat/compat */
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -367,7 +372,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
}
|
||||
|
||||
function enableNativeHistory() {
|
||||
return page.enableNativeHistory();
|
||||
return false;
|
||||
}
|
||||
|
||||
function authenticate(ctx, route, callback) {
|
||||
|
@ -387,13 +392,13 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
var apiClient = connectionManager.currentApiClient();
|
||||
var pathname = ctx.pathname.toLowerCase();
|
||||
|
||||
console.log('appRouter - processing path request ' + pathname);
|
||||
console.debug('appRouter - processing path request ' + pathname);
|
||||
|
||||
var isCurrentRouteStartup = currentRouteInfo ? currentRouteInfo.route.startup : true;
|
||||
var shouldExitApp = ctx.isBack && route.isDefaultRoute && isCurrentRouteStartup;
|
||||
|
||||
if (!shouldExitApp && (!apiClient || !apiClient.isLoggedIn()) && !route.anonymous) {
|
||||
console.log('appRouter - route does not allow anonymous access, redirecting to login');
|
||||
console.debug('appRouter - route does not allow anonymous access, redirecting to login');
|
||||
beginConnectionWizard();
|
||||
return;
|
||||
}
|
||||
|
@ -408,10 +413,10 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
|
||||
if (apiClient && apiClient.isLoggedIn()) {
|
||||
|
||||
console.log('appRouter - user is authenticated');
|
||||
console.debug('appRouter - user is authenticated');
|
||||
|
||||
if (route.isDefaultRoute) {
|
||||
console.log('appRouter - loading skin home page');
|
||||
console.debug('appRouter - loading skin home page');
|
||||
loadUserSkinWithOptions(ctx);
|
||||
return;
|
||||
} else if (route.roles) {
|
||||
|
@ -425,7 +430,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
}
|
||||
}
|
||||
|
||||
console.log('appRouter - proceeding to ' + pathname);
|
||||
console.debug('appRouter - proceeding to ' + pathname);
|
||||
callback();
|
||||
}
|
||||
|
||||
|
@ -508,9 +513,16 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
return baseRoute;
|
||||
}
|
||||
|
||||
var popstateOccurred = false;
|
||||
window.addEventListener('popstate', function () {
|
||||
popstateOccurred = true;
|
||||
});
|
||||
|
||||
function getHandler(route) {
|
||||
return function (ctx, next) {
|
||||
ctx.isBack = popstateOccurred;
|
||||
handleRoute(ctx, next, route);
|
||||
popstateOccurred = false;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -529,15 +541,15 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
}
|
||||
|
||||
function param(name, url) {
|
||||
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
|
||||
var regexS = "[\\?&]" + name + "=([^&#]*)";
|
||||
var regex = new RegExp(regexS, "i");
|
||||
name = name.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]');
|
||||
var regexS = '[\\?&]' + name + '=([^&#]*)';
|
||||
var regex = new RegExp(regexS, 'i');
|
||||
|
||||
var results = regex.exec(url || getWindowLocationSearch());
|
||||
if (results == null) {
|
||||
return "";
|
||||
return '';
|
||||
} else {
|
||||
return decodeURIComponent(results[1].replace(/\+/g, " "));
|
||||
return decodeURIComponent(results[1].replace(/\+/g, ' '));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,22 +557,31 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
page.back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pages of "no return" (when "Go back" should behave differently, probably quitting the application).
|
||||
*/
|
||||
var startPages = ['home', 'login', 'selectserver'];
|
||||
|
||||
function canGoBack() {
|
||||
var curr = current();
|
||||
if (!curr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (curr.type === 'home') {
|
||||
if (!document.querySelector('.dialogContainer') && startPages.indexOf(curr.type) !== -1) {
|
||||
return false;
|
||||
}
|
||||
return page.canGoBack();
|
||||
if (enableHistory()) {
|
||||
return history.length > 1;
|
||||
}
|
||||
return (page.len || 0) > 0;
|
||||
}
|
||||
|
||||
function showDirect(path) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
resolveOnNextShow = resolve, page.show(baseUrl()+path)
|
||||
})
|
||||
resolveOnNextShow = resolve;
|
||||
page.show(baseUrl() + path);
|
||||
});
|
||||
}
|
||||
|
||||
function show(path, options) {
|
||||
|
@ -658,7 +679,8 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
|
||||
function pushState(state, title, url) {
|
||||
state.navigate = false;
|
||||
page.pushState(state, title, url);
|
||||
history.pushState(state, title, url);
|
||||
|
||||
}
|
||||
|
||||
function setBaseRoute() {
|
||||
|
@ -667,7 +689,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
baseRoute = baseRoute.substring(0, baseRoute.length - 1);
|
||||
}
|
||||
|
||||
console.log('Setting page base to ' + baseRoute);
|
||||
console.debug('setting page base to ' + baseRoute);
|
||||
page.base(baseRoute);
|
||||
}
|
||||
|
||||
|
@ -708,7 +730,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
|||
appRouter.getRoutes = getRoutes;
|
||||
appRouter.pushState = pushState;
|
||||
appRouter.enableNativeHistory = enableNativeHistory;
|
||||
appRouter.handleAnchorClick = page.handleAnchorClick;
|
||||
appRouter.handleAnchorClick = page.clickHandler;
|
||||
appRouter.TransparencyLevel = {
|
||||
None: 0,
|
||||
Backdrop: 1,
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
z-index: 10;
|
||||
bottom: 0;
|
||||
transition: transform 180ms linear;
|
||||
contain: layout style;
|
||||
}
|
||||
|
||||
.appfooter.headroom--unpinned {
|
||||
transform: translateY(100%)!important;
|
||||
}
|
||||
.appfooter.headroom--unpinned {
|
||||
transform: translateY(100%) !important;
|
||||
}
|
||||
|
|
|
@ -2,24 +2,18 @@ define(['browser', 'css!./appfooter'], function (browser) {
|
|||
'use strict';
|
||||
|
||||
function render(options) {
|
||||
|
||||
var elem = document.createElement('div');
|
||||
|
||||
elem.classList.add('appfooter');
|
||||
|
||||
elem.classList.add('appfooter-blurred');
|
||||
|
||||
document.body.appendChild(elem);
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
function appFooter(options) {
|
||||
|
||||
var self = this;
|
||||
|
||||
self.element = render(options);
|
||||
|
||||
self.add = function (elem) {
|
||||
self.element.appendChild(elem);
|
||||
};
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSettings, browser, events, htmlMediaHelper) {
|
||||
"use strict";
|
||||
define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'globalize'], function (appSettings, browser, events, htmlMediaHelper, webSettings, globalize) {
|
||||
'use strict';
|
||||
|
||||
function getBaseProfileOptions(item) {
|
||||
var disableHlsVideoAudioCodecs = [];
|
||||
|
||||
if (item && htmlMediaHelper.enableHlsJsPlayer(item.RunTimeTicks, item.MediaType)) {
|
||||
if (browser.edge || browser.msie) {
|
||||
disableHlsVideoAudioCodecs.push("mp3");
|
||||
disableHlsVideoAudioCodecs.push('mp3');
|
||||
}
|
||||
|
||||
disableHlsVideoAudioCodecs.push("ac3");
|
||||
disableHlsVideoAudioCodecs.push("eac3");
|
||||
disableHlsVideoAudioCodecs.push("opus");
|
||||
disableHlsVideoAudioCodecs.push('ac3');
|
||||
disableHlsVideoAudioCodecs.push('eac3');
|
||||
disableHlsVideoAudioCodecs.push('opus');
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -22,7 +22,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
|
||||
function getDeviceProfileForWindowsUwp(item) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
require(["browserdeviceprofile", "environments/windows-uwp/mediacaps"], function (profileBuilder, uwpMediaCaps) {
|
||||
require(['browserdeviceprofile', 'environments/windows-uwp/mediacaps'], function (profileBuilder, uwpMediaCaps) {
|
||||
var profileOptions = getBaseProfileOptions(item);
|
||||
profileOptions.supportsDts = uwpMediaCaps.supportsDTS();
|
||||
profileOptions.supportsTrueHd = uwpMediaCaps.supportsDolby();
|
||||
|
@ -40,26 +40,15 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
}
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
require(["browserdeviceprofile"], function (profileBuilder) {
|
||||
require(['browserdeviceprofile'], function (profileBuilder) {
|
||||
var profile;
|
||||
|
||||
if (window.NativeShell) {
|
||||
profile = window.NativeShell.AppHost.getDeviceProfile(profileBuilder);
|
||||
} else {
|
||||
profile = profileBuilder(getBaseProfileOptions(item));
|
||||
|
||||
if (item && !options.isRetry && "allcomplexformats" !== appSettings.get("subtitleburnin")) {
|
||||
if (!browser.orsay && !browser.tizen) {
|
||||
profile.SubtitleProfiles.push({
|
||||
Format: "ass",
|
||||
Method: "External"
|
||||
});
|
||||
profile.SubtitleProfiles.push({
|
||||
Format: "ssa",
|
||||
Method: "External"
|
||||
});
|
||||
}
|
||||
}
|
||||
var builderOpts = getBaseProfileOptions(item);
|
||||
builderOpts.enableSsaRender = (item && !options.isRetry && 'allcomplexformats' !== appSettings.get('subtitleburnin'));
|
||||
profile = profileBuilder(builderOpts);
|
||||
}
|
||||
|
||||
resolve(profile);
|
||||
|
@ -68,12 +57,12 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
}
|
||||
|
||||
function escapeRegExp(str) {
|
||||
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
|
||||
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1');
|
||||
}
|
||||
|
||||
function replaceAll(originalString, strReplace, strWith) {
|
||||
var strReplace2 = escapeRegExp(strReplace);
|
||||
var reg = new RegExp(strReplace2, "ig");
|
||||
var reg = new RegExp(strReplace2, 'ig');
|
||||
return originalString.replace(reg, strWith);
|
||||
}
|
||||
|
||||
|
@ -81,7 +70,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
var keys = [];
|
||||
|
||||
if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), self.btoa) {
|
||||
var result = replaceAll(btoa(keys.join("|")), "=", "1");
|
||||
var result = replaceAll(btoa(keys.join('|')), '=', '1');
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
|
@ -89,7 +78,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
}
|
||||
|
||||
function getDeviceId() {
|
||||
var key = "_deviceId2";
|
||||
var key = '_deviceId2';
|
||||
var deviceId = appSettings.get(key);
|
||||
|
||||
if (deviceId) {
|
||||
|
@ -104,16 +93,16 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
|
||||
function getDeviceName() {
|
||||
var deviceName;
|
||||
deviceName = browser.tizen ? "Samsung Smart TV" : browser.web0s ? "LG Smart TV" : browser.operaTv ? "Opera TV" : browser.xboxOne ? "Xbox One" : browser.ps4 ? "Sony PS4" : browser.chrome ? "Chrome" : browser.edge ? "Edge" : browser.firefox ? "Firefox" : browser.msie ? "Internet Explorer" : browser.opera ? "Opera" : "Web Browser";
|
||||
deviceName = browser.tizen ? 'Samsung Smart TV' : browser.web0s ? 'LG Smart TV' : browser.operaTv ? 'Opera TV' : browser.xboxOne ? 'Xbox One' : browser.ps4 ? 'Sony PS4' : browser.chrome ? 'Chrome' : browser.edge ? 'Edge' : browser.firefox ? 'Firefox' : browser.msie ? 'Internet Explorer' : browser.opera ? 'Opera' : browser.safari ? 'Safari' : 'Web Browser';
|
||||
|
||||
if (browser.ipad) {
|
||||
deviceName += " iPad";
|
||||
deviceName += ' iPad';
|
||||
} else {
|
||||
if (browser.iphone) {
|
||||
deviceName += " iPhone";
|
||||
deviceName += ' iPhone';
|
||||
} else {
|
||||
if (browser.android) {
|
||||
deviceName += " Android";
|
||||
deviceName += ' Android';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,12 +124,12 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
}
|
||||
|
||||
var element = document.documentElement;
|
||||
return (element.requestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen || element.msRequestFullscreen) || document.createElement("video").webkitEnterFullscreen;
|
||||
return (element.requestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen || element.msRequestFullscreen) || document.createElement('video').webkitEnterFullscreen;
|
||||
}
|
||||
|
||||
function getSyncProfile() {
|
||||
return new Promise(function (resolve) {
|
||||
require(["browserdeviceprofile", "appSettings"], function (profileBuilder, appSettings) {
|
||||
require(['browserdeviceprofile', 'appSettings'], function (profileBuilder, appSettings) {
|
||||
var profile;
|
||||
|
||||
if (window.NativeShell) {
|
||||
|
@ -156,7 +145,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
}
|
||||
|
||||
function getDefaultLayout() {
|
||||
return "desktop";
|
||||
return 'desktop';
|
||||
}
|
||||
|
||||
function supportsHtmlMediaAutoplay() {
|
||||
|
@ -168,23 +157,25 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
return false;
|
||||
}
|
||||
|
||||
var savedResult = appSettings.get(htmlMediaAutoplayAppStorageKey);
|
||||
return "true" === savedResult || "false" !== savedResult && null;
|
||||
return true;
|
||||
}
|
||||
|
||||
function cueSupported() {
|
||||
function supportsCue() {
|
||||
try {
|
||||
var video = document.createElement("video");
|
||||
var style = document.createElement("style");
|
||||
style.textContent = "video::cue {background: inherit}";
|
||||
var video = document.createElement('video');
|
||||
var style = document.createElement('style');
|
||||
|
||||
style.textContent = 'video::cue {background: inherit}';
|
||||
document.body.appendChild(style);
|
||||
document.body.appendChild(video);
|
||||
var cue = window.getComputedStyle(video, "::cue").background;
|
||||
|
||||
var cue = window.getComputedStyle(video, '::cue').background;
|
||||
document.body.removeChild(style);
|
||||
document.body.removeChild(video);
|
||||
|
||||
return !!cue.length;
|
||||
} catch (err) {
|
||||
console.log("Error detecting cue support:" + err);
|
||||
console.error('error detecting cue support: ' + err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -192,150 +183,172 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
function onAppVisible() {
|
||||
if (isHidden) {
|
||||
isHidden = false;
|
||||
console.log("triggering app resume event");
|
||||
events.trigger(appHost, "resume");
|
||||
console.debug('triggering app resume event');
|
||||
events.trigger(appHost, 'resume');
|
||||
}
|
||||
}
|
||||
|
||||
function onAppHidden() {
|
||||
if (!isHidden) {
|
||||
isHidden = true;
|
||||
console.log("app is hidden");
|
||||
console.debug('app is hidden');
|
||||
}
|
||||
}
|
||||
|
||||
var htmlMediaAutoplayAppStorageKey = "supportshtmlmediaautoplay0";
|
||||
|
||||
var supportedFeatures = function () {
|
||||
var features = [];
|
||||
|
||||
if (navigator.share) {
|
||||
features.push("sharing");
|
||||
features.push('sharing');
|
||||
}
|
||||
|
||||
if (!browser.edgeUwp && !browser.tv && !browser.xboxOne && !browser.ps4) {
|
||||
features.push("filedownload");
|
||||
features.push('filedownload');
|
||||
}
|
||||
|
||||
if (browser.operaTv || browser.tizen || browser.orsay || browser.web0s) {
|
||||
features.push("exit");
|
||||
features.push('exit');
|
||||
} else {
|
||||
features.push("exitmenu");
|
||||
features.push("plugins");
|
||||
features.push('exitmenu');
|
||||
features.push('plugins');
|
||||
}
|
||||
|
||||
if (!browser.operaTv && !browser.tizen && !browser.orsay && !browser.web0s && !browser.ps4) {
|
||||
features.push("externallinks");
|
||||
features.push("externalpremium");
|
||||
features.push('externallinks');
|
||||
features.push('externalpremium');
|
||||
}
|
||||
|
||||
if (!browser.operaTv) {
|
||||
features.push("externallinkdisplay");
|
||||
features.push('externallinkdisplay');
|
||||
}
|
||||
|
||||
if (supportsVoiceInput()) {
|
||||
features.push("voiceinput");
|
||||
}
|
||||
|
||||
if (!browser.tv && !browser.xboxOne) {
|
||||
browser.ps4;
|
||||
features.push('voiceinput');
|
||||
}
|
||||
|
||||
if (supportsHtmlMediaAutoplay()) {
|
||||
features.push("htmlaudioautoplay");
|
||||
features.push("htmlvideoautoplay");
|
||||
features.push('htmlaudioautoplay');
|
||||
features.push('htmlvideoautoplay');
|
||||
}
|
||||
|
||||
if (browser.edgeUwp) {
|
||||
features.push("sync");
|
||||
features.push('sync');
|
||||
}
|
||||
|
||||
if (supportsFullscreen()) {
|
||||
features.push("fullscreenchange");
|
||||
features.push('fullscreenchange');
|
||||
}
|
||||
|
||||
if (browser.chrome || browser.edge && !browser.slow) {
|
||||
if (!browser.noAnimation && !browser.edgeUwp && !browser.xboxOne) {
|
||||
features.push("imageanalysis");
|
||||
features.push('imageanalysis');
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.tv || browser.xboxOne || browser.ps4 || browser.mobile) {
|
||||
features.push("physicalvolumecontrol");
|
||||
features.push('physicalvolumecontrol');
|
||||
}
|
||||
|
||||
if (!browser.tv && !browser.xboxOne && !browser.ps4) {
|
||||
features.push("remotecontrol");
|
||||
features.push('remotecontrol');
|
||||
}
|
||||
|
||||
if (!browser.operaTv && !browser.tizen && !browser.orsay && !browser.web0s && !browser.edgeUwp) {
|
||||
features.push("remotevideo");
|
||||
features.push('remotevideo');
|
||||
}
|
||||
|
||||
features.push("displaylanguage");
|
||||
features.push("otherapppromotions");
|
||||
features.push("displaymode");
|
||||
features.push("targetblank");
|
||||
// allows users to connect to more than one server
|
||||
//features.push("multiserver");
|
||||
features.push("screensaver");
|
||||
features.push('displaylanguage');
|
||||
features.push('otherapppromotions');
|
||||
features.push('displaymode');
|
||||
features.push('targetblank');
|
||||
features.push('screensaver');
|
||||
|
||||
if (!browser.orsay && !browser.tizen && !browser.msie && (browser.firefox || browser.ps4 || browser.edge || cueSupported())) {
|
||||
features.push("subtitleappearancesettings");
|
||||
webSettings.enableMultiServer().then(enabled => {
|
||||
if (enabled) features.push('multiserver');
|
||||
});
|
||||
|
||||
if (!browser.orsay && !browser.msie && (browser.firefox || browser.ps4 || browser.edge || supportsCue())) {
|
||||
features.push('subtitleappearancesettings');
|
||||
}
|
||||
|
||||
if (!browser.orsay && !browser.tizen) {
|
||||
features.push("subtitleburnsettings");
|
||||
if (!browser.orsay) {
|
||||
features.push('subtitleburnsettings');
|
||||
}
|
||||
|
||||
if (!browser.tv && !browser.ps4 && !browser.xboxOne) {
|
||||
features.push("fileinput");
|
||||
features.push('fileinput');
|
||||
}
|
||||
|
||||
if (browser.chrome) {
|
||||
features.push("chromecast");
|
||||
features.push('chromecast');
|
||||
}
|
||||
|
||||
return features;
|
||||
}();
|
||||
|
||||
if (supportedFeatures.indexOf("htmlvideoautoplay") === -1 && supportsHtmlMediaAutoplay() !== false) {
|
||||
require(["autoPlayDetect"], function (autoPlayDetect) {
|
||||
autoPlayDetect.supportsHtmlMediaAutoplay().then(function () {
|
||||
appSettings.set(htmlMediaAutoplayAppStorageKey, "true");
|
||||
supportedFeatures.push("htmlvideoautoplay");
|
||||
supportedFeatures.push("htmlaudioautoplay");
|
||||
}, function () {
|
||||
appSettings.set(htmlMediaAutoplayAppStorageKey, "false");
|
||||
/**
|
||||
* Do exit according to platform
|
||||
*/
|
||||
function doExit() {
|
||||
try {
|
||||
if (window.NativeShell) {
|
||||
window.NativeShell.AppHost.exit();
|
||||
} else if (browser.tizen) {
|
||||
tizen.application.getCurrentApplication().exit();
|
||||
} else if (browser.web0s) {
|
||||
webOS.platformBack();
|
||||
} else {
|
||||
window.close();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('error closing application: ' + err);
|
||||
}
|
||||
}
|
||||
|
||||
var exitPromise;
|
||||
|
||||
/**
|
||||
* Ask user for exit
|
||||
*/
|
||||
function askForExit() {
|
||||
if (exitPromise) {
|
||||
return;
|
||||
}
|
||||
|
||||
require(['actionsheet'], function (actionsheet) {
|
||||
exitPromise = actionsheet.show({
|
||||
title: globalize.translate('MessageConfirmAppExit'),
|
||||
items: [
|
||||
{id: 'yes', name: globalize.translate('Yes')},
|
||||
{id: 'no', name: globalize.translate('No')}
|
||||
]
|
||||
}).then(function (value) {
|
||||
if (value === 'yes') {
|
||||
doExit();
|
||||
}
|
||||
}).finally(function () {
|
||||
exitPromise = null;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var deviceId;
|
||||
var deviceName;
|
||||
var appName = "Jellyfin Web";
|
||||
var appVersion = "10.5.0";
|
||||
var visibilityChange;
|
||||
var visibilityState;
|
||||
var appName = 'Jellyfin Web';
|
||||
var appVersion = '10.6.0';
|
||||
|
||||
var appHost = {
|
||||
getWindowState: function () {
|
||||
return document.windowState || "Normal";
|
||||
return document.windowState || 'Normal';
|
||||
},
|
||||
setWindowState: function (state) {
|
||||
alert("setWindowState is not supported and should not be called");
|
||||
alert('setWindowState is not supported and should not be called');
|
||||
},
|
||||
exit: function () {
|
||||
if (window.NativeShell) {
|
||||
window.NativeShell.AppHost.exit();
|
||||
} else if (browser.tizen) {
|
||||
try {
|
||||
tizen.application.getCurrentApplication().exit();
|
||||
} catch (err) {
|
||||
console.log("error closing application: " + err);
|
||||
}
|
||||
if (!!window.appMode && browser.tizen) {
|
||||
askForExit();
|
||||
} else {
|
||||
window.close();
|
||||
doExit();
|
||||
}
|
||||
},
|
||||
supports: function (command) {
|
||||
|
@ -346,14 +359,14 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
return -1 !== supportedFeatures.indexOf(command.toLowerCase());
|
||||
},
|
||||
preferVisualCards: browser.android || browser.chrome,
|
||||
moreIcon: browser.android ? "dots-vert" : "dots-horiz",
|
||||
moreIcon: browser.android ? 'more_vert' : 'more_horiz',
|
||||
getSyncProfile: getSyncProfile,
|
||||
getDefaultLayout: function () {
|
||||
if (window.NativeShell) {
|
||||
return window.NativeShell.AppHost.getDefaultLayout();
|
||||
}
|
||||
|
||||
return getDefaultLayout()
|
||||
return getDefaultLayout();
|
||||
},
|
||||
getDeviceProfile: getDeviceProfile,
|
||||
init: function () {
|
||||
|
@ -382,58 +395,44 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
|||
return {};
|
||||
},
|
||||
setThemeColor: function (color) {
|
||||
var metaThemeColor = document.querySelector("meta[name=theme-color]");
|
||||
var metaThemeColor = document.querySelector('meta[name=theme-color]');
|
||||
|
||||
if (metaThemeColor) {
|
||||
metaThemeColor.setAttribute("content", color);
|
||||
metaThemeColor.setAttribute('content', color);
|
||||
}
|
||||
},
|
||||
setUserScalable: function (scalable) {
|
||||
if (!browser.tv) {
|
||||
var att = scalable ? "width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes" : "width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no";
|
||||
document.querySelector("meta[name=viewport]").setAttribute("content", att);
|
||||
var att = scalable ? 'width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes' : 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no';
|
||||
document.querySelector('meta[name=viewport]').setAttribute('content', att);
|
||||
}
|
||||
}
|
||||
};
|
||||
var doc = self.document;
|
||||
|
||||
if (doc) {
|
||||
if (void 0 !== doc.visibilityState) {
|
||||
visibilityChange = "visibilitychange";
|
||||
visibilityState = "hidden";
|
||||
} else {
|
||||
if (void 0 !== doc.mozHidden) {
|
||||
visibilityChange = "mozvisibilitychange";
|
||||
visibilityState = "mozVisibilityState";
|
||||
} else {
|
||||
if (void 0 !== doc.msHidden) {
|
||||
visibilityChange = "msvisibilitychange";
|
||||
visibilityState = "msVisibilityState";
|
||||
} else {
|
||||
if (void 0 !== doc.webkitHidden) {
|
||||
visibilityChange = "webkitvisibilitychange";
|
||||
visibilityState = "webkitVisibilityState";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isHidden = false;
|
||||
var hidden;
|
||||
var visibilityChange;
|
||||
|
||||
if (doc) {
|
||||
doc.addEventListener(visibilityChange, function () {
|
||||
if (document[visibilityState]) {
|
||||
onAppHidden();
|
||||
} else {
|
||||
onAppVisible();
|
||||
}
|
||||
});
|
||||
if (typeof document.hidden !== 'undefined') { /* eslint-disable-line compat/compat */
|
||||
hidden = 'hidden';
|
||||
visibilityChange = 'visibilitychange';
|
||||
} else if (typeof document.webkitHidden !== 'undefined') {
|
||||
hidden = 'webkitHidden';
|
||||
visibilityChange = 'webkitvisibilitychange';
|
||||
}
|
||||
|
||||
document.addEventListener(visibilityChange, function () {
|
||||
/* eslint-disable-next-line compat/compat */
|
||||
if (document[hidden]) {
|
||||
onAppHidden();
|
||||
} else {
|
||||
onAppVisible();
|
||||
}
|
||||
}, false);
|
||||
|
||||
if (self.addEventListener) {
|
||||
self.addEventListener("focus", onAppVisible);
|
||||
self.addEventListener("blur", onAppHidden);
|
||||
self.addEventListener('focus', onAppVisible);
|
||||
self.addEventListener('blur', onAppHidden);
|
||||
}
|
||||
|
||||
return appHost;
|
||||
|
|
|
@ -1,71 +1,73 @@
|
|||
define(["focusManager", "layoutManager"], function (focusManager, layoutManager) {
|
||||
"use strict";
|
||||
/* eslint-disable indent */
|
||||
|
||||
/**
|
||||
* Module for performing auto-focus.
|
||||
* @module components/autoFocuser
|
||||
*/
|
||||
|
||||
import focusManager from 'focusManager';
|
||||
import layoutManager from 'layoutManager';
|
||||
|
||||
/**
|
||||
* Previously selected element.
|
||||
*/
|
||||
var activeElement;
|
||||
let activeElement;
|
||||
|
||||
/**
|
||||
* Returns true if AutoFocuser is enabled.
|
||||
* Returns _true_ if AutoFocuser is enabled.
|
||||
*/
|
||||
function isEnabled() {
|
||||
export function isEnabled() {
|
||||
return layoutManager.tv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start AutoFocuser
|
||||
* Start AutoFocuser.
|
||||
*/
|
||||
function enable() {
|
||||
export function enable() {
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener("focusin", function (e) {
|
||||
window.addEventListener('focusin', function (e) {
|
||||
activeElement = e.target;
|
||||
});
|
||||
|
||||
console.log("AutoFocuser enabled");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array from some source.
|
||||
*/
|
||||
var arrayFrom = Array.prototype.from || function (src) {
|
||||
return Array.prototype.slice.call(src);
|
||||
console.debug('AutoFocuser enabled');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set focus on a suitable element, taking into account the previously selected.
|
||||
* @param {HTMLElement} [container] - Element to limit scope.
|
||||
* @returns {HTMLElement} Focused element.
|
||||
*/
|
||||
function autoFocus(container) {
|
||||
export function autoFocus(container) {
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
container = container || document.body;
|
||||
|
||||
var candidates = [];
|
||||
let candidates = [];
|
||||
|
||||
if (activeElement) {
|
||||
// These elements are recreated
|
||||
if (activeElement.classList.contains("btnPreviousPage")) {
|
||||
candidates.push(container.querySelector(".btnPreviousPage"));
|
||||
candidates.push(container.querySelector(".btnNextPage"));
|
||||
} else if (activeElement.classList.contains("btnNextPage")) {
|
||||
candidates.push(container.querySelector(".btnNextPage"));
|
||||
candidates.push(container.querySelector(".btnPreviousPage"));
|
||||
} else if (activeElement.classList.contains("btnSelectView")) {
|
||||
candidates.push(container.querySelector(".btnSelectView"));
|
||||
if (activeElement.classList.contains('btnPreviousPage')) {
|
||||
candidates.push(container.querySelector('.btnPreviousPage'));
|
||||
candidates.push(container.querySelector('.btnNextPage'));
|
||||
} else if (activeElement.classList.contains('btnNextPage')) {
|
||||
candidates.push(container.querySelector('.btnNextPage'));
|
||||
candidates.push(container.querySelector('.btnPreviousPage'));
|
||||
} else if (activeElement.classList.contains('btnSelectView')) {
|
||||
candidates.push(container.querySelector('.btnSelectView'));
|
||||
}
|
||||
|
||||
candidates.push(activeElement);
|
||||
}
|
||||
|
||||
candidates = candidates.concat(arrayFrom(container.querySelectorAll(".btnResume")));
|
||||
candidates = candidates.concat(arrayFrom(container.querySelectorAll(".btnPlay")));
|
||||
candidates = candidates.concat(Array.from(container.querySelectorAll('.btnResume')));
|
||||
candidates = candidates.concat(Array.from(container.querySelectorAll('.btnPlay')));
|
||||
|
||||
var focusedElement;
|
||||
let focusedElement;
|
||||
|
||||
candidates.every(function (element) {
|
||||
if (focusManager.isCurrentlyFocusable(element)) {
|
||||
|
@ -79,7 +81,7 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
|
|||
|
||||
if (!focusedElement) {
|
||||
// FIXME: Multiple itemsContainers
|
||||
var itemsContainer = container.querySelector(".itemsContainer");
|
||||
const itemsContainer = container.querySelector('.itemsContainer');
|
||||
|
||||
if (itemsContainer) {
|
||||
focusedElement = focusManager.autoFocus(itemsContainer);
|
||||
|
@ -93,9 +95,10 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
|
|||
return focusedElement;
|
||||
}
|
||||
|
||||
return {
|
||||
isEnabled: isEnabled,
|
||||
enable: enable,
|
||||
autoFocus: autoFocus
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
|
||||
export default {
|
||||
isEnabled: isEnabled,
|
||||
enable: enable,
|
||||
autoFocus: autoFocus
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./backdrop'], function (browser, connectionManager, playbackManager, dom) {
|
||||
define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings', 'css!./backdrop'], function (browser, connectionManager, playbackManager, dom, userSettings) {
|
||||
'use strict';
|
||||
|
||||
function enableAnimation(elem) {
|
||||
|
@ -180,8 +180,9 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./backdro
|
|||
if (item.BackdropImageTags && item.BackdropImageTags.length > 0) {
|
||||
return item.BackdropImageTags.map(function (imgTag, index) {
|
||||
return apiClient.getScaledImageUrl(item.BackdropItemId || item.Id, Object.assign(imageOptions, {
|
||||
type: "Backdrop",
|
||||
type: 'Backdrop',
|
||||
tag: imgTag,
|
||||
maxWidth: dom.getScreenWidth(),
|
||||
index: index
|
||||
}));
|
||||
});
|
||||
|
@ -190,8 +191,9 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./backdro
|
|||
if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
|
||||
return item.ParentBackdropImageTags.map(function (imgTag, index) {
|
||||
return apiClient.getScaledImageUrl(item.ParentBackdropItemId, Object.assign(imageOptions, {
|
||||
type: "Backdrop",
|
||||
type: 'Backdrop',
|
||||
tag: imgTag,
|
||||
maxWidth: dom.getScreenWidth(),
|
||||
index: index
|
||||
}));
|
||||
});
|
||||
|
@ -236,16 +238,22 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./backdro
|
|||
return true;
|
||||
}
|
||||
|
||||
function enabled() {
|
||||
return userSettings.enableBackdrops();
|
||||
}
|
||||
|
||||
var rotationInterval;
|
||||
var currentRotatingImages = [];
|
||||
var currentRotationIndex = -1;
|
||||
function setBackdrops(items, imageOptions, enableImageRotation) {
|
||||
var images = getImageUrls(items, imageOptions);
|
||||
if (enabled()) {
|
||||
var images = getImageUrls(items, imageOptions);
|
||||
|
||||
if (images.length) {
|
||||
startRotation(images, enableImageRotation);
|
||||
} else {
|
||||
clearBackdrop();
|
||||
if (images.length) {
|
||||
startRotation(images, enableImageRotation);
|
||||
} else {
|
||||
clearBackdrop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,4 +318,4 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./backdro
|
|||
clear: clearBackdrop,
|
||||
externalBackdrop: externalBackdrop
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
define(["connectionManager"], function (connectionManager) {
|
||||
define(['connectionManager'], function (connectionManager) {
|
||||
|
||||
return function () {
|
||||
|
||||
var self = this;
|
||||
|
||||
self.name = "Backdrop ScreenSaver";
|
||||
self.type = "screensaver";
|
||||
self.id = "backdropscreensaver";
|
||||
self.name = 'Backdrop ScreenSaver';
|
||||
self.type = 'screensaver';
|
||||
self.id = 'backdropscreensaver';
|
||||
self.supportsAnonymous = false;
|
||||
|
||||
var currentSlideshow;
|
||||
|
@ -14,12 +14,12 @@ define(["connectionManager"], function (connectionManager) {
|
|||
self.show = function () {
|
||||
|
||||
var query = {
|
||||
ImageTypes: "Backdrop",
|
||||
EnableImageTypes: "Backdrop",
|
||||
IncludeItemTypes: "Movie,Series,MusicArtist",
|
||||
SortBy: "Random",
|
||||
ImageTypes: 'Backdrop',
|
||||
EnableImageTypes: 'Backdrop',
|
||||
IncludeItemTypes: 'Movie,Series,MusicArtist',
|
||||
SortBy: 'Random',
|
||||
Recursive: true,
|
||||
Fields: "Taglines",
|
||||
Fields: 'Taglines',
|
||||
ImageTypeLimit: 1,
|
||||
StartIndex: 0,
|
||||
Limit: 200
|
||||
|
@ -30,7 +30,7 @@ define(["connectionManager"], function (connectionManager) {
|
|||
|
||||
if (result.Items.length) {
|
||||
|
||||
require(["slideshow"], function (slideshow) {
|
||||
require(['slideshow'], function (slideshow) {
|
||||
|
||||
var newSlideShow = new slideshow({
|
||||
showTitle: true,
|
||||
|
@ -52,5 +52,5 @@ define(["connectionManager"], function (connectionManager) {
|
|||
currentSlideshow = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
button {
|
||||
-webkit-border-fit: border !important;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
-webkit-border-fit: border !important;
|
||||
}
|
||||
|
||||
.card {
|
||||
border: 0;
|
||||
font-size: inherit !important;
|
||||
font-family: inherit !important;
|
||||
text-transform: none;
|
||||
background-color: transparent !important;
|
||||
background: none !important;
|
||||
background-color: transparent !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
color: inherit !important;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
outline: none !important;
|
||||
cursor: pointer;
|
||||
contain: layout style;
|
||||
|
@ -54,17 +55,27 @@ button {
|
|||
contain: layout style;
|
||||
}
|
||||
|
||||
.cardPadder-backdrop, .cardPadder-mixedBackdrop, .cardPadder-smallBackdrop, .cardPadder-overflowBackdrop, .cardPadder-overflowSmallBackdrop {
|
||||
.cardPadder-backdrop,
|
||||
.cardPadder-mixedBackdrop,
|
||||
.cardPadder-smallBackdrop,
|
||||
.cardPadder-overflowBackdrop,
|
||||
.cardPadder-overflowSmallBackdrop {
|
||||
padding-bottom: 56.25%;
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
.cardPadder-square, .cardPadder-mixedSquare, .cardPadder-overflowSquare, .overflowSquareCard-textCardPadder {
|
||||
.cardPadder-square,
|
||||
.cardPadder-mixedSquare,
|
||||
.cardPadder-overflowSquare,
|
||||
.overflowSquareCard-textCardPadder {
|
||||
padding-bottom: 100%;
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
.cardPadder-portrait, .cardPadder-mixedPortrait, .cardPadder-overflowPortrait, .overflowPortraitCard-textCardPadder {
|
||||
.cardPadder-portrait,
|
||||
.cardPadder-mixedPortrait,
|
||||
.cardPadder-overflowPortrait,
|
||||
.overflowPortraitCard-textCardPadder {
|
||||
padding-bottom: 150%;
|
||||
contain: strict;
|
||||
}
|
||||
|
@ -79,23 +90,26 @@ button {
|
|||
margin: 0.6em;
|
||||
transition: none;
|
||||
border: 0 solid transparent;
|
||||
|
||||
/* These both are needed in case cardBox is a button */
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
outline: none !important;
|
||||
contain: layout;
|
||||
contain: style;
|
||||
}
|
||||
|
||||
.card.show-animation .cardBox {
|
||||
will-change: transform;
|
||||
transition: transform 200ms ease-out;
|
||||
}
|
||||
|
||||
.card.show-focus:not(.show-animation) .cardBox {
|
||||
margin: .4em;
|
||||
margin: 0.4em;
|
||||
}
|
||||
|
||||
.card.show-focus:not(.show-animation) .cardBox.visualCardBox,
|
||||
.card.show-focus:not(.show-animation) .cardBox:not(.visualCardBox) .cardScalable {
|
||||
border: .5em solid transparent;
|
||||
}
|
||||
|
||||
.card.show-animation .cardBox {
|
||||
will-change: transform;
|
||||
transition: transform 200ms ease-out;
|
||||
border: 0.5em solid transparent;
|
||||
}
|
||||
|
||||
.card.show-animation:focus > .cardBox {
|
||||
|
@ -120,7 +134,7 @@ button {
|
|||
|
||||
.btnCardOptions {
|
||||
position: absolute;
|
||||
bottom: .25em;
|
||||
bottom: 0.25em;
|
||||
right: 0;
|
||||
margin: 0 !important;
|
||||
z-index: 1;
|
||||
|
@ -131,8 +145,8 @@ button {
|
|||
position: absolute;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
top: .3em;
|
||||
left: .3em;
|
||||
top: 0.3em;
|
||||
left: 0.3em;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
width: 1.6em;
|
||||
|
@ -146,12 +160,14 @@ button {
|
|||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
background-clip: content-box !important;
|
||||
color: inherit;
|
||||
|
||||
/* This is only needed for scalable cards */
|
||||
height: 100%;
|
||||
contain: strict;
|
||||
|
@ -173,12 +189,16 @@ button {
|
|||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
/* Needed in case this is a button */
|
||||
display: block;
|
||||
|
||||
/* Needed in case this is a button */
|
||||
margin: 0 !important;
|
||||
|
||||
/* Needed in safari */
|
||||
height: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
outline: none !important;
|
||||
contain: strict;
|
||||
}
|
||||
|
@ -207,10 +227,6 @@ button {
|
|||
box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
|
||||
}
|
||||
|
||||
.cardImageContainer {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.cardImage {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -226,6 +242,7 @@ button {
|
|||
.cardImage-img {
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
|
||||
/* This is simply for lazy image purposes, to ensure the image is visible sooner when scrolling */
|
||||
min-height: 70%;
|
||||
min-width: 70%;
|
||||
|
@ -252,17 +269,17 @@ button {
|
|||
}
|
||||
|
||||
.cardFooter {
|
||||
padding: .3em .3em .5em .3em;
|
||||
padding: 0.3em 0.3em 0.5em 0.3em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.visualCardBox {
|
||||
box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
|
||||
border-radius: .145em;
|
||||
border-radius: 0.145em;
|
||||
}
|
||||
|
||||
.innerCardFooter {
|
||||
background: rgba(0,0,0,.7);
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
@ -282,7 +299,7 @@ button {
|
|||
}
|
||||
|
||||
.cardText {
|
||||
padding: .06em .5em;
|
||||
padding: 0.06em 0.5em;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
@ -294,7 +311,24 @@ button {
|
|||
}
|
||||
|
||||
.cardText-first {
|
||||
padding-top: .24em;
|
||||
padding-top: 0.24em;
|
||||
}
|
||||
|
||||
.textActionButton {
|
||||
border: 0 !important;
|
||||
background: transparent;
|
||||
padding: 0 !important;
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
outline: none !important;
|
||||
color: inherit;
|
||||
vertical-align: middle;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.textActionButton:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cardText > .textActionButton {
|
||||
|
@ -304,7 +338,7 @@ button {
|
|||
}
|
||||
|
||||
.innerCardFooter > .cardText {
|
||||
padding: .3em .5em;
|
||||
padding: 0.3em 0.5em;
|
||||
}
|
||||
|
||||
.cardFooter-withlogo {
|
||||
|
@ -336,36 +370,19 @@ button {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.textActionButton {
|
||||
border: 0 !important;
|
||||
background: transparent;
|
||||
border: 0 !important;
|
||||
padding: 0 !important;
|
||||
cursor: pointer;
|
||||
outline: none !important;
|
||||
color: inherit;
|
||||
vertical-align: middle;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.textActionButton:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cardImageIcon {
|
||||
.cardImageContainer .cardImageIcon {
|
||||
font-size: 5em;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.cardImageIcon-small {
|
||||
font-size: 3em;
|
||||
margin-bottom: .1em;
|
||||
font-size: 3em !important;
|
||||
margin-bottom: 0.1em;
|
||||
}
|
||||
|
||||
.cardIndicators {
|
||||
right: .225em;
|
||||
top: .225em;
|
||||
right: 0.225em;
|
||||
top: 0.225em;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -382,16 +399,16 @@ button {
|
|||
}
|
||||
|
||||
.programAttributeIndicator {
|
||||
padding: .18em .5em;
|
||||
padding: 0.18em 0.5em;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.cardOverlayButton {
|
||||
color: rgba(255, 255, 255, .76);
|
||||
color: rgba(255, 255, 255, 0.76);
|
||||
margin: 0;
|
||||
z-index: 1;
|
||||
padding: .75em;
|
||||
padding: 0.75em;
|
||||
font-size: 88%;
|
||||
}
|
||||
|
||||
|
@ -402,7 +419,7 @@ button {
|
|||
}
|
||||
|
||||
.cardOverlayButtonIcon {
|
||||
background-color: rgba(0,0,0,.7) !important;
|
||||
background-color: rgba(0, 0, 0, 0.7) !important;
|
||||
border-radius: 100em;
|
||||
width: 1.5em !important;
|
||||
height: 1.5em !important;
|
||||
|
@ -412,6 +429,12 @@ button {
|
|||
font-size: 1.66956521739130434em !important;
|
||||
}
|
||||
|
||||
.cardOverlayButtonIcon.material-icons {
|
||||
/* material-icons override display, so we need to
|
||||
make a better matching selector to set it to flex */
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.cardOverlayButton-centered {
|
||||
bottom: initial;
|
||||
right: initial;
|
||||
|
@ -424,10 +447,10 @@ button {
|
|||
height: 2.6em;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
background-color: rgba(0,0,0,.5) !important;
|
||||
border: .06em solid rgba(255,255,255,.6);
|
||||
padding: .38em !important;
|
||||
color: rgba(255, 255, 255, .76);
|
||||
background-color: rgba(0, 0, 0, 0.5) !important;
|
||||
border: 0.06em solid rgba(255, 255, 255, 0.6);
|
||||
padding: 0.38em !important;
|
||||
color: rgba(255, 255, 255, 0.76);
|
||||
transition: transform 200ms ease-out;
|
||||
}
|
||||
|
||||
|
@ -474,13 +497,15 @@ button {
|
|||
width: 33.333333333333333333333333333333%;
|
||||
}
|
||||
|
||||
.squareCard, .portraitCard {
|
||||
.squareCard,
|
||||
.portraitCard {
|
||||
width: 33.333333333333333333333333333333%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 43.75em) {
|
||||
.squareCard, .portraitCard {
|
||||
.squareCard,
|
||||
.portraitCard {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
@ -496,7 +521,8 @@ button {
|
|||
width: 50%;
|
||||
}
|
||||
|
||||
.squareCard, .portraitCard {
|
||||
.squareCard,
|
||||
.portraitCard {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
|
@ -516,7 +542,8 @@ button {
|
|||
width: 25%;
|
||||
}
|
||||
|
||||
.squareCard, .portraitCard {
|
||||
.squareCard,
|
||||
.portraitCard {
|
||||
width: 16.666666666666666666666666666667%;
|
||||
}
|
||||
|
||||
|
@ -529,9 +556,9 @@ button {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 87.5em) {
|
||||
.squareCard, .portraitCard {
|
||||
.squareCard,
|
||||
.portraitCard {
|
||||
width: 14.285714285714285714285714285714%;
|
||||
}
|
||||
|
||||
|
@ -549,13 +576,15 @@ button {
|
|||
width: 20%;
|
||||
}
|
||||
|
||||
.squareCard, .portraitCard {
|
||||
.squareCard,
|
||||
.portraitCard {
|
||||
width: 12.5%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 120em) {
|
||||
.squareCard, .portraitCard {
|
||||
.squareCard,
|
||||
.portraitCard {
|
||||
width: 11.111111111111111111111111111111%;
|
||||
}
|
||||
}
|
||||
|
@ -565,7 +594,8 @@ button {
|
|||
width: 25%;
|
||||
}
|
||||
|
||||
.squareCard, .portraitCard {
|
||||
.squareCard,
|
||||
.portraitCard {
|
||||
width: 10%;
|
||||
}
|
||||
}
|
||||
|
@ -596,7 +626,8 @@ button {
|
|||
width: 72vw;
|
||||
}
|
||||
|
||||
.overflowSquareCard, .overflowPortraitCard {
|
||||
.overflowSquareCard,
|
||||
.overflowPortraitCard {
|
||||
width: 40vw;
|
||||
}
|
||||
|
||||
|
@ -621,29 +652,34 @@ button {
|
|||
}
|
||||
|
||||
@media (min-width: 43.75em) {
|
||||
.overflowSquareCard, .overflowPortraitCard {
|
||||
.overflowSquareCard,
|
||||
.overflowPortraitCard {
|
||||
width: 23.1vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 48.125em) {
|
||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
||||
.overflowBackdropCard,
|
||||
.overflowSmallBackdropCard {
|
||||
width: 30vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (orientation: landscape) {
|
||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
||||
.overflowBackdropCard,
|
||||
.overflowSmallBackdropCard {
|
||||
width: 30vw;
|
||||
}
|
||||
|
||||
.overflowSquareCard, .overflowPortraitCard {
|
||||
.overflowSquareCard,
|
||||
.overflowPortraitCard {
|
||||
width: 23.1vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (orientation: landscape) and (min-width: 48.125em) {
|
||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
||||
.overflowBackdropCard,
|
||||
.overflowSmallBackdropCard {
|
||||
width: 23.1vw;
|
||||
}
|
||||
}
|
||||
|
@ -655,55 +691,60 @@ button {
|
|||
}
|
||||
|
||||
@media (min-width: 50em) {
|
||||
.overflowSquareCard, .overflowPortraitCard {
|
||||
.overflowSquareCard,
|
||||
.overflowPortraitCard {
|
||||
width: 18.5vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 75em) {
|
||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
||||
.overflowBackdropCard,
|
||||
.overflowSmallBackdropCard {
|
||||
width: 23.1vw;
|
||||
}
|
||||
|
||||
.overflowSquareCard, .overflowPortraitCard {
|
||||
.overflowSquareCard,
|
||||
.overflowPortraitCard {
|
||||
width: 15.5vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 87.5em) {
|
||||
.overflowSquareCard, .overflowPortraitCard {
|
||||
.overflowSquareCard,
|
||||
.overflowPortraitCard {
|
||||
width: 13.3vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 100em) {
|
||||
|
||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
||||
.overflowBackdropCard,
|
||||
.overflowSmallBackdropCard {
|
||||
width: 18.7vw;
|
||||
}
|
||||
|
||||
.overflowSquareCard, .overflowPortraitCard {
|
||||
.overflowSquareCard,
|
||||
.overflowPortraitCard {
|
||||
width: 11.6vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 120em) {
|
||||
|
||||
.overflowSquareCard, .overflowPortraitCard {
|
||||
width: 10.3vw;
|
||||
.overflowSquareCard,
|
||||
.overflowPortraitCard {
|
||||
width: 10.41vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 131.25em) {
|
||||
|
||||
.overflowSquareCard, .overflowPortraitCard {
|
||||
.overflowSquareCard,
|
||||
.overflowPortraitCard {
|
||||
width: 9.3vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 156.25em) {
|
||||
|
||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
||||
.overflowBackdropCard,
|
||||
.overflowSmallBackdropCard {
|
||||
width: 15.6vw;
|
||||
}
|
||||
}
|
||||
|
@ -720,7 +761,8 @@ button {
|
|||
padding-bottom: 87.75%;
|
||||
}
|
||||
|
||||
.itemsContainer-tv > .overflowSquareCard, .itemsContainer-tv > .overflowPortraitCard {
|
||||
.itemsContainer-tv > .overflowSquareCard,
|
||||
.itemsContainer-tv > .overflowPortraitCard {
|
||||
width: 15.6vw;
|
||||
}
|
||||
|
||||
|
@ -729,9 +771,9 @@ button {
|
|||
}
|
||||
|
||||
.cardOverlayContainer {
|
||||
background: rgba(0,0,0,0.5);
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
opacity: 0;
|
||||
transition: opacity .2s;
|
||||
transition: opacity 0.2s;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -748,7 +790,7 @@ button {
|
|||
opacity: 0;
|
||||
transition: 0.2s;
|
||||
background: transparent;
|
||||
padding: 0.5em;
|
||||
padding: 0.25em;
|
||||
}
|
||||
|
||||
.cardOverlayButtonIcon-hover {
|
||||
|
@ -760,7 +802,7 @@ button {
|
|||
}
|
||||
|
||||
.cardOverlayFab-primary {
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
font-size: 130%;
|
||||
padding: 0;
|
||||
width: 3em;
|
||||
|
|
|
@ -68,9 +68,9 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
|
|||
|
||||
return apiClient.getScaledImageUrl(item.Id, {
|
||||
|
||||
maxWidth: maxWidth,
|
||||
maxWidth: maxWidth * 2,
|
||||
tag: chapter.ImageTag,
|
||||
type: "Chapter",
|
||||
type: 'Chapter',
|
||||
index: index
|
||||
});
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
|
|||
var cardImageContainer = imgUrl ? ('<div class="' + cardImageContainerClass + ' lazy" data-src="' + imgUrl + '">') : ('<div class="' + cardImageContainerClass + '">');
|
||||
|
||||
if (!imgUrl) {
|
||||
cardImageContainer += '<i class="md-icon cardImageIcon">local_movies</i>';
|
||||
cardImageContainer += '<span class="material-icons cardImageIcon local_movies"></span>';
|
||||
}
|
||||
|
||||
var nameHtml = '';
|
||||
|
|
34
src/components/castSenderApi.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
define([], function() {
|
||||
'use strict';
|
||||
|
||||
if (window.appMode === 'cordova' || window.appMode === 'android') {
|
||||
return {
|
||||
load: function () {
|
||||
window.chrome = window.chrome || {};
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
var ccLoaded = false;
|
||||
return {
|
||||
load: function () {
|
||||
if (ccLoaded) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
var fileref = document.createElement('script');
|
||||
fileref.setAttribute('type', 'text/javascript');
|
||||
|
||||
fileref.onload = function () {
|
||||
ccLoaded = true;
|
||||
resolve();
|
||||
};
|
||||
|
||||
fileref.setAttribute('src', 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js');
|
||||
document.querySelector('head').appendChild(fileref);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
|
@ -1,44 +1,33 @@
|
|||
define(["dialogHelper", "loading", "connectionManager", "globalize", "actionsheet", "emby-input", "paper-icon-button-light", "emby-button", "listViewStyle", "material-icons", "formDialogStyle"], function (dialogHelper, loading, connectionManager, globalize, actionsheet) {
|
||||
"use strict";
|
||||
define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'actionsheet', 'emby-input', 'paper-icon-button-light', 'emby-button', 'listViewStyle', 'material-icons', 'formDialogStyle'], function (dom, dialogHelper, loading, connectionManager, globalize, actionsheet) {
|
||||
'use strict';
|
||||
|
||||
return function (options) {
|
||||
function parentWithClass(elem, className) {
|
||||
while (!elem.classList || !elem.classList.contains(className)) {
|
||||
elem = elem.parentNode;
|
||||
if (!elem) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
function mapChannel(button, channelId, providerChannelId) {
|
||||
loading.show();
|
||||
var providerId = options.providerId;
|
||||
connectionManager.getApiClient(options.serverId).ajax({
|
||||
type: "POST",
|
||||
url: ApiClient.getUrl("LiveTv/ChannelMappings"),
|
||||
type: 'POST',
|
||||
url: ApiClient.getUrl('LiveTv/ChannelMappings'),
|
||||
data: {
|
||||
providerId: providerId,
|
||||
tunerChannelId: channelId,
|
||||
providerChannelId: providerChannelId
|
||||
},
|
||||
dataType: "json"
|
||||
dataType: 'json'
|
||||
}).then(function (mapping) {
|
||||
var listItem = parentWithClass(button, "listItem");
|
||||
button.setAttribute("data-providerid", mapping.ProviderChannelId);
|
||||
listItem.querySelector(".secondary").innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName);
|
||||
var listItem = dom.parentWithClass(button, 'listItem');
|
||||
button.setAttribute('data-providerid', mapping.ProviderChannelId);
|
||||
listItem.querySelector('.secondary').innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName);
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
function onChannelsElementClick(e) {
|
||||
var btnMap = parentWithClass(e.target, "btnMap");
|
||||
var btnMap = dom.parentWithClass(e.target, 'btnMap');
|
||||
|
||||
if (btnMap) {
|
||||
var channelId = btnMap.getAttribute("data-id");
|
||||
var providerChannelId = btnMap.getAttribute("data-providerid");
|
||||
var channelId = btnMap.getAttribute('data-id');
|
||||
var providerChannelId = btnMap.getAttribute('data-providerid');
|
||||
var menuItems = currentMappingOptions.ProviderChannels.map(function (m) {
|
||||
return {
|
||||
name: m.Name,
|
||||
|
@ -59,56 +48,56 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee
|
|||
|
||||
function getChannelMappingOptions(serverId, providerId) {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
return apiClient.getJSON(apiClient.getUrl("LiveTv/ChannelMappingOptions", {
|
||||
return apiClient.getJSON(apiClient.getUrl('LiveTv/ChannelMappingOptions', {
|
||||
providerId: providerId
|
||||
}));
|
||||
}
|
||||
|
||||
function getMappingSecondaryName(mapping, providerName) {
|
||||
return (mapping.ProviderChannelName || "") + " - " + providerName;
|
||||
return (mapping.ProviderChannelName || '') + ' - ' + providerName;
|
||||
}
|
||||
|
||||
function getTunerChannelHtml(channel, providerName) {
|
||||
var html = "";
|
||||
var html = '';
|
||||
html += '<div class="listItem">';
|
||||
html += '<i class="md-icon listItemIcon">dvr</i>';
|
||||
html += '<span class="material-icons listItemIcon dvr"></span>';
|
||||
html += '<div class="listItemBody two-line">';
|
||||
html += '<h3 class="listItemBodyText">';
|
||||
html += channel.Name;
|
||||
html += "</h3>";
|
||||
html += '</h3>';
|
||||
html += '<div class="secondary listItemBodyText">';
|
||||
|
||||
if (channel.ProviderChannelName) {
|
||||
html += getMappingSecondaryName(channel, providerName);
|
||||
}
|
||||
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += '<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="' + channel.Id + '" data-providerid="' + channel.ProviderChannelId + '"><i class="md-icon">mode_edit</i></button>';
|
||||
return html += "</div>";
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
html += '<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="' + channel.Id + '" data-providerid="' + channel.ProviderChannelId + '"><span class="material-icons mode_edit"></span></button>';
|
||||
return html += '</div>';
|
||||
}
|
||||
|
||||
function getEditorHtml() {
|
||||
var html = "";
|
||||
var html = '';
|
||||
html += '<div class="formDialogContent">';
|
||||
html += '<div class="dialogContentInner dialog-content-centered">';
|
||||
html += '<form style="margin:auto;">';
|
||||
html += "<h1>" + globalize.translate("HeaderChannels") + "</h1>";
|
||||
html += '<h1>' + globalize.translate('HeaderChannels') + '</h1>';
|
||||
html += '<div class="channels paperList">';
|
||||
html += "</div>";
|
||||
html += "</form>";
|
||||
html += "</div>";
|
||||
return html += "</div>";
|
||||
html += '</div>';
|
||||
html += '</form>';
|
||||
html += '</div>';
|
||||
return html += '</div>';
|
||||
}
|
||||
|
||||
function initEditor(dlg, options) {
|
||||
getChannelMappingOptions(options.serverId, options.providerId).then(function (result) {
|
||||
currentMappingOptions = result;
|
||||
var channelsElement = dlg.querySelector(".channels");
|
||||
var channelsElement = dlg.querySelector('.channels');
|
||||
channelsElement.innerHTML = result.TunerChannels.map(function (channel) {
|
||||
return getTunerChannelHtml(channel, result.ProviderName);
|
||||
}).join("");
|
||||
channelsElement.addEventListener("click", onChannelsElementClick);
|
||||
}).join('');
|
||||
channelsElement.addEventListener('click', onChannelsElementClick);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -119,27 +108,27 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee
|
|||
var dialogOptions = {
|
||||
removeOnClose: true
|
||||
};
|
||||
dialogOptions.size = "small";
|
||||
dialogOptions.size = 'small';
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
dlg.classList.add("formDialog");
|
||||
dlg.classList.add("ui-body-a");
|
||||
dlg.classList.add("background-theme-a");
|
||||
var html = "";
|
||||
var title = globalize.translate("MapChannels");
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.classList.add('ui-body-a');
|
||||
dlg.classList.add('background-theme-a');
|
||||
var html = '';
|
||||
var title = globalize.translate('MapChannels');
|
||||
html += '<div class="formDialogHeader">';
|
||||
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="md-icon">arrow_back</i></button>';
|
||||
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<h3 class="formDialogHeaderTitle">';
|
||||
html += title;
|
||||
html += "</h3>";
|
||||
html += "</div>";
|
||||
html += '</h3>';
|
||||
html += '</div>';
|
||||
html += getEditorHtml();
|
||||
dlg.innerHTML = html;
|
||||
initEditor(dlg, options);
|
||||
dlg.querySelector(".btnCancel").addEventListener("click", function () {
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
return new Promise(function (resolve, reject) {
|
||||
dlg.addEventListener("close", resolve);
|
||||
dlg.addEventListener('close', resolve);
|
||||
dialogHelper.open(dlg);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -37,69 +37,69 @@ define(['events'], function (events) {
|
|||
// 5) It wasn't as smart as it could have been about what should be part of a
|
||||
// URL and what should be part of human language.
|
||||
|
||||
var protocols = "(?:(?:http|https|rtsp|ftp):\\/\\/)";
|
||||
var protocols = '(?:(?:http|https|rtsp|ftp):\\/\\/)';
|
||||
var credentials = "(?:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,64}" // username (1-64 normal or url escaped characters)
|
||||
+ "(?:\\:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,25})?" // followed by optional password (: + 1-25 normal or url escaped characters)
|
||||
+ "\\@)";
|
||||
+ '\\@)';
|
||||
|
||||
// IPv6 Regex http://forums.intermapper.com/viewtopic.php?t=452
|
||||
// by Dartware, LLC is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License
|
||||
// http://intermapper.com/
|
||||
var ipv6 = "("
|
||||
+ "(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))"
|
||||
+ "|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))"
|
||||
+ "|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))"
|
||||
+ "|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
|
||||
+ "|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
|
||||
+ "|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
|
||||
+ "|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
|
||||
+ "|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
|
||||
+ ")(%.+)?";
|
||||
var ipv6 = '('
|
||||
+ '(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))'
|
||||
+ '|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))'
|
||||
+ '|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))'
|
||||
+ '|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
|
||||
+ '|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
|
||||
+ '|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
|
||||
+ '|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
|
||||
+ '|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
|
||||
+ ')(%.+)?';
|
||||
|
||||
var ipv4 = "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\."
|
||||
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\."
|
||||
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\."
|
||||
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])";
|
||||
var ipv4 = '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.'
|
||||
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.'
|
||||
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.'
|
||||
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])';
|
||||
|
||||
// This would have been a lot cleaner if JS RegExp supported conditionals...
|
||||
var linkRegExpString =
|
||||
|
||||
// begin match for protocol / username / password / host
|
||||
"(?:"
|
||||
'(?:'
|
||||
|
||||
// ============================
|
||||
// If we have a recognized protocol at the beginning of the URL, we're
|
||||
// more relaxed about what we accept, because we assume the user wants
|
||||
// this to be a URL, and we're not accidentally matching human language
|
||||
+ protocols + "?"
|
||||
+ protocols + '?'
|
||||
|
||||
// optional username:password@
|
||||
+ credentials + "?"
|
||||
+ credentials + '?'
|
||||
|
||||
// IP address (both v4 and v6)
|
||||
+ "(?:"
|
||||
+ '(?:'
|
||||
|
||||
// IPv6
|
||||
+ ipv6
|
||||
|
||||
// IPv4
|
||||
+ "|" + ipv4
|
||||
+ '|' + ipv4
|
||||
|
||||
+ ")"
|
||||
+ ')'
|
||||
|
||||
// end match for protocol / username / password / host
|
||||
+ ")"
|
||||
+ ')'
|
||||
|
||||
// optional port number
|
||||
+ "(?:\\:\\d{1,5})?"
|
||||
+ '(?:\\:\\d{1,5})?'
|
||||
|
||||
// plus optional path and query params (no unicode allowed here?)
|
||||
+ "(?:"
|
||||
+ "\\/(?:"
|
||||
+ '(?:'
|
||||
+ '\\/(?:'
|
||||
// some characters we'll accept because it's unlikely human language
|
||||
// would use them after a URL unless they were part of the url
|
||||
+ "(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])"
|
||||
+ "|(?:\\%[a-f0-9]{2})"
|
||||
+ '(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])'
|
||||
+ '|(?:\\%[a-f0-9]{2})'
|
||||
// some characters are much more likely to be used AFTER a url and
|
||||
// were not intended to be included in the url itself. Mostly end
|
||||
// of sentence type things. It's also likely that the URL would
|
||||
|
@ -108,9 +108,9 @@ define(['events'], function (events) {
|
|||
// they must be followed by another character that we're reasonably
|
||||
// sure is part of the url
|
||||
+ "|(?:[\\;\\?\\:\\.\\!\\'\\(\\)\\,\\=]+(?=(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])|(?:\\%[a-f0-9]{2})))"
|
||||
+ ")*"
|
||||
+ "|\\b|\$"
|
||||
+ ")";
|
||||
+ ')*'
|
||||
+ '|\\b|\$'
|
||||
+ ')';
|
||||
|
||||
// regex = XRegExp(regex,'gi');
|
||||
var linkRegExp = RegExp(linkRegExpString, 'gi');
|
||||
|
@ -120,7 +120,7 @@ define(['events'], function (events) {
|
|||
// if url doesn't begin with a known protocol, add http by default
|
||||
function ensureProtocol(url) {
|
||||
if (!url.match(protocolRegExp)) {
|
||||
url = "http://" + url;
|
||||
url = 'http://' + url;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
@ -131,8 +131,9 @@ define(['events'], function (events) {
|
|||
var links = [];
|
||||
var match;
|
||||
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while (match = linkRegExp.exec(text)) {
|
||||
// console.log(matches);
|
||||
console.debug(match);
|
||||
var txt = match[0];
|
||||
var pos = match.index;
|
||||
var len = txt.length;
|
||||
|
@ -187,9 +188,9 @@ define(['events'], function (events) {
|
|||
return apiClient.getEndpointInfo().then(function (endpoint) {
|
||||
if (endpoint.IsInNetwork) {
|
||||
return apiClient.getPublicSystemInfo().then(function (info) {
|
||||
var localAddress = info.LocalAddress
|
||||
var localAddress = info.LocalAddress;
|
||||
if (!localAddress) {
|
||||
console.log("No valid local address returned, defaulting to external one")
|
||||
console.debug('No valid local address returned, defaulting to external one');
|
||||
localAddress = serverAddress;
|
||||
}
|
||||
addToCache(serverAddress, localAddress);
|
||||
|
@ -230,4 +231,4 @@ define(['events'], function (events) {
|
|||
return {
|
||||
getServerAddress: getServerAddress
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
var currentResolve;
|
||||
var currentReject;
|
||||
|
||||
var PlayerName = 'Chromecast';
|
||||
var PlayerName = 'Google Cast';
|
||||
|
||||
function sendConnectionResult(isOk) {
|
||||
|
||||
|
@ -54,7 +54,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
|
||||
// production version registered with google
|
||||
// replace this value if you want to test changes on another instance
|
||||
var applicationID = "F007D354";
|
||||
var applicationID = 'F007D354';
|
||||
|
||||
var messageNamespace = 'urn:x-cast:com.connectsdk';
|
||||
|
||||
|
@ -105,7 +105,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
this.sessionListener.bind(this),
|
||||
this.receiverListener.bind(this));
|
||||
|
||||
console.log('chromecast.initialize');
|
||||
console.debug('chromecast.initialize');
|
||||
chrome.cast.initialize(apiConfig, this.onInitSuccess.bind(this), this.errorHandler);
|
||||
};
|
||||
|
||||
|
@ -114,14 +114,14 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
*/
|
||||
CastPlayer.prototype.onInitSuccess = function () {
|
||||
this.isInitialized = true;
|
||||
console.log("chromecast init success");
|
||||
console.debug('chromecast init success');
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic error callback function
|
||||
*/
|
||||
CastPlayer.prototype.onError = function () {
|
||||
console.log("chromecast error");
|
||||
console.debug('chromecast error');
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -177,10 +177,10 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
*/
|
||||
CastPlayer.prototype.receiverListener = function (e) {
|
||||
if (e === 'available') {
|
||||
console.log("chromecast receiver found");
|
||||
console.debug('chromecast receiver found');
|
||||
this.hasReceivers = true;
|
||||
} else {
|
||||
console.log("chromecast receiver list empty");
|
||||
console.debug('chromecast receiver list empty');
|
||||
this.hasReceivers = false;
|
||||
}
|
||||
};
|
||||
|
@ -190,15 +190,15 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
*/
|
||||
CastPlayer.prototype.sessionUpdateListener = function (isAlive) {
|
||||
if (isAlive) {
|
||||
console.log('sessionUpdateListener: already alive');
|
||||
console.debug('sessionUpdateListener: already alive');
|
||||
} else {
|
||||
this.session = null;
|
||||
this.deviceState = DEVICE_STATE.IDLE;
|
||||
this.castPlayerState = PLAYER_STATE.IDLE;
|
||||
document.removeEventListener("volumeupbutton", onVolumeUpKeyDown, false);
|
||||
document.removeEventListener("volumedownbutton", onVolumeDownKeyDown, false);
|
||||
document.removeEventListener('volumeupbutton', onVolumeUpKeyDown, false);
|
||||
document.removeEventListener('volumedownbutton', onVolumeDownKeyDown, false);
|
||||
|
||||
console.log('sessionUpdateListener: setting currentMediaSession to null');
|
||||
console.debug('sessionUpdateListener: setting currentMediaSession to null');
|
||||
this.currentMediaSession = null;
|
||||
|
||||
sendConnectionResult(false);
|
||||
|
@ -211,7 +211,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
* session request in opt_sessionRequest.
|
||||
*/
|
||||
CastPlayer.prototype.launchApp = function () {
|
||||
console.log("chromecast launching app...");
|
||||
console.debug('chromecast launching app...');
|
||||
chrome.cast.requestSession(this.onRequestSessionSuccess.bind(this), this.onLaunchError.bind(this));
|
||||
};
|
||||
|
||||
|
@ -220,7 +220,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
* @param {Object} e A chrome.cast.Session object
|
||||
*/
|
||||
CastPlayer.prototype.onRequestSessionSuccess = function (e) {
|
||||
console.log("chromecast session success: " + e.sessionId);
|
||||
console.debug('chromecast session success: ' + e.sessionId);
|
||||
this.onSessionConnected(e);
|
||||
};
|
||||
|
||||
|
@ -232,8 +232,8 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
this.session.addMediaListener(this.sessionMediaListener.bind(this));
|
||||
this.session.addUpdateListener(this.sessionUpdateListener.bind(this));
|
||||
|
||||
document.addEventListener("volumeupbutton", onVolumeUpKeyDown, false);
|
||||
document.addEventListener("volumedownbutton", onVolumeDownKeyDown, false);
|
||||
document.addEventListener('volumeupbutton', onVolumeUpKeyDown, false);
|
||||
document.addEventListener('volumedownbutton', onVolumeDownKeyDown, false);
|
||||
|
||||
events.trigger(this, 'connect');
|
||||
this.sendMessage({
|
||||
|
@ -262,7 +262,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
* Callback function for launch error
|
||||
*/
|
||||
CastPlayer.prototype.onLaunchError = function () {
|
||||
console.log("chromecast launch error");
|
||||
console.debug('chromecast launch error');
|
||||
this.deviceState = DEVICE_STATE.ERROR;
|
||||
sendConnectionResult(false);
|
||||
};
|
||||
|
@ -280,12 +280,12 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
* Callback function for stop app success
|
||||
*/
|
||||
CastPlayer.prototype.onStopAppSuccess = function (message) {
|
||||
console.log(message);
|
||||
console.debug(message);
|
||||
|
||||
this.deviceState = DEVICE_STATE.IDLE;
|
||||
this.castPlayerState = PLAYER_STATE.IDLE;
|
||||
document.removeEventListener("volumeupbutton", onVolumeUpKeyDown, false);
|
||||
document.removeEventListener("volumedownbutton", onVolumeDownKeyDown, false);
|
||||
document.removeEventListener('volumeupbutton', onVolumeUpKeyDown, false);
|
||||
document.removeEventListener('volumedownbutton', onVolumeDownKeyDown, false);
|
||||
|
||||
this.currentMediaSession = null;
|
||||
};
|
||||
|
@ -296,7 +296,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
*/
|
||||
CastPlayer.prototype.loadMedia = function (options, command) {
|
||||
if (!this.session) {
|
||||
console.log("no session");
|
||||
console.debug('no session');
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
|
@ -377,7 +377,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
};
|
||||
|
||||
CastPlayer.prototype.onPlayCommandSuccess = function () {
|
||||
//console.log('Message was sent to receiver ok.');
|
||||
console.debug('Message was sent to receiver ok.');
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -386,7 +386,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
*/
|
||||
CastPlayer.prototype.onMediaDiscovered = function (how, mediaSession) {
|
||||
|
||||
//console.log("chromecast new media session ID:" + mediaSession.mediaSessionId + ' (' + how + ')');
|
||||
console.debug('chromecast new media session ID:' + mediaSession.mediaSessionId + ' (' + how + ')');
|
||||
this.currentMediaSession = mediaSession;
|
||||
|
||||
if (how === 'loadMedia') {
|
||||
|
@ -405,7 +405,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
* @param {!Boolean} e true/false
|
||||
*/
|
||||
CastPlayer.prototype.onMediaStatusUpdate = function (e) {
|
||||
//console.log("chromecast updating media: " + e);
|
||||
console.debug('chromecast updating media: ' + e);
|
||||
if (e === false) {
|
||||
this.castPlayerState = PLAYER_STATE.IDLE;
|
||||
}
|
||||
|
@ -417,7 +417,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
*/
|
||||
CastPlayer.prototype.setReceiverVolume = function (mute, vol) {
|
||||
if (!this.currentMediaSession) {
|
||||
//console.log('this.currentMediaSession is null');
|
||||
console.debug('this.currentMediaSession is null');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -443,7 +443,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
* Callback function for media command success
|
||||
*/
|
||||
CastPlayer.prototype.mediaCommandSuccessCallback = function (info, e) {
|
||||
//console.log(info);
|
||||
console.debug(info);
|
||||
};
|
||||
|
||||
function normalizeImages(state) {
|
||||
|
@ -482,7 +482,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
} else {
|
||||
|
||||
query.Limit = query.Limit || 100;
|
||||
query.ExcludeLocationTypes = "Virtual";
|
||||
query.ExcludeLocationTypes = 'Virtual';
|
||||
query.EnableTotalRecordCount = false;
|
||||
|
||||
return apiClient.getItems(userId, query);
|
||||
|
@ -493,7 +493,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
|
||||
events.on(instance._castPlayer, eventName, function (e, data) {
|
||||
|
||||
//console.log('cc: ' + eventName);
|
||||
console.debug('cc: ' + eventName);
|
||||
var state = instance.getPlayerStateInternal(data);
|
||||
|
||||
events.trigger(instance, eventName, [state]);
|
||||
|
@ -506,13 +506,13 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
instance._castPlayer = new CastPlayer();
|
||||
|
||||
// To allow the native android app to override
|
||||
document.dispatchEvent(new CustomEvent("chromecastloaded", {
|
||||
document.dispatchEvent(new CustomEvent('chromecastloaded', {
|
||||
detail: {
|
||||
player: instance
|
||||
}
|
||||
}));
|
||||
|
||||
events.on(instance._castPlayer, "connect", function (e) {
|
||||
events.on(instance._castPlayer, 'connect', function (e) {
|
||||
|
||||
if (currentResolve) {
|
||||
sendConnectionResult(true);
|
||||
|
@ -520,27 +520,27 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
playbackManager.setActivePlayer(PlayerName, instance.getCurrentTargetInfo());
|
||||
}
|
||||
|
||||
console.log('cc: connect');
|
||||
console.debug('cc: connect');
|
||||
// Reset this so that statechange will fire
|
||||
instance.lastPlayerData = null;
|
||||
});
|
||||
|
||||
events.on(instance._castPlayer, "playbackstart", function (e, data) {
|
||||
events.on(instance._castPlayer, 'playbackstart', function (e, data) {
|
||||
|
||||
console.log('cc: playbackstart');
|
||||
console.debug('cc: playbackstart');
|
||||
|
||||
instance._castPlayer.initializeCastPlayer();
|
||||
|
||||
var state = instance.getPlayerStateInternal(data);
|
||||
events.trigger(instance, "playbackstart", [state]);
|
||||
events.trigger(instance, 'playbackstart', [state]);
|
||||
});
|
||||
|
||||
events.on(instance._castPlayer, "playbackstop", function (e, data) {
|
||||
events.on(instance._castPlayer, 'playbackstop', function (e, data) {
|
||||
|
||||
console.log('cc: playbackstop');
|
||||
console.debug('cc: playbackstop');
|
||||
var state = instance.getPlayerStateInternal(data);
|
||||
|
||||
events.trigger(instance, "playbackstop", [state]);
|
||||
events.trigger(instance, 'playbackstop', [state]);
|
||||
|
||||
var state = instance.lastPlayerData.PlayState || {};
|
||||
var volume = state.VolumeLevel || 0.5;
|
||||
|
@ -553,12 +553,12 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
instance.lastPlayerData.PlayState.IsMuted = mute;
|
||||
});
|
||||
|
||||
events.on(instance._castPlayer, "playbackprogress", function (e, data) {
|
||||
events.on(instance._castPlayer, 'playbackprogress', function (e, data) {
|
||||
|
||||
//console.log('cc: positionchange');
|
||||
console.debug('cc: positionchange');
|
||||
var state = instance.getPlayerStateInternal(data);
|
||||
|
||||
events.trigger(instance, "timeupdate", [state]);
|
||||
events.trigger(instance, 'timeupdate', [state]);
|
||||
});
|
||||
|
||||
bindEventForRelay(instance, 'timeupdate');
|
||||
|
@ -567,12 +567,12 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
bindEventForRelay(instance, 'volumechange');
|
||||
bindEventForRelay(instance, 'repeatmodechange');
|
||||
|
||||
events.on(instance._castPlayer, "playstatechange", function (e, data) {
|
||||
events.on(instance._castPlayer, 'playstatechange', function (e, data) {
|
||||
|
||||
//console.log('cc: playstatechange');
|
||||
console.debug('cc: playstatechange');
|
||||
var state = instance.getPlayerStateInternal(data);
|
||||
|
||||
events.trigger(instance, "pause", [state]);
|
||||
events.trigger(instance, 'pause', [state]);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -630,24 +630,24 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
name: PlayerName,
|
||||
id: PlayerName,
|
||||
playerName: PlayerName,
|
||||
playableMediaTypes: ["Audio", "Video"],
|
||||
playableMediaTypes: ['Audio', 'Video'],
|
||||
isLocalPlayer: false,
|
||||
appName: PlayerName,
|
||||
deviceName: appName,
|
||||
supportedCommands: [
|
||||
"VolumeUp",
|
||||
"VolumeDown",
|
||||
"Mute",
|
||||
"Unmute",
|
||||
"ToggleMute",
|
||||
"SetVolume",
|
||||
"SetAudioStreamIndex",
|
||||
"SetSubtitleStreamIndex",
|
||||
"DisplayContent",
|
||||
"SetRepeatMode",
|
||||
"EndSession",
|
||||
"PlayMediaSource",
|
||||
"PlayTrailers"
|
||||
'VolumeUp',
|
||||
'VolumeDown',
|
||||
'Mute',
|
||||
'Unmute',
|
||||
'ToggleMute',
|
||||
'SetVolume',
|
||||
'SetAudioStreamIndex',
|
||||
'SetSubtitleStreamIndex',
|
||||
'DisplayContent',
|
||||
'SetRepeatMode',
|
||||
'EndSession',
|
||||
'PlayMediaSource',
|
||||
'PlayTrailers'
|
||||
]
|
||||
};
|
||||
};
|
||||
|
@ -664,10 +664,10 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
|
||||
normalizeImages(data);
|
||||
|
||||
//console.log(JSON.stringify(data));
|
||||
console.debug(JSON.stringify(data));
|
||||
|
||||
if (triggerStateChange) {
|
||||
events.trigger(this, "statechange", [data]);
|
||||
events.trigger(this, 'statechange', [data]);
|
||||
}
|
||||
|
||||
return data;
|
||||
|
@ -686,6 +686,13 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
|||
});
|
||||
}
|
||||
|
||||
if (options.items.length > 1 && options && options.ids) {
|
||||
// Use the original request id array for sorting the result in the proper order
|
||||
options.items.sort(function (a, b) {
|
||||
return options.ids.indexOf(a.Id) - options.ids.indexOf(b.Id);
|
||||
});
|
||||
}
|
||||
|
||||
return this._castPlayer.loadMedia(options, command);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,25 +1,12 @@
|
|||
define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) {
|
||||
define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (dom, dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) {
|
||||
'use strict';
|
||||
|
||||
var currentServerId;
|
||||
|
||||
function parentWithClass(elem, className) {
|
||||
|
||||
while (!elem.classList || !elem.classList.contains(className)) {
|
||||
elem = elem.parentNode;
|
||||
|
||||
if (!elem) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
loading.show();
|
||||
|
||||
var panel = parentWithClass(this, 'dialog');
|
||||
var panel = dom.parentWithClass(this, 'dialog');
|
||||
|
||||
var collectionId = panel.querySelector('#selectCollectionToAddTo').value;
|
||||
|
||||
|
@ -37,7 +24,7 @@ define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManage
|
|||
|
||||
function createCollection(apiClient, dlg) {
|
||||
|
||||
var url = apiClient.getUrl("Collections", {
|
||||
var url = apiClient.getUrl('Collections', {
|
||||
|
||||
Name: dlg.querySelector('#txtNewCollectionName').value,
|
||||
IsLocked: !dlg.querySelector('#chkEnableInternetMetadata').checked,
|
||||
|
@ -45,9 +32,9 @@ define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManage
|
|||
});
|
||||
|
||||
apiClient.ajax({
|
||||
type: "POST",
|
||||
type: 'POST',
|
||||
url: url,
|
||||
dataType: "json"
|
||||
dataType: 'json'
|
||||
|
||||
}).then(function (result) {
|
||||
|
||||
|
@ -69,13 +56,13 @@ define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManage
|
|||
|
||||
function addToCollection(apiClient, dlg, id) {
|
||||
|
||||
var url = apiClient.getUrl("Collections/" + id + "/Items", {
|
||||
var url = apiClient.getUrl('Collections/' + id + '/Items', {
|
||||
|
||||
Ids: dlg.querySelector('.fldSelectedItemIds').value || ''
|
||||
});
|
||||
|
||||
apiClient.ajax({
|
||||
type: "POST",
|
||||
type: 'POST',
|
||||
url: url
|
||||
|
||||
}).then(function () {
|
||||
|
@ -106,8 +93,8 @@ define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManage
|
|||
var options = {
|
||||
|
||||
Recursive: true,
|
||||
IncludeItemTypes: "BoxSet",
|
||||
SortBy: "SortName",
|
||||
IncludeItemTypes: 'BoxSet',
|
||||
SortBy: 'SortName',
|
||||
EnableTotalRecordCount: false
|
||||
};
|
||||
|
||||
|
@ -243,13 +230,13 @@ define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManage
|
|||
var title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection');
|
||||
|
||||
html += '<div class="formDialogHeader">';
|
||||
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="md-icon">arrow_back</i></button>';
|
||||
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<h3 class="formDialogHeaderTitle">';
|
||||
html += title;
|
||||
html += '</h3>';
|
||||
|
||||
if (appHost.supports('externallinks')) {
|
||||
html += '<a is="emby-linkbutton" class="button-link btnHelp flex align-items-center" href="https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Collections" target="_blank" style="margin-left:auto;margin-right:.5em;padding:.25em;" title="' + globalize.translate('Help') + '"><i class="md-icon">info</i><span style="margin-left:.25em;">' + globalize.translate('Help') + '</span></a>';
|
||||
html += '<a is="emby-linkbutton" class="button-link btnHelp flex align-items-center" href="https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Collections" target="_blank" style="margin-left:auto;margin-right:.5em;padding:.25em;" title="' + globalize.translate('Help') + '"><span class="material-icons info"></span><span style="margin-left:.25em;">' + globalize.translate('Help') + '</span></a>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
|
|
|
@ -1,40 +1,65 @@
|
|||
define(['dialog', 'globalize'], function (dialog, globalize) {
|
||||
define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) {
|
||||
'use strict';
|
||||
|
||||
return function (text, title) {
|
||||
function replaceAll(str, find, replace) {
|
||||
return str.split(find).join(replace);
|
||||
}
|
||||
|
||||
var options;
|
||||
if (typeof text === 'string') {
|
||||
options = {
|
||||
title: title,
|
||||
text: text
|
||||
};
|
||||
} else {
|
||||
options = text;
|
||||
}
|
||||
|
||||
var items = [];
|
||||
|
||||
items.push({
|
||||
name: options.cancelText || globalize.translate('ButtonCancel'),
|
||||
id: 'cancel',
|
||||
type: 'cancel'
|
||||
});
|
||||
|
||||
items.push({
|
||||
name: options.confirmText || globalize.translate('ButtonOk'),
|
||||
id: 'ok',
|
||||
type: options.primary === 'delete' ? 'delete' : 'submit'
|
||||
});
|
||||
|
||||
options.buttons = items;
|
||||
|
||||
return dialog(options).then(function (result) {
|
||||
if (result === 'ok') {
|
||||
return Promise.resolve();
|
||||
if (browser.tv && window.confirm) {
|
||||
// Use the native confirm dialog
|
||||
return function (options) {
|
||||
if (typeof options === 'string') {
|
||||
options = {
|
||||
title: '',
|
||||
text: options
|
||||
};
|
||||
}
|
||||
|
||||
return Promise.reject();
|
||||
});
|
||||
};
|
||||
var text = replaceAll(options.text || '', '<br/>', '\n');
|
||||
var result = confirm(text);
|
||||
|
||||
if (result) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return Promise.reject();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// Use our own dialog
|
||||
return function (text, title) {
|
||||
var options;
|
||||
if (typeof text === 'string') {
|
||||
options = {
|
||||
title: title,
|
||||
text: text
|
||||
};
|
||||
} else {
|
||||
options = text;
|
||||
}
|
||||
|
||||
var items = [];
|
||||
|
||||
items.push({
|
||||
name: options.cancelText || globalize.translate('ButtonCancel'),
|
||||
id: 'cancel',
|
||||
type: 'cancel'
|
||||
});
|
||||
|
||||
items.push({
|
||||
name: options.confirmText || globalize.translate('ButtonOk'),
|
||||
id: 'ok',
|
||||
type: options.primary === 'delete' ? 'delete' : 'submit'
|
||||
});
|
||||
|
||||
options.buttons = items;
|
||||
|
||||
return dialog(options).then(function (result) {
|
||||
if (result === 'ok') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return Promise.reject();
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
define([], function () {
|
||||
'use strict';
|
||||
|
||||
function replaceAll(str, find, replace) {
|
||||
|
||||
return str.split(find).join(replace);
|
||||
}
|
||||
|
||||
return function (options) {
|
||||
|
||||
if (typeof options === 'string') {
|
||||
options = {
|
||||
title: '',
|
||||
text: options
|
||||
};
|
||||
}
|
||||
|
||||
var text = replaceAll(options.text || '', '<br/>', '\n');
|
||||
var result = confirm(text);
|
||||
|
||||
if (result) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return Promise.reject();
|
||||
}
|
||||
};
|
||||
});
|
|
@ -12,4 +12,4 @@
|
|||
</div>
|
||||
|
||||
<div class="formDialogFooter formDialogFooter-clear formDialogFooter-flex" style="padding-bottom: 1.5em;">
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -32,7 +32,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
|||
try {
|
||||
parentNode.removeChild(elem);
|
||||
} catch (err) {
|
||||
console.log('Error removing dialog element: ' + err);
|
||||
console.error('error removing dialog element: ' + err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
|||
animateDialogOpen(dlg);
|
||||
|
||||
if (isHistoryEnabled(dlg)) {
|
||||
appRouter.pushState({ dialogId: hash }, "Dialog", '#' + hash);
|
||||
appRouter.pushState({ dialogId: hash }, 'Dialog', '#' + hash);
|
||||
|
||||
window.addEventListener('popstate', onHashChange);
|
||||
} else {
|
||||
|
@ -169,6 +169,15 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
|||
}, {
|
||||
passive: true
|
||||
});
|
||||
|
||||
dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', function (e) {
|
||||
if (e.target === dlg.dialogContainer) {
|
||||
// Close the application dialog menu
|
||||
close(dlg);
|
||||
// Prevent the default browser context menu from appearing
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isHistoryEnabled(dlg) {
|
||||
|
@ -242,9 +251,15 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
|||
|
||||
var onAnimationFinish = function () {
|
||||
focusManager.pushScope(dlg);
|
||||
|
||||
if (dlg.getAttribute('data-autofocus') === 'true') {
|
||||
focusManager.autoFocus(dlg);
|
||||
}
|
||||
|
||||
if (document.activeElement && !dlg.contains(document.activeElement)) {
|
||||
// Blur foreign element to prevent triggering of an action from the previous scope
|
||||
document.activeElement.blur();
|
||||
}
|
||||
};
|
||||
|
||||
if (enableAnimation()) {
|
||||
|
@ -481,4 +496,4 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
|||
globalOnOpenCallback = val;
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
|
||||
.dialog {
|
||||
margin: 0;
|
||||
border-radius: .2em;
|
||||
border-radius: 0.2em;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
will-change: transform, opacity;
|
||||
|
||||
/* Strict does not work well with actionsheet */
|
||||
contain: style paint;
|
||||
box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.4);
|
||||
|
@ -50,13 +52,13 @@
|
|||
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: scale(.5);
|
||||
transform: scale(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scaleup {
|
||||
from {
|
||||
transform: scale(.5);
|
||||
transform: scale(0.5);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
@ -77,7 +79,6 @@
|
|||
}
|
||||
|
||||
@keyframes fadeout {
|
||||
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
@ -100,7 +101,6 @@
|
|||
}
|
||||
|
||||
@keyframes slidedown {
|
||||
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
|
@ -113,8 +113,8 @@
|
|||
}
|
||||
|
||||
@media all and (max-width: 80em), all and (max-height: 45em) {
|
||||
|
||||
.dialog-fixedSize, .dialog-fullscreen-lowres {
|
||||
.dialog-fixedSize,
|
||||
.dialog-fullscreen-lowres {
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
bottom: 0 !important;
|
||||
|
@ -126,7 +126,6 @@
|
|||
}
|
||||
|
||||
@media all and (min-width: 80em) and (min-height: 45em) {
|
||||
|
||||
.dialog-medium {
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
|
@ -168,5 +167,5 @@
|
|||
}
|
||||
|
||||
.dialogBackdropOpened {
|
||||
opacity: .5;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ulDirectoryPickerList a {
|
||||
padding-top: .4em;
|
||||
padding-bottom: .4em
|
||||
padding-top: 0.4em;
|
||||
padding-bottom: 0.4em;
|
||||
}
|
||||
|
||||
.lblDirectoryPickerPath {
|
||||
white-space: nowrap
|
||||
}
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom) {
|
||||
define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-input', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom, globalize) {
|
||||
'use strict';
|
||||
|
||||
function getSystemInfo() {
|
||||
|
@ -7,24 +7,24 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
|||
systemInfo = info;
|
||||
return info;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function onDialogClosed() {
|
||||
loading.hide()
|
||||
loading.hide();
|
||||
}
|
||||
|
||||
function refreshDirectoryBrowser(page, path, fileOptions, updatePathOnError) {
|
||||
if (path && typeof path !== 'string') {
|
||||
throw new Error("invalid path");
|
||||
throw new Error('invalid path');
|
||||
}
|
||||
|
||||
loading.show();
|
||||
|
||||
var promises = [];
|
||||
|
||||
if ("Network" === path) {
|
||||
promises.push(ApiClient.getNetworkDevices())
|
||||
if ('Network' === path) {
|
||||
promises.push(ApiClient.getNetworkDevices());
|
||||
} else {
|
||||
if (path) {
|
||||
promises.push(ApiClient.getDirectoryContents(path, fileOptions));
|
||||
|
@ -37,31 +37,31 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
|||
Promise.all(promises).then(
|
||||
function(responses) {
|
||||
var folders = responses[0];
|
||||
var parentPath = responses[1] || "";
|
||||
var html = "";
|
||||
var parentPath = responses[1] || '';
|
||||
var html = '';
|
||||
|
||||
page.querySelector(".results").scrollTop = 0;
|
||||
page.querySelector("#txtDirectoryPickerPath").value = path || "";
|
||||
page.querySelector('.results').scrollTop = 0;
|
||||
page.querySelector('#txtDirectoryPickerPath').value = path || '';
|
||||
|
||||
if (path) {
|
||||
html += getItem("lnkPath lnkDirectory", "", parentPath, "...");
|
||||
html += getItem('lnkPath lnkDirectory', '', parentPath, '...');
|
||||
}
|
||||
for (var i = 0, length = folders.length; i < length; i++) {
|
||||
var folder = folders[i];
|
||||
var cssClass = "File" === folder.Type ? "lnkPath lnkFile" : "lnkPath lnkDirectory";
|
||||
var cssClass = 'File' === folder.Type ? 'lnkPath lnkFile' : 'lnkPath lnkDirectory';
|
||||
html += getItem(cssClass, folder.Type, folder.Path, folder.Name);
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
html += getItem("lnkPath lnkDirectory", "", "Network", Globalize.translate("ButtonNetwork"));
|
||||
html += getItem('lnkPath lnkDirectory', '', 'Network', globalize.translate('ButtonNetwork'));
|
||||
}
|
||||
|
||||
page.querySelector(".results").innerHTML = html;
|
||||
page.querySelector('.results').innerHTML = html;
|
||||
loading.hide();
|
||||
}, function() {
|
||||
if (updatePathOnError) {
|
||||
page.querySelector("#txtDirectoryPickerPath").value = "";
|
||||
page.querySelector(".results").innerHTML = "";
|
||||
page.querySelector('#txtDirectoryPickerPath').value = '';
|
||||
page.querySelector('.results').innerHTML = '';
|
||||
loading.hide();
|
||||
}
|
||||
}
|
||||
|
@ -69,74 +69,74 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
|||
}
|
||||
|
||||
function getItem(cssClass, type, path, name) {
|
||||
var html = "";
|
||||
var html = '';
|
||||
html += '<div class="listItem listItem-border ' + cssClass + '" data-type="' + type + '" data-path="' + path + '">';
|
||||
html += '<div class="listItemBody" style="padding-left:0;padding-top:.5em;padding-bottom:.5em;">';
|
||||
html += '<div class="listItemBodyText">';
|
||||
html += name;
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += '<i class="md-icon" style="font-size:inherit;">arrow_forward</i>';
|
||||
html += "</div>";
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
html += '<span class="material-icons arrow_forward" style="font-size:inherit;"></span>';
|
||||
html += '</div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function getEditorHtml(options, systemInfo) {
|
||||
var html = "";
|
||||
var html = '';
|
||||
html += '<div class="formDialogContent scrollY">';
|
||||
html += '<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;">';
|
||||
if (!options.pathReadOnly) {
|
||||
var instruction = options.instruction ? options.instruction + "<br/><br/>" : "";
|
||||
var instruction = options.instruction ? options.instruction + '<br/><br/>' : '';
|
||||
html += '<div class="infoBanner" style="margin-bottom:1.5em;">';
|
||||
html += instruction;
|
||||
html += Globalize.translate("MessageDirectoryPickerInstruction").replace("{0}", "<b>\\\\server</b>").replace("{1}", "<b>\\\\192.168.1.101</b>");
|
||||
if ("bsd" === systemInfo.OperatingSystem.toLowerCase()) {
|
||||
html += "<br/>";
|
||||
html += "<br/>";
|
||||
html += Globalize.translate("MessageDirectoryPickerBSDInstruction");
|
||||
html += "<br/>";
|
||||
} else if ("linux" === systemInfo.OperatingSystem.toLowerCase()) {
|
||||
html += "<br/>";
|
||||
html += "<br/>";
|
||||
html += Globalize.translate("MessageDirectoryPickerLinuxInstruction");
|
||||
html += "<br/>";
|
||||
html += globalize.translate('MessageDirectoryPickerInstruction', '<b>\\\\server</b>', '<b>\\\\192.168.1.101</b>');
|
||||
if ('bsd' === systemInfo.OperatingSystem.toLowerCase()) {
|
||||
html += '<br/>';
|
||||
html += '<br/>';
|
||||
html += globalize.translate('MessageDirectoryPickerBSDInstruction');
|
||||
html += '<br/>';
|
||||
} else if ('linux' === systemInfo.OperatingSystem.toLowerCase()) {
|
||||
html += '<br/>';
|
||||
html += '<br/>';
|
||||
html += globalize.translate('MessageDirectoryPickerLinuxInstruction');
|
||||
html += '<br/>';
|
||||
}
|
||||
html += "</div>"
|
||||
html += '</div>';
|
||||
}
|
||||
html += '<form style="margin:auto;">';
|
||||
html += '<div class="inputContainer" style="display: flex; align-items: center;">';
|
||||
html += '<div style="flex-grow:1;">';
|
||||
var labelKey;
|
||||
if (options.includeFiles !== true) {
|
||||
labelKey = "LabelFolder";
|
||||
labelKey = 'LabelFolder';
|
||||
} else {
|
||||
labelKey = "LabelPath";
|
||||
labelKey = 'LabelPath';
|
||||
}
|
||||
var readOnlyAttribute = options.pathReadOnly ? " readonly" : "";
|
||||
html += '<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ' + readOnlyAttribute + ' label="' + Globalize.translate(labelKey) + '"/>';
|
||||
html += "</div>";
|
||||
var readOnlyAttribute = options.pathReadOnly ? ' readonly' : '';
|
||||
html += '<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ' + readOnlyAttribute + ' label="' + globalize.translate(labelKey) + '"/>';
|
||||
html += '</div>';
|
||||
if (!readOnlyAttribute) {
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="' + Globalize.translate("ButtonRefresh") + '"><i class="md-icon">search</i></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="' + globalize.translate('ButtonRefresh') + '"><span class="material-icons search"></span></button>';
|
||||
}
|
||||
html += "</div>";
|
||||
html += '</div>';
|
||||
if (!readOnlyAttribute) {
|
||||
html += '<div class="results paperList" style="max-height: 200px; overflow-y: auto;"></div>';
|
||||
}
|
||||
if (options.enableNetworkSharePath) {
|
||||
html += '<div class="inputContainer" style="margin-top:2em;">';
|
||||
html += '<input is="emby-input" id="txtNetworkPath" type="text" label="' + Globalize.translate("LabelOptionalNetworkPath") + '"/>';
|
||||
html += '<input is="emby-input" id="txtNetworkPath" type="text" label="' + globalize.translate('LabelOptionalNetworkPath') + '"/>';
|
||||
html += '<div class="fieldDescription">';
|
||||
html += Globalize.translate("LabelOptionalNetworkPathHelp");
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += globalize.translate('LabelOptionalNetworkPathHelp');
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
}
|
||||
html += '<div class="formDialogFooter">';
|
||||
html += '<button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem">' + Globalize.translate("ButtonOk") + "</button>";
|
||||
html += "</div>";
|
||||
html += "</form>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += '<button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem">' + globalize.translate('ButtonOk') + '</button>';
|
||||
html += '</div>';
|
||||
html += '</form>';
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
|
||||
return html;
|
||||
}
|
||||
|
@ -144,75 +144,74 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
|||
function alertText(text) {
|
||||
alertTextWithOptions({
|
||||
text: text
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function alertTextWithOptions(options) {
|
||||
require(["alert"], function(alert) {
|
||||
alert(options)
|
||||
})
|
||||
require(['alert'], function(alert) {
|
||||
alert(options);
|
||||
});
|
||||
}
|
||||
|
||||
function validatePath(path, validateWriteable, apiClient) {
|
||||
return apiClient.ajax({
|
||||
type: "POST",
|
||||
url: apiClient.getUrl("Environment/ValidatePath"),
|
||||
type: 'POST',
|
||||
url: apiClient.getUrl('Environment/ValidatePath'),
|
||||
data: {
|
||||
ValidateWriteable: validateWriteable,
|
||||
Path: path
|
||||
}
|
||||
}).catch(function(response) {
|
||||
if (response) {
|
||||
// TODO All alerts (across the project), should use Globalize.translate()
|
||||
if (response.status === 404) {
|
||||
alertText("The path could not be found. Please ensure the path is valid and try again.");
|
||||
alertText(globalize.translate('PathNotFound'));
|
||||
return Promise.reject();
|
||||
}
|
||||
if (response.status === 500) {
|
||||
if (validateWriteable) {
|
||||
alertText("Jellyfin Server requires write access to this folder. Please ensure write access and try again.");
|
||||
alertText(globalize.translate('WriteAccessRequired'));
|
||||
} else {
|
||||
alertText("The path could not be found. Please ensure the path is valid and try again.")
|
||||
alertText(globalize.translate('PathNotFound'));
|
||||
}
|
||||
return Promise.reject()
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
return Promise.resolve()
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
function initEditor(content, options, fileOptions) {
|
||||
content.addEventListener("click", function(e) {
|
||||
var lnkPath = dom.parentWithClass(e.target, "lnkPath");
|
||||
content.addEventListener('click', function(e) {
|
||||
var lnkPath = dom.parentWithClass(e.target, 'lnkPath');
|
||||
if (lnkPath) {
|
||||
var path = lnkPath.getAttribute("data-path");
|
||||
if (lnkPath.classList.contains("lnkFile")) {
|
||||
content.querySelector("#txtDirectoryPickerPath").value = path;
|
||||
var path = lnkPath.getAttribute('data-path');
|
||||
if (lnkPath.classList.contains('lnkFile')) {
|
||||
content.querySelector('#txtDirectoryPickerPath').value = path;
|
||||
} else {
|
||||
refreshDirectoryBrowser(content, path, fileOptions, true)
|
||||
refreshDirectoryBrowser(content, path, fileOptions, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
content.addEventListener("click", function(e) {
|
||||
if (dom.parentWithClass(e.target, "btnRefreshDirectories")) {
|
||||
var path = content.querySelector("#txtDirectoryPickerPath").value;
|
||||
content.addEventListener('click', function(e) {
|
||||
if (dom.parentWithClass(e.target, 'btnRefreshDirectories')) {
|
||||
var path = content.querySelector('#txtDirectoryPickerPath').value;
|
||||
refreshDirectoryBrowser(content, path, fileOptions);
|
||||
}
|
||||
});
|
||||
|
||||
content.addEventListener("change", function(e) {
|
||||
var txtDirectoryPickerPath = dom.parentWithTag(e.target, "INPUT");
|
||||
if (txtDirectoryPickerPath && "txtDirectoryPickerPath" === txtDirectoryPickerPath.id) {
|
||||
content.addEventListener('change', function(e) {
|
||||
var txtDirectoryPickerPath = dom.parentWithTag(e.target, 'INPUT');
|
||||
if (txtDirectoryPickerPath && 'txtDirectoryPickerPath' === txtDirectoryPickerPath.id) {
|
||||
refreshDirectoryBrowser(content, txtDirectoryPickerPath.value, fileOptions);
|
||||
}
|
||||
});
|
||||
|
||||
content.querySelector("form").addEventListener("submit", function(e) {
|
||||
content.querySelector('form').addEventListener('submit', function(e) {
|
||||
if (options.callback) {
|
||||
var networkSharePath = this.querySelector("#txtNetworkPath");
|
||||
var networkSharePath = this.querySelector('#txtNetworkPath');
|
||||
networkSharePath = networkSharePath ? networkSharePath.value : null;
|
||||
var path = this.querySelector("#txtDirectoryPickerPath").value;
|
||||
var path = this.querySelector('#txtDirectoryPickerPath').value;
|
||||
validatePath(path, options.validateWriteable, ApiClient).then(options.callback(path, networkSharePath));
|
||||
}
|
||||
e.preventDefault();
|
||||
|
@ -225,11 +224,11 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
|||
if (options.path) {
|
||||
return Promise.resolve(options.path);
|
||||
} else {
|
||||
return ApiClient.getJSON(ApiClient.getUrl("Environment/DefaultDirectoryBrowser")).then(
|
||||
return ApiClient.getJSON(ApiClient.getUrl('Environment/DefaultDirectoryBrowser')).then(
|
||||
function(result) {
|
||||
return result.Path || "";
|
||||
return result.Path || '';
|
||||
}, function() {
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -254,35 +253,35 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
|||
var systemInfo = responses[0];
|
||||
var initialPath = responses[1];
|
||||
var dlg = dialogHelper.createDialog({
|
||||
size: "medium-tall",
|
||||
size: 'medium-tall',
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
});
|
||||
dlg.classList.add("ui-body-a");
|
||||
dlg.classList.add("background-theme-a");
|
||||
dlg.classList.add("directoryPicker");
|
||||
dlg.classList.add("formDialog");
|
||||
dlg.classList.add('ui-body-a');
|
||||
dlg.classList.add('background-theme-a');
|
||||
dlg.classList.add('directoryPicker');
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
var html = "";
|
||||
var html = '';
|
||||
html += '<div class="formDialogHeader">';
|
||||
html += '<button is="paper-icon-button-light" class="btnCloseDialog autoSize" tabindex="-1"><i class="md-icon">arrow_back</i></button>';
|
||||
html += '<button is="paper-icon-button-light" class="btnCloseDialog autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<h3 class="formDialogHeaderTitle">';
|
||||
html += options.header || Globalize.translate("HeaderSelectPath");
|
||||
html += "</h3>";
|
||||
html += "</div>";
|
||||
html += options.header || globalize.translate('HeaderSelectPath');
|
||||
html += '</h3>';
|
||||
html += '</div>';
|
||||
html += getEditorHtml(options, systemInfo);
|
||||
dlg.innerHTML = html;
|
||||
initEditor(dlg, options, fileOptions);
|
||||
dlg.addEventListener("close", onDialogClosed);
|
||||
dlg.addEventListener('close', onDialogClosed);
|
||||
dialogHelper.open(dlg);
|
||||
dlg.querySelector(".btnCloseDialog").addEventListener("click", function() {
|
||||
dialogHelper.close(dlg)
|
||||
dlg.querySelector('.btnCloseDialog').addEventListener('click', function() {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
currentDialog = dlg;
|
||||
dlg.querySelector("#txtDirectoryPickerPath").value = initialPath;
|
||||
var txtNetworkPath = dlg.querySelector("#txtNetworkPath");
|
||||
dlg.querySelector('#txtDirectoryPickerPath').value = initialPath;
|
||||
var txtNetworkPath = dlg.querySelector('#txtNetworkPath');
|
||||
if (txtNetworkPath) {
|
||||
txtNetworkPath.value = options.networkSharePath || "";
|
||||
txtNetworkPath.value = options.networkSharePath || '';
|
||||
}
|
||||
if (!options.pathReadOnly) {
|
||||
refreshDirectoryBrowser(dlg, initialPath, fileOptions, true);
|
||||
|
@ -294,9 +293,9 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
|||
if (currentDialog) {
|
||||
dialogHelper.close(currentDialog);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var systemInfo;
|
||||
return directoryBrowser
|
||||
return directoryBrowser;
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', 'apphost', 'focusManager', 'datetime', 'globalize', 'loading', 'connectionManager', 'skinManager', 'dom', 'events', 'emby-select', 'emby-checkbox', 'emby-button'], function (require, browser, layoutManager, appSettings, pluginManager, appHost, focusManager, datetime, globalize, loading, connectionManager, skinManager, dom, events) {
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
function fillThemes(select, isDashboard) {
|
||||
select.innerHTML = skinManager.getThemes().map(function (t) {
|
||||
|
@ -180,11 +180,14 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
|||
|
||||
context.querySelector('#chkThemeSong').checked = userSettings.enableThemeSongs();
|
||||
context.querySelector('#chkThemeVideo').checked = userSettings.enableThemeVideos();
|
||||
context.querySelector('#chkFadein').checked = userSettings.enableFastFadein();
|
||||
context.querySelector('#chkBackdrops').checked = userSettings.enableBackdrops();
|
||||
|
||||
context.querySelector('#selectLanguage').value = userSettings.language() || '';
|
||||
context.querySelector('.selectDateTimeLocale').value = userSettings.dateTimeLocale() || '';
|
||||
|
||||
context.querySelector('#txtLibraryPageSize').value = userSettings.libraryPageSize();
|
||||
|
||||
selectDashboardTheme.value = userSettings.dashboardTheme() || '';
|
||||
selectTheme.value = userSettings.theme() || '';
|
||||
|
||||
|
@ -214,8 +217,11 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
|||
userSettingsInstance.soundEffects(context.querySelector('.selectSoundEffects').value);
|
||||
userSettingsInstance.screensaver(context.querySelector('.selectScreensaver').value);
|
||||
|
||||
userSettingsInstance.libraryPageSize(context.querySelector('#txtLibraryPageSize').value);
|
||||
|
||||
userSettingsInstance.skin(context.querySelector('.selectSkin').value);
|
||||
|
||||
userSettingsInstance.enableFastFadein(context.querySelector('#chkFadein').checked);
|
||||
userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked);
|
||||
|
||||
if (user.Id === apiClient.getCurrentUserId()) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<h2 class="sectionTitle">
|
||||
${Display}
|
||||
</h2>
|
||||
|
||||
<div class="selectContainer languageSection hide">
|
||||
<select id="selectLanguage" is="emby-select" label="${LabelDisplayLanguage}">
|
||||
<option value="">${Auto}</option>
|
||||
|
@ -55,14 +56,14 @@
|
|||
<div class="fieldDescription">
|
||||
<div>${LabelDisplayLanguageHelp}</div>
|
||||
<div class="learnHowToContributeContainer hide" style="margin-top: .25em;">
|
||||
<a is="emby-linkbutton" class="button-link" href="https://github.com/jellyfin/jellyfin" target="_blank">${LearnHowYouCanContribute}</a>
|
||||
<a is="emby-linkbutton" rel="noopener noreferrer" class="button-link" href="https://github.com/jellyfin/jellyfin" target="_blank">${LearnHowYouCanContribute}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="selectContainer fldDateTimeLocale hide">
|
||||
<select is="emby-select" class="selectDateTimeLocale" label="${LabelDateTimeLocale}">
|
||||
<option value="">${AutoBasedOnLanguageSetting}</option>
|
||||
<option value="">${Auto}</option>
|
||||
<option value="ar">Arabic</option>
|
||||
<option value="be-BY">Belarusian (Belarus)</option>
|
||||
<option value="bg-BG">Bulgarian (Bulgaria)</option>
|
||||
|
@ -133,6 +134,7 @@
|
|||
<div class="selectContainer selectDashboardThemeContainer hide">
|
||||
<select id="selectDashboardTheme" is="emby-select" label="${LabelDashboardTheme}"></select>
|
||||
</div>
|
||||
|
||||
<div class="selectContainer hide selectScreensaverContainer">
|
||||
<select is="emby-select" class="selectScreensaver" label="${LabelScreensaver}"></select>
|
||||
</div>
|
||||
|
@ -141,6 +143,19 @@
|
|||
<select is="emby-select" class="selectSoundEffects" label="${LabelSoundEffects}"></select>
|
||||
</div>
|
||||
|
||||
<div class="inputContainer inputContainer-withDescription fldFadein">
|
||||
<input is="emby-input" type="number" id="txtLibraryPageSize" pattern="[0-9]*" required="required" min="0" max="1000" step="1" label="${LabelLibraryPageSize}" />
|
||||
<div class="fieldDescription">${LabelLibraryPageSizeHelp}</div>
|
||||
</div>
|
||||
|
||||
<div class="checkboxContainer checkboxContainer-withDescription fldFadein">
|
||||
<label>
|
||||
<input type="checkbox" is="emby-checkbox" id="chkFadein" />
|
||||
<span>${EnableFastImageFadeIn}</span>
|
||||
</label>
|
||||
<div class="fieldDescription checkboxFieldDescription">${EnableFastImageFadeInHelp}</div>
|
||||
</div>
|
||||
|
||||
<div class="checkboxContainer checkboxContainer-withDescription fldBackdrops hide">
|
||||
<label>
|
||||
<input type="checkbox" is="emby-checkbox" id="chkBackdrops" />
|
||||
|
@ -148,6 +163,7 @@
|
|||
</label>
|
||||
<div class="fieldDescription checkboxFieldDescription">${EnableBackdropsHelp}</div>
|
||||
</div>
|
||||
|
||||
<div class="checkboxContainer checkboxContainer-withDescription fldThemeSong hide">
|
||||
<label>
|
||||
<input type="checkbox" is="emby-checkbox" id="chkThemeSong" />
|
||||
|
@ -155,6 +171,7 @@
|
|||
</label>
|
||||
<div class="fieldDescription checkboxFieldDescription">${EnableThemeSongsHelp}</div>
|
||||
</div>
|
||||
|
||||
<div class="checkboxContainer checkboxContainer-withDescription fldThemeVideo hide">
|
||||
<label>
|
||||
<input type="checkbox" is="emby-checkbox" id="chkThemeVideo" />
|
||||
|
|
|
@ -1,181 +0,0 @@
|
|||
define([], function () {
|
||||
'use strict';
|
||||
|
||||
function parentWithAttribute(elem, name, value) {
|
||||
|
||||
while ((value ? elem.getAttribute(name) !== value : !elem.getAttribute(name))) {
|
||||
elem = elem.parentNode;
|
||||
|
||||
if (!elem || !elem.getAttribute) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
function parentWithTag(elem, tagNames) {
|
||||
|
||||
// accept both string and array passed in
|
||||
if (!Array.isArray(tagNames)) {
|
||||
tagNames = [tagNames];
|
||||
}
|
||||
|
||||
while (tagNames.indexOf(elem.tagName || '') === -1) {
|
||||
elem = elem.parentNode;
|
||||
|
||||
if (!elem) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
function containsAnyClass(classList, classNames) {
|
||||
|
||||
for (var i = 0, length = classNames.length; i < length; i++) {
|
||||
if (classList.contains(classNames[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function parentWithClass(elem, classNames) {
|
||||
|
||||
// accept both string and array passed in
|
||||
if (!Array.isArray(classNames)) {
|
||||
classNames = [classNames];
|
||||
}
|
||||
|
||||
while (!elem.classList || !containsAnyClass(elem.classList, classNames)) {
|
||||
elem = elem.parentNode;
|
||||
|
||||
if (!elem) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
var supportsCaptureOption = false;
|
||||
try {
|
||||
var opts = Object.defineProperty({}, 'capture', {
|
||||
get: function () {
|
||||
supportsCaptureOption = true;
|
||||
}
|
||||
});
|
||||
window.addEventListener("test", null, opts);
|
||||
} catch (e) {
|
||||
console.log('error checking capture support');
|
||||
}
|
||||
|
||||
function addEventListenerWithOptions(target, type, handler, options) {
|
||||
var optionsOrCapture = options;
|
||||
if (!supportsCaptureOption) {
|
||||
optionsOrCapture = options.capture;
|
||||
}
|
||||
target.addEventListener(type, handler, optionsOrCapture);
|
||||
}
|
||||
|
||||
function removeEventListenerWithOptions(target, type, handler, options) {
|
||||
var optionsOrCapture = options;
|
||||
if (!supportsCaptureOption) {
|
||||
optionsOrCapture = options.capture;
|
||||
}
|
||||
target.removeEventListener(type, handler, optionsOrCapture);
|
||||
}
|
||||
|
||||
var windowSize;
|
||||
var windowSizeEventsBound;
|
||||
function clearWindowSize() {
|
||||
windowSize = null;
|
||||
}
|
||||
|
||||
function getWindowSize() {
|
||||
if (!windowSize) {
|
||||
windowSize = {
|
||||
innerHeight: window.innerHeight,
|
||||
innerWidth: window.innerWidth
|
||||
};
|
||||
|
||||
if (!windowSizeEventsBound) {
|
||||
windowSizeEventsBound = true;
|
||||
addEventListenerWithOptions(window, "orientationchange", clearWindowSize, { passive: true });
|
||||
addEventListenerWithOptions(window, 'resize', clearWindowSize, { passive: true });
|
||||
}
|
||||
}
|
||||
|
||||
return windowSize;
|
||||
}
|
||||
|
||||
var _animationEvent;
|
||||
function whichAnimationEvent() {
|
||||
|
||||
if (_animationEvent) {
|
||||
return _animationEvent;
|
||||
}
|
||||
|
||||
var t;
|
||||
var el = document.createElement("div");
|
||||
var animations = {
|
||||
"animation": "animationend",
|
||||
"OAnimation": "oAnimationEnd",
|
||||
"MozAnimation": "animationend",
|
||||
"WebkitAnimation": "webkitAnimationEnd"
|
||||
};
|
||||
for (t in animations) {
|
||||
if (el.style[t] !== undefined) {
|
||||
_animationEvent = animations[t];
|
||||
return animations[t];
|
||||
}
|
||||
}
|
||||
|
||||
_animationEvent = 'animationend';
|
||||
return _animationEvent;
|
||||
}
|
||||
|
||||
function whichAnimationCancelEvent() {
|
||||
|
||||
return whichAnimationEvent().replace('animationend', 'animationcancel').replace('AnimationEnd', 'AnimationCancel');
|
||||
}
|
||||
|
||||
var _transitionEvent;
|
||||
function whichTransitionEvent() {
|
||||
if (_transitionEvent) {
|
||||
return _transitionEvent;
|
||||
}
|
||||
|
||||
var t;
|
||||
var el = document.createElement("div");
|
||||
var transitions = {
|
||||
"transition": "transitionend",
|
||||
"OTransition": "oTransitionEnd",
|
||||
"MozTransition": "transitionend",
|
||||
"WebkitTransition": "webkitTransitionEnd"
|
||||
};
|
||||
for (t in transitions) {
|
||||
if (el.style[t] !== undefined) {
|
||||
_transitionEvent = transitions[t];
|
||||
return transitions[t];
|
||||
}
|
||||
}
|
||||
|
||||
_transitionEvent = 'transitionend';
|
||||
return _transitionEvent;
|
||||
}
|
||||
|
||||
return {
|
||||
parentWithAttribute: parentWithAttribute,
|
||||
parentWithClass: parentWithClass,
|
||||
parentWithTag: parentWithTag,
|
||||
addEventListener: addEventListenerWithOptions,
|
||||
removeEventListener: removeEventListenerWithOptions,
|
||||
getWindowSize: getWindowSize,
|
||||
whichTransitionEvent: whichTransitionEvent,
|
||||
whichAnimationEvent: whichAnimationEvent,
|
||||
whichAnimationCancelEvent: whichAnimationCancelEvent
|
||||
};
|
||||
});
|
|
@ -1,41 +1,41 @@
|
|||
define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoader", "globalize", "layoutManager", "scrollStyles", "emby-itemscontainer"], function (loading, libraryBrowser, cardBuilder, dom, appHost, imageLoader, globalize, layoutManager) {
|
||||
"use strict";
|
||||
define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoader', 'globalize', 'layoutManager', 'scrollStyles', 'emby-itemscontainer'], function (loading, libraryBrowser, cardBuilder, dom, appHost, imageLoader, globalize, layoutManager) {
|
||||
'use strict';
|
||||
|
||||
function enableScrollX() {
|
||||
return !layoutManager.desktop;
|
||||
}
|
||||
|
||||
function getThumbShape() {
|
||||
return enableScrollX() ? "overflowBackdrop" : "backdrop";
|
||||
return enableScrollX() ? 'overflowBackdrop' : 'backdrop';
|
||||
}
|
||||
|
||||
function getPosterShape() {
|
||||
return enableScrollX() ? "overflowPortrait" : "portrait";
|
||||
return enableScrollX() ? 'overflowPortrait' : 'portrait';
|
||||
}
|
||||
|
||||
function getSquareShape() {
|
||||
return enableScrollX() ? "overflowSquare" : "square";
|
||||
return enableScrollX() ? 'overflowSquare' : 'square';
|
||||
}
|
||||
|
||||
function getSections() {
|
||||
return [{
|
||||
name: "HeaderFavoriteMovies",
|
||||
types: "Movie",
|
||||
id: "favoriteMovies",
|
||||
name: 'HeaderFavoriteMovies',
|
||||
types: 'Movie',
|
||||
id: 'favoriteMovies',
|
||||
shape: getPosterShape(),
|
||||
showTitle: false,
|
||||
overlayPlayButton: true
|
||||
}, {
|
||||
name: "HeaderFavoriteShows",
|
||||
types: "Series",
|
||||
id: "favoriteShows",
|
||||
name: 'HeaderFavoriteShows',
|
||||
types: 'Series',
|
||||
id: 'favoriteShows',
|
||||
shape: getPosterShape(),
|
||||
showTitle: false,
|
||||
overlayPlayButton: true
|
||||
}, {
|
||||
name: "HeaderFavoriteEpisodes",
|
||||
types: "Episode",
|
||||
id: "favoriteEpisode",
|
||||
name: 'HeaderFavoriteEpisodes',
|
||||
types: 'Episode',
|
||||
id: 'favoriteEpisode',
|
||||
shape: getThumbShape(),
|
||||
preferThumb: false,
|
||||
showTitle: true,
|
||||
|
@ -44,9 +44,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
overlayText: false,
|
||||
centerText: true
|
||||
}, {
|
||||
name: "HeaderFavoriteVideos",
|
||||
types: "Video,MusicVideo",
|
||||
id: "favoriteVideos",
|
||||
name: 'HeaderFavoriteVideos',
|
||||
types: 'Video,MusicVideo',
|
||||
id: 'favoriteVideos',
|
||||
shape: getThumbShape(),
|
||||
preferThumb: true,
|
||||
showTitle: true,
|
||||
|
@ -54,9 +54,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
overlayText: false,
|
||||
centerText: true
|
||||
}, {
|
||||
name: "HeaderFavoriteArtists",
|
||||
types: "MusicArtist",
|
||||
id: "favoriteArtists",
|
||||
name: 'HeaderFavoriteArtists',
|
||||
types: 'MusicArtist',
|
||||
id: 'favoriteArtists',
|
||||
shape: getSquareShape(),
|
||||
preferThumb: false,
|
||||
showTitle: true,
|
||||
|
@ -66,9 +66,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
overlayPlayButton: true,
|
||||
coverImage: true
|
||||
}, {
|
||||
name: "HeaderFavoriteAlbums",
|
||||
types: "MusicAlbum",
|
||||
id: "favoriteAlbums",
|
||||
name: 'HeaderFavoriteAlbums',
|
||||
types: 'MusicAlbum',
|
||||
id: 'favoriteAlbums',
|
||||
shape: getSquareShape(),
|
||||
preferThumb: false,
|
||||
showTitle: true,
|
||||
|
@ -78,9 +78,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
overlayPlayButton: true,
|
||||
coverImage: true
|
||||
}, {
|
||||
name: "HeaderFavoriteSongs",
|
||||
types: "Audio",
|
||||
id: "favoriteSongs",
|
||||
name: 'HeaderFavoriteSongs',
|
||||
types: 'Audio',
|
||||
id: 'favoriteSongs',
|
||||
shape: getSquareShape(),
|
||||
preferThumb: false,
|
||||
showTitle: true,
|
||||
|
@ -88,7 +88,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
showParentTitle: true,
|
||||
centerText: true,
|
||||
overlayMoreButton: true,
|
||||
action: "instantmix",
|
||||
action: 'instantmix',
|
||||
coverImage: true
|
||||
}];
|
||||
}
|
||||
|
@ -96,13 +96,13 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
function loadSection(elem, userId, topParentId, section, isSingleSection) {
|
||||
var screenWidth = dom.getWindowSize().innerWidth;
|
||||
var options = {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
Filters: "IsFavorite",
|
||||
SortBy: 'SortName',
|
||||
SortOrder: 'Ascending',
|
||||
Filters: 'IsFavorite',
|
||||
Recursive: true,
|
||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||
CollapseBoxSetItems: false,
|
||||
ExcludeLocationTypes: "Virtual",
|
||||
ExcludeLocationTypes: 'Virtual',
|
||||
EnableTotalRecordCount: false
|
||||
};
|
||||
|
||||
|
@ -120,7 +120,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
|
||||
var promise;
|
||||
|
||||
if ("MusicArtist" === section.types) {
|
||||
if ('MusicArtist' === section.types) {
|
||||
promise = ApiClient.getArtists(userId, options);
|
||||
} else {
|
||||
options.IncludeItemTypes = section.types;
|
||||
|
@ -128,25 +128,25 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
}
|
||||
|
||||
return promise.then(function (result) {
|
||||
var html = "";
|
||||
var html = '';
|
||||
|
||||
if (result.Items.length) {
|
||||
if (html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">', !layoutManager.tv && options.Limit && result.Items.length >= options.Limit) {
|
||||
html += '<a is="emby-linkbutton" href="' + ("list.html?serverId=" + ApiClient.serverId() + "&type=" + section.types + "&IsFavorite=true") + '" class="more button-flat button-flat-mini sectionTitleTextButton">';
|
||||
html += '<a is="emby-linkbutton" href="' + ('list.html?serverId=' + ApiClient.serverId() + '&type=' + section.types + '&IsFavorite=true') + '" class="more button-flat button-flat-mini sectionTitleTextButton">';
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
||||
html += globalize.translate(section.name);
|
||||
html += "</h2>";
|
||||
html += '<i class="md-icon">chevron_right</i>';
|
||||
html += "</a>";
|
||||
html += '</h2>';
|
||||
html += '<span class="material-icons chevron_right"></span>';
|
||||
html += '</a>';
|
||||
} else {
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate(section.name) + "</h2>";
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate(section.name) + '</h2>';
|
||||
}
|
||||
|
||||
html += "</div>";
|
||||
html += '</div>';
|
||||
if (enableScrollX()) {
|
||||
var scrollXClass = "scrollX hiddenScrollX";
|
||||
var scrollXClass = 'scrollX hiddenScrollX';
|
||||
if (layoutManager.tv) {
|
||||
scrollXClass += " smoothScrollX";
|
||||
scrollXClass += ' smoothScrollX';
|
||||
}
|
||||
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer ' + scrollXClass + ' padded-left padded-right">';
|
||||
|
@ -154,7 +154,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right">';
|
||||
}
|
||||
|
||||
var supportsImageAnalysis = appHost.supports("imageanalysis");
|
||||
var supportsImageAnalysis = appHost.supports('imageanalysis');
|
||||
var cardLayout = (appHost.preferVisualCards || supportsImageAnalysis) && section.autoCardLayout && section.showTitle;
|
||||
cardLayout = false;
|
||||
html += cardBuilder.getCardsHtml(result.Items, {
|
||||
|
@ -172,7 +172,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
allowBottomPadding: !enableScrollX(),
|
||||
cardLayout: cardLayout
|
||||
});
|
||||
html += "</div>";
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
elem.innerHTML = html;
|
||||
|
@ -183,7 +183,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
function loadSections(page, userId, topParentId, types) {
|
||||
loading.show();
|
||||
var sections = getSections();
|
||||
var sectionid = getParameterByName("sectionid");
|
||||
var sectionid = getParameterByName('sectionid');
|
||||
|
||||
if (sectionid) {
|
||||
sections = sections.filter(function (s) {
|
||||
|
@ -199,10 +199,10 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
|
||||
var i;
|
||||
var length;
|
||||
var elem = page.querySelector(".favoriteSections");
|
||||
var elem = page.querySelector('.favoriteSections');
|
||||
|
||||
if (!elem.innerHTML) {
|
||||
var html = "";
|
||||
var html = '';
|
||||
|
||||
for (i = 0, length = sections.length; i < length; i++) {
|
||||
html += '<div class="verticalSection section' + sections[i].id + '"></div>';
|
||||
|
@ -215,7 +215,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
|||
|
||||
for (i = 0, length = sections.length; i < length; i++) {
|
||||
var section = sections[i];
|
||||
elem = page.querySelector(".section" + section.id);
|
||||
elem = page.querySelector('.section' + section.id);
|
||||
promises.push(loadSection(elem, userId, topParentId, section, 1 === sections.length));
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ define([], function () {
|
|||
|
||||
function fetchWithTimeout(url, options, timeoutMs) {
|
||||
|
||||
console.log('fetchWithTimeout: timeoutMs: ' + timeoutMs + ', url: ' + url);
|
||||
console.debug('fetchWithTimeout: timeoutMs: ' + timeoutMs + ', url: ' + url);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
|
@ -63,14 +63,14 @@ define([], function () {
|
|||
fetch(url, options).then(function (response) {
|
||||
clearTimeout(timeout);
|
||||
|
||||
console.log('fetchWithTimeout: succeeded connecting to url: ' + url);
|
||||
console.debug('fetchWithTimeout: succeeded connecting to url: ' + url);
|
||||
|
||||
resolve(response);
|
||||
}, function (error) {
|
||||
|
||||
clearTimeout(timeout);
|
||||
|
||||
console.log('fetchWithTimeout: timed out connecting to url: ' + url);
|
||||
console.debug('fetchWithTimeout: timed out connecting to url: ' + url);
|
||||
|
||||
reject();
|
||||
});
|
||||
|
@ -86,28 +86,24 @@ define([], function () {
|
|||
var value = params[key];
|
||||
|
||||
if (value !== null && value !== undefined && value !== '') {
|
||||
values.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
|
||||
values.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
|
||||
}
|
||||
}
|
||||
return values.join('&');
|
||||
}
|
||||
|
||||
function ajax(request) {
|
||||
|
||||
if (!request) {
|
||||
throw new Error("Request cannot be null");
|
||||
throw new Error('Request cannot be null');
|
||||
}
|
||||
|
||||
request.headers = request.headers || {};
|
||||
|
||||
console.log('requesting url: ' + request.url);
|
||||
console.debug('requesting url: ' + request.url);
|
||||
|
||||
return getFetchPromise(request).then(function (response) {
|
||||
|
||||
console.log('response status: ' + response.status + ', url: ' + request.url);
|
||||
|
||||
console.debug('response status: ' + response.status + ', url: ' + request.url);
|
||||
if (response.status < 400) {
|
||||
|
||||
if (request.dataType === 'json' || request.headers.accept === 'application/json') {
|
||||
return response.json();
|
||||
} else if (request.dataType === 'text' || (response.headers.get('Content-Type') || '').toLowerCase().indexOf('text/') === 0) {
|
||||
|
@ -118,10 +114,8 @@ define([], function () {
|
|||
} else {
|
||||
return Promise.reject(response);
|
||||
}
|
||||
|
||||
}, function (err) {
|
||||
|
||||
console.log('request failed to url: ' + request.url);
|
||||
console.error('request failed to url: ' + request.url);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
@ -129,4 +123,4 @@ define([], function () {
|
|||
getFetchPromise: getFetchPromise,
|
||||
ajax: ajax
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
define(['multi-download'], function (multiDownload) {
|
||||
'use strict';
|
||||
import multiDownload from 'multi-download';
|
||||
|
||||
return {
|
||||
download: function (items) {
|
||||
export function download(items) {
|
||||
|
||||
if (window.NativeShell) {
|
||||
items.map(function (item) {
|
||||
window.NativeShell.downloadFile(item.url);
|
||||
});
|
||||
} else {
|
||||
multiDownload(items.map(function (item) {
|
||||
return item.url;
|
||||
}));
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
if (window.NativeShell) {
|
||||
items.map(function (item) {
|
||||
window.NativeShell.downloadFile(item);
|
||||
});
|
||||
} else {
|
||||
multiDownload(items.map(function (item) {
|
||||
return item.url;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
define([], function () {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
fileExists: function (path) {
|
||||
if (window.NativeShell && window.NativeShell.FileSystem) {
|
||||
return window.NativeShell.FileSystem.fileExists(path);
|
||||
}
|
||||
return Promise.reject();
|
||||
},
|
||||
directoryExists: function (path) {
|
||||
if (window.NativeShell && window.NativeShell.FileSystem) {
|
||||
return window.NativeShell.FileSystem.directoryExists(path);
|
||||
}
|
||||
return Promise.reject();
|
||||
}
|
||||
};
|
||||
});
|
|
@ -1,52 +1,49 @@
|
|||
define(["dialogHelper", "globalize", "connectionManager", "events", "browser", "require", "emby-checkbox", "emby-collapse", "css!./style"], function (dialogHelper, globalize, connectionManager, events, browser, require) {
|
||||
"use strict";
|
||||
define(['dom', 'dialogHelper', 'globalize', 'connectionManager', 'events', 'browser', 'require', 'emby-checkbox', 'emby-collapse', 'css!./style'], function (dom, dialogHelper, globalize, connectionManager, events, browser, require) {
|
||||
'use strict';
|
||||
|
||||
function renderOptions(context, selector, cssClass, items, isCheckedFn) {
|
||||
var elem = context.querySelector(selector);
|
||||
if (items.length) {
|
||||
elem.classList.remove("hide");
|
||||
elem.classList.remove('hide');
|
||||
} else {
|
||||
elem.classList.add("hide");
|
||||
elem.classList.add('hide');
|
||||
}
|
||||
var html = "";
|
||||
var html = '';
|
||||
html += '<div class="checkboxList">';
|
||||
html += items.map(function (filter) {
|
||||
var itemHtml = "";
|
||||
var checkedHtml = isCheckedFn(filter) ? " checked" : "";
|
||||
itemHtml += "<label>";
|
||||
var itemHtml = '';
|
||||
var checkedHtml = isCheckedFn(filter) ? ' checked' : '';
|
||||
itemHtml += '<label>';
|
||||
itemHtml += '<input is="emby-checkbox" type="checkbox"' + checkedHtml + ' data-filter="' + filter + '" class="' + cssClass + '"/>';
|
||||
itemHtml += "<span>" + filter + "</span>";
|
||||
itemHtml += "</label>";
|
||||
itemHtml += '<span>' + filter + '</span>';
|
||||
itemHtml += '</label>';
|
||||
return itemHtml;
|
||||
}).join("");
|
||||
html += "</div>";
|
||||
elem.querySelector(".filterOptions").innerHTML = html;
|
||||
}).join('');
|
||||
html += '</div>';
|
||||
elem.querySelector('.filterOptions').innerHTML = html;
|
||||
}
|
||||
|
||||
function renderFilters(context, result, query) {
|
||||
if (result.Tags) {
|
||||
result.Tags.length = Math.min(result.Tags.length, 50);
|
||||
}
|
||||
renderOptions(context, ".genreFilters", "chkGenreFilter", result.Genres, function (i) {
|
||||
var delimeter = "|";
|
||||
return (delimeter + (query.Genres || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
||||
renderOptions(context, '.genreFilters', 'chkGenreFilter', result.Genres, function (i) {
|
||||
var delimeter = '|';
|
||||
return (delimeter + (query.Genres || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
||||
});
|
||||
renderOptions(context, ".officialRatingFilters", "chkOfficialRatingFilter", result.OfficialRatings, function (i) {
|
||||
var delimeter = "|";
|
||||
return (delimeter + (query.OfficialRatings || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
||||
renderOptions(context, '.officialRatingFilters', 'chkOfficialRatingFilter', result.OfficialRatings, function (i) {
|
||||
var delimeter = '|';
|
||||
return (delimeter + (query.OfficialRatings || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
||||
});
|
||||
renderOptions(context, ".tagFilters", "chkTagFilter", result.Tags, function (i) {
|
||||
var delimeter = "|";
|
||||
return (delimeter + (query.Tags || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
||||
renderOptions(context, '.tagFilters', 'chkTagFilter', result.Tags, function (i) {
|
||||
var delimeter = '|';
|
||||
return (delimeter + (query.Tags || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
||||
});
|
||||
renderOptions(context, ".yearFilters", "chkYearFilter", result.Years, function (i) {
|
||||
var delimeter = ",";
|
||||
return (delimeter + (query.Years || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
||||
renderOptions(context, '.yearFilters', 'chkYearFilter', result.Years, function (i) {
|
||||
var delimeter = ',';
|
||||
return (delimeter + (query.Years || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
||||
});
|
||||
}
|
||||
|
||||
function loadDynamicFilters(context, apiClient, userId, itemQuery) {
|
||||
return apiClient.getJSON(apiClient.getUrl("Items/Filters", {
|
||||
return apiClient.getJSON(apiClient.getUrl('Items/Filters', {
|
||||
UserId: userId,
|
||||
ParentId: itemQuery.ParentId,
|
||||
IncludeItemTypes: itemQuery.IncludeItemTypes
|
||||
|
@ -61,108 +58,98 @@ define(["dialogHelper", "globalize", "connectionManager", "events", "browser", "
|
|||
var length;
|
||||
var query = options.query;
|
||||
|
||||
if (options.mode == "livetvchannels") {
|
||||
context.querySelector(".chkFavorite").checked = query.IsFavorite == true;
|
||||
context.querySelector(".chkLikes").checked = query.IsLiked == true;
|
||||
context.querySelector(".chkDislikes").checked = query.IsDisliked == true;
|
||||
if (options.mode == 'livetvchannels') {
|
||||
context.querySelector('.chkFavorite').checked = query.IsFavorite == true;
|
||||
context.querySelector('.chkLikes').checked = query.IsLiked == true;
|
||||
context.querySelector('.chkDislikes').checked = query.IsDisliked == true;
|
||||
} else {
|
||||
elems = context.querySelectorAll(".chkStandardFilter");
|
||||
elems = context.querySelectorAll('.chkStandardFilter');
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
var chkStandardFilter = elems[i];
|
||||
var filters = "," + (query.Filters || "");
|
||||
var filterName = chkStandardFilter.getAttribute("data-filter");
|
||||
chkStandardFilter.checked = filters.indexOf("," + filterName) != -1;
|
||||
var filters = ',' + (query.Filters || '');
|
||||
var filterName = chkStandardFilter.getAttribute('data-filter');
|
||||
chkStandardFilter.checked = filters.indexOf(',' + filterName) != -1;
|
||||
}
|
||||
}
|
||||
|
||||
elems = context.querySelectorAll(".chkVideoTypeFilter");
|
||||
elems = context.querySelectorAll('.chkVideoTypeFilter');
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
var chkVideoTypeFilter = elems[i];
|
||||
var filters = "," + (query.VideoTypes || "");
|
||||
var filterName = chkVideoTypeFilter.getAttribute("data-filter");
|
||||
chkVideoTypeFilter.checked = filters.indexOf("," + filterName) != -1;
|
||||
var filters = ',' + (query.VideoTypes || '');
|
||||
var filterName = chkVideoTypeFilter.getAttribute('data-filter');
|
||||
chkVideoTypeFilter.checked = filters.indexOf(',' + filterName) != -1;
|
||||
}
|
||||
context.querySelector(".chk3DFilter").checked = query.Is3D == true;
|
||||
context.querySelector(".chkHDFilter").checked = query.IsHD == true;
|
||||
context.querySelector(".chk4KFilter").checked = query.Is4K == true;
|
||||
context.querySelector(".chkSDFilter").checked = query.IsHD == true;
|
||||
context.querySelector("#chkSubtitle").checked = query.HasSubtitles == true;
|
||||
context.querySelector("#chkTrailer").checked = query.HasTrailer == true;
|
||||
context.querySelector("#chkThemeSong").checked = query.HasThemeSong == true;
|
||||
context.querySelector("#chkThemeVideo").checked = query.HasThemeVideo == true;
|
||||
context.querySelector("#chkSpecialFeature").checked = query.HasSpecialFeature == true;
|
||||
context.querySelector("#chkSpecialEpisode").checked = query.ParentIndexNumber == 0;
|
||||
context.querySelector("#chkMissingEpisode").checked = query.IsMissing == true;
|
||||
context.querySelector("#chkFutureEpisode").checked = query.IsUnaired == true;
|
||||
context.querySelector('.chk3DFilter').checked = query.Is3D == true;
|
||||
context.querySelector('.chkHDFilter').checked = query.IsHD == true;
|
||||
context.querySelector('.chk4KFilter').checked = query.Is4K == true;
|
||||
context.querySelector('.chkSDFilter').checked = query.IsHD == true;
|
||||
context.querySelector('#chkSubtitle').checked = query.HasSubtitles == true;
|
||||
context.querySelector('#chkTrailer').checked = query.HasTrailer == true;
|
||||
context.querySelector('#chkThemeSong').checked = query.HasThemeSong == true;
|
||||
context.querySelector('#chkThemeVideo').checked = query.HasThemeVideo == true;
|
||||
context.querySelector('#chkSpecialFeature').checked = query.HasSpecialFeature == true;
|
||||
context.querySelector('#chkSpecialEpisode').checked = query.ParentIndexNumber == 0;
|
||||
context.querySelector('#chkMissingEpisode').checked = query.IsMissing == true;
|
||||
context.querySelector('#chkFutureEpisode').checked = query.IsUnaired == true;
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
var chkStatus = elems[i];
|
||||
var filters = "," + (query.SeriesStatus || "");
|
||||
var filterName = chkStatus.getAttribute("data-filter");
|
||||
chkStatus.checked = filters.indexOf("," + filterName) != -1;
|
||||
var filters = ',' + (query.SeriesStatus || '');
|
||||
var filterName = chkStatus.getAttribute('data-filter');
|
||||
chkStatus.checked = filters.indexOf(',' + filterName) != -1;
|
||||
}
|
||||
}
|
||||
|
||||
function triggerChange(instance) {
|
||||
events.trigger(instance, "filterchange");
|
||||
}
|
||||
|
||||
function parentWithClass(elem, className) {
|
||||
while (!elem.classList || !elem.classList.contains(className)) {
|
||||
elem = elem.parentNode;
|
||||
if (!elem) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return elem;
|
||||
events.trigger(instance, 'filterchange');
|
||||
}
|
||||
|
||||
function setVisibility(context, options) {
|
||||
if (options.mode == "livetvchannels" || options.mode == "albums" || options.mode == "artists" || options.mode == "albumartists" || options.mode == "songs") {
|
||||
hideByClass(context, "videoStandard");
|
||||
if (options.mode == 'livetvchannels' || options.mode == 'albums' || options.mode == 'artists' || options.mode == 'albumartists' || options.mode == 'songs') {
|
||||
hideByClass(context, 'videoStandard');
|
||||
}
|
||||
|
||||
if (enableDynamicFilters(options.mode)) {
|
||||
context.querySelector(".genreFilters").classList.remove("hide");
|
||||
context.querySelector(".officialRatingFilters").classList.remove("hide");
|
||||
context.querySelector(".tagFilters").classList.remove("hide");
|
||||
context.querySelector(".yearFilters").classList.remove("hide");
|
||||
context.querySelector('.genreFilters').classList.remove('hide');
|
||||
context.querySelector('.officialRatingFilters').classList.remove('hide');
|
||||
context.querySelector('.tagFilters').classList.remove('hide');
|
||||
context.querySelector('.yearFilters').classList.remove('hide');
|
||||
}
|
||||
|
||||
if (options.mode == "movies" || options.mode == "episodes") {
|
||||
context.querySelector(".videoTypeFilters").classList.remove("hide");
|
||||
if (options.mode == 'movies' || options.mode == 'episodes') {
|
||||
context.querySelector('.videoTypeFilters').classList.remove('hide');
|
||||
}
|
||||
|
||||
if (options.mode == "movies" || options.mode == "series" || options.mode == "episodes") {
|
||||
context.querySelector(".features").classList.remove("hide");
|
||||
if (options.mode == 'movies' || options.mode == 'series' || options.mode == 'episodes') {
|
||||
context.querySelector('.features').classList.remove('hide');
|
||||
}
|
||||
|
||||
if (options.mode == "series") {
|
||||
context.querySelector(".seriesStatus").classList.remove("hide");
|
||||
if (options.mode == 'series') {
|
||||
context.querySelector('.seriesStatus').classList.remove('hide');
|
||||
}
|
||||
|
||||
if (options.mode == "episodes") {
|
||||
showByClass(context, "episodeFilter");
|
||||
if (options.mode == 'episodes') {
|
||||
showByClass(context, 'episodeFilter');
|
||||
}
|
||||
}
|
||||
|
||||
function showByClass(context, className) {
|
||||
var elems = context.querySelectorAll("." + className);
|
||||
var elems = context.querySelectorAll('.' + className);
|
||||
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
elems[i].classList.remove("hide");
|
||||
elems[i].classList.remove('hide');
|
||||
}
|
||||
}
|
||||
|
||||
function hideByClass(context, className) {
|
||||
var elems = context.querySelectorAll("." + className);
|
||||
var elems = context.querySelectorAll('.' + className);
|
||||
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
elems[i].classList.add("hide");
|
||||
elems[i].classList.add('hide');
|
||||
}
|
||||
}
|
||||
|
||||
function enableDynamicFilters(mode) {
|
||||
return mode == "movies" || mode == "series" || mode == "albums" || mode == "albumartists" || mode == "artists" || mode == "songs" || mode == "episodes";
|
||||
return mode == 'movies' || mode == 'series' || mode == 'albums' || mode == 'albumartists' || mode == 'artists' || mode == 'songs' || mode == 'episodes';
|
||||
}
|
||||
|
||||
return function (options) {
|
||||
|
@ -175,12 +162,12 @@ define(["dialogHelper", "globalize", "connectionManager", "events", "browser", "
|
|||
|
||||
function onStandardFilterChange() {
|
||||
var query = options.query;
|
||||
var filterName = this.getAttribute("data-filter");
|
||||
var filters = query.Filters || "";
|
||||
filters = ("," + filters).replace("," + filterName, "").substring(1);
|
||||
var filterName = this.getAttribute('data-filter');
|
||||
var filters = query.Filters || '';
|
||||
filters = (',' + filters).replace(',' + filterName, '').substring(1);
|
||||
|
||||
if (this.checked) {
|
||||
filters = filters ? filters + "," + filterName : filterName;
|
||||
filters = filters ? filters + ',' + filterName : filterName;
|
||||
}
|
||||
|
||||
query.StartIndex = 0;
|
||||
|
@ -190,12 +177,12 @@ define(["dialogHelper", "globalize", "connectionManager", "events", "browser", "
|
|||
|
||||
function onVideoTypeFilterChange() {
|
||||
var query = options.query;
|
||||
var filterName = this.getAttribute("data-filter");
|
||||
var filters = query.VideoTypes || "";
|
||||
filters = ("," + filters).replace("," + filterName, "").substring(1);
|
||||
var filterName = this.getAttribute('data-filter');
|
||||
var filters = query.VideoTypes || '';
|
||||
filters = (',' + filters).replace(',' + filterName, '').substring(1);
|
||||
|
||||
if (this.checked) {
|
||||
filters = filters ? filters + "," + filterName : filterName;
|
||||
filters = filters ? filters + ',' + filterName : filterName;
|
||||
}
|
||||
|
||||
query.StartIndex = 0;
|
||||
|
@ -205,12 +192,12 @@ define(["dialogHelper", "globalize", "connectionManager", "events", "browser", "
|
|||
|
||||
function onStatusChange() {
|
||||
var query = options.query;
|
||||
var filterName = this.getAttribute("data-filter");
|
||||
var filters = query.SeriesStatus || "";
|
||||
filters = ("," + filters).replace("," + filterName, "").substring(1);
|
||||
var filterName = this.getAttribute('data-filter');
|
||||
var filters = query.SeriesStatus || '';
|
||||
filters = (',' + filters).replace(',' + filterName, '').substring(1);
|
||||
|
||||
if (this.checked) {
|
||||
filters = filters ? filters + "," + filterName : filterName;
|
||||
filters = filters ? filters + ',' + filterName : filterName;
|
||||
}
|
||||
|
||||
query.SeriesStatus = filters;
|
||||
|
@ -224,86 +211,86 @@ define(["dialogHelper", "globalize", "connectionManager", "events", "browser", "
|
|||
var length;
|
||||
var query = options.query;
|
||||
|
||||
if (options.mode == "livetvchannels") {
|
||||
elems = context.querySelectorAll(".chkFavorite");
|
||||
if (options.mode == 'livetvchannels') {
|
||||
elems = context.querySelectorAll('.chkFavorite');
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
elems[i].addEventListener("change", onFavoriteChange);
|
||||
elems[i].addEventListener('change', onFavoriteChange);
|
||||
}
|
||||
context.querySelector(".chkLikes").addEventListener("change", function () {
|
||||
context.querySelector('.chkLikes').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.IsLiked = this.checked ? true : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
context.querySelector(".chkDislikes").addEventListener("change", function () {
|
||||
context.querySelector('.chkDislikes').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.IsDisliked = this.checked ? true : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
} else {
|
||||
elems = context.querySelectorAll(".chkStandardFilter");
|
||||
elems = context.querySelectorAll('.chkStandardFilter');
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
elems[i].addEventListener("change", onStandardFilterChange);
|
||||
elems[i].addEventListener('change', onStandardFilterChange);
|
||||
}
|
||||
}
|
||||
elems = context.querySelectorAll(".chkVideoTypeFilter");
|
||||
elems = context.querySelectorAll('.chkVideoTypeFilter');
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
elems[i].addEventListener("change", onVideoTypeFilterChange);
|
||||
elems[i].addEventListener('change', onVideoTypeFilterChange);
|
||||
}
|
||||
context.querySelector(".chk3DFilter").addEventListener("change", function () {
|
||||
context.querySelector('.chk3DFilter').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.Is3D = this.checked ? true : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
context.querySelector(".chk4KFilter").addEventListener("change", function () {
|
||||
context.querySelector('.chk4KFilter').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.Is4K = this.checked ? true : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
context.querySelector(".chkHDFilter").addEventListener("change", function () {
|
||||
context.querySelector('.chkHDFilter').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.IsHD = this.checked ? true : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
context.querySelector(".chkSDFilter").addEventListener("change", function () {
|
||||
context.querySelector('.chkSDFilter').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.IsHD = this.checked ? false : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
elems = context.querySelectorAll(".chkStatus");
|
||||
elems = context.querySelectorAll('.chkStatus');
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
elems[i].addEventListener("change", onStatusChange);
|
||||
elems[i].addEventListener('change', onStatusChange);
|
||||
}
|
||||
context.querySelector("#chkTrailer").addEventListener("change", function () {
|
||||
context.querySelector('#chkTrailer').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.HasTrailer = this.checked ? true : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
context.querySelector("#chkThemeSong").addEventListener("change", function () {
|
||||
context.querySelector('#chkThemeSong').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.HasThemeSong = this.checked ? true : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
context.querySelector("#chkSpecialFeature").addEventListener("change", function () {
|
||||
context.querySelector('#chkSpecialFeature').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.HasSpecialFeature = this.checked ? true : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
context.querySelector("#chkThemeVideo").addEventListener("change", function () {
|
||||
context.querySelector('#chkThemeVideo').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.HasThemeVideo = this.checked ? true : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
context.querySelector("#chkMissingEpisode").addEventListener("change", function () {
|
||||
context.querySelector('#chkMissingEpisode').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.IsMissing = this.checked ? true : false;
|
||||
triggerChange(self);
|
||||
});
|
||||
context.querySelector("#chkSpecialEpisode").addEventListener("change", function () {
|
||||
context.querySelector('#chkSpecialEpisode').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.ParentIndexNumber = this.checked ? 0 : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
context.querySelector("#chkFutureEpisode").addEventListener("change", function () {
|
||||
context.querySelector('#chkFutureEpisode').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
if (this.checked) {
|
||||
query.IsUnaired = true;
|
||||
|
@ -314,18 +301,18 @@ define(["dialogHelper", "globalize", "connectionManager", "events", "browser", "
|
|||
}
|
||||
triggerChange(self);
|
||||
});
|
||||
context.querySelector("#chkSubtitle").addEventListener("change", function () {
|
||||
context.querySelector('#chkSubtitle').addEventListener('change', function () {
|
||||
query.StartIndex = 0;
|
||||
query.HasSubtitles = this.checked ? true : null;
|
||||
triggerChange(self);
|
||||
});
|
||||
context.addEventListener("change", function (e) {
|
||||
var chkGenreFilter = parentWithClass(e.target, "chkGenreFilter");
|
||||
context.addEventListener('change', function (e) {
|
||||
var chkGenreFilter = dom.parentWithClass(e.target, 'chkGenreFilter');
|
||||
if (chkGenreFilter) {
|
||||
var filterName = chkGenreFilter.getAttribute("data-filter");
|
||||
var filters = query.Genres || "";
|
||||
var delimiter = "|";
|
||||
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
|
||||
var filterName = chkGenreFilter.getAttribute('data-filter');
|
||||
var filters = query.Genres || '';
|
||||
var delimiter = '|';
|
||||
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||
if (chkGenreFilter.checked) {
|
||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||
}
|
||||
|
@ -334,12 +321,12 @@ define(["dialogHelper", "globalize", "connectionManager", "events", "browser", "
|
|||
triggerChange(self);
|
||||
return;
|
||||
}
|
||||
var chkTagFilter = parentWithClass(e.target, "chkTagFilter");
|
||||
var chkTagFilter = dom.parentWithClass(e.target, 'chkTagFilter');
|
||||
if (chkTagFilter) {
|
||||
var filterName = chkTagFilter.getAttribute("data-filter");
|
||||
var filters = query.Tags || "";
|
||||
var delimiter = "|";
|
||||
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
|
||||
var filterName = chkTagFilter.getAttribute('data-filter');
|
||||
var filters = query.Tags || '';
|
||||
var delimiter = '|';
|
||||
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||
if (chkTagFilter.checked) {
|
||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||
}
|
||||
|
@ -348,12 +335,12 @@ define(["dialogHelper", "globalize", "connectionManager", "events", "browser", "
|
|||
triggerChange(self);
|
||||
return;
|
||||
}
|
||||
var chkYearFilter = parentWithClass(e.target, "chkYearFilter");
|
||||
var chkYearFilter = dom.parentWithClass(e.target, 'chkYearFilter');
|
||||
if (chkYearFilter) {
|
||||
var filterName = chkYearFilter.getAttribute("data-filter");
|
||||
var filters = query.Years || "";
|
||||
var delimiter = ",";
|
||||
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
|
||||
var filterName = chkYearFilter.getAttribute('data-filter');
|
||||
var filters = query.Years || '';
|
||||
var delimiter = ',';
|
||||
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||
if (chkYearFilter.checked) {
|
||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||
}
|
||||
|
@ -362,12 +349,12 @@ define(["dialogHelper", "globalize", "connectionManager", "events", "browser", "
|
|||
triggerChange(self);
|
||||
return;
|
||||
}
|
||||
var chkOfficialRatingFilter = parentWithClass(e.target, "chkOfficialRatingFilter");
|
||||
var chkOfficialRatingFilter = dom.parentWithClass(e.target, 'chkOfficialRatingFilter');
|
||||
if (chkOfficialRatingFilter) {
|
||||
var filterName = chkOfficialRatingFilter.getAttribute("data-filter");
|
||||
var filters = query.OfficialRatings || "";
|
||||
var delimiter = "|";
|
||||
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
|
||||
var filterName = chkOfficialRatingFilter.getAttribute('data-filter');
|
||||
var filters = query.OfficialRatings || '';
|
||||
var delimiter = '|';
|
||||
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||
if (chkOfficialRatingFilter.checked) {
|
||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||
}
|
||||
|
@ -383,23 +370,23 @@ define(["dialogHelper", "globalize", "connectionManager", "events", "browser", "
|
|||
|
||||
self.show = function () {
|
||||
return new Promise(function (resolve, reject) {
|
||||
require(["text!./filterdialog.template.html"], function (template) {
|
||||
require(['text!./filterdialog.template.html'], function (template) {
|
||||
var dlg = dialogHelper.createDialog({
|
||||
removeOnClose: true,
|
||||
modal: false
|
||||
});
|
||||
dlg.classList.add("ui-body-a");
|
||||
dlg.classList.add("background-theme-a");
|
||||
dlg.classList.add("formDialog");
|
||||
dlg.classList.add("filterDialog");
|
||||
dlg.classList.add('ui-body-a');
|
||||
dlg.classList.add('background-theme-a');
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.classList.add('filterDialog');
|
||||
dlg.innerHTML = globalize.translateDocument(template);
|
||||
setVisibility(dlg, options);
|
||||
dialogHelper.open(dlg);
|
||||
dlg.addEventListener("close", resolve);
|
||||
dlg.addEventListener('close', resolve);
|
||||
updateFilterControls(dlg, options);
|
||||
bindEvents(dlg);
|
||||
if (enableDynamicFilters(options.mode)) {
|
||||
dlg.classList.add("dynamicFilterDialog");
|
||||
dlg.classList.add('dynamicFilterDialog');
|
||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
||||
loadDynamicFilters(dlg, apiClient, apiClient.getCurrentUserId(), options.query);
|
||||
}
|
||||
|
|
|
@ -5,31 +5,32 @@
|
|||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
-webkit-border-radius: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
max-height: none !important;
|
||||
max-width: none !important
|
||||
max-width: none !important;
|
||||
}
|
||||
|
||||
@media all and (min-height:600px) {
|
||||
@media all and (min-height: 600px) {
|
||||
.dynamicFilterDialog {
|
||||
top: 10% !important;
|
||||
bottom: 25% !important
|
||||
bottom: 25% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width:400px) {
|
||||
@media all and (max-width: 400px) {
|
||||
.dynamicFilterDialog {
|
||||
width: auto;
|
||||
left: 10vw !important;
|
||||
right: 10vw !important;
|
||||
margin-left: 0 !important
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width:400px) {
|
||||
@media all and (min-width: 400px) {
|
||||
.dynamicFilterDialog {
|
||||
width: 300px;
|
||||
margin-left: -150px !important;
|
||||
left: 50% !important
|
||||
width: 20.16em;
|
||||
margin-left: -10.08em !important;
|
||||
left: 50% !important;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -279,7 +279,7 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
|||
var html = '';
|
||||
|
||||
html += '<div class="formDialogHeader">';
|
||||
html += '<button is="paper-icon-button-light" class="btnCancel hide-mouse-idle-tv" tabindex="-1"><i class="md-icon">arrow_back</i></button>';
|
||||
html += '<button is="paper-icon-button-light" class="btnCancel hide-mouse-idle-tv" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<h3 class="formDialogHeaderTitle">${Filters}</h3>';
|
||||
|
||||
html += '</div>';
|
||||
|
|
|
@ -105,4 +105,4 @@
|
|||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -43,7 +43,7 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
|||
preventScroll: scrollManager.isEnabled()
|
||||
});
|
||||
} catch (err) {
|
||||
console.log('Error in focusManager.autoFocus: ' + err);
|
||||
console.error('Error in focusManager.autoFocus: ' + err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (elem.getAttribute('tabindex') === "-1") {
|
||||
if (elem.getAttribute('tabindex') === '-1') {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,14 +5,15 @@
|
|||
}
|
||||
|
||||
.formDialogHeader {
|
||||
padding: 1em .5em;
|
||||
padding: 1em 0.5em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.formDialogHeaderTitle {
|
||||
margin-left: .25em;
|
||||
margin-left: 0.25em;
|
||||
|
||||
/* In case of h1, h2, h3 */
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
|
@ -23,7 +24,7 @@
|
|||
}
|
||||
|
||||
.dialogContentInner {
|
||||
padding: .5em 1em 20em 1em;
|
||||
padding: 0.5em 1em 20em 1em;
|
||||
}
|
||||
|
||||
.dialogContentInner-mini {
|
||||
|
@ -46,6 +47,7 @@
|
|||
display: flex;
|
||||
position: absolute;
|
||||
padding: 1.25em 1em;
|
||||
|
||||
/* Without this emby-checkbox is able to appear on top */
|
||||
z-index: 1;
|
||||
align-items: center;
|
||||
|
@ -62,11 +64,11 @@
|
|||
padding-bottom: 1.5em;
|
||||
flex-direction: column;
|
||||
width: 80% !important;
|
||||
padding-top: .5em;
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
|
||||
.formDialogFooterItem {
|
||||
margin: .5em !important;
|
||||
margin: 0.5em !important;
|
||||
flex-grow: 1;
|
||||
text-align: center;
|
||||
flex-basis: 0;
|
||||
|
@ -91,7 +93,6 @@
|
|||
}
|
||||
|
||||
@media all and (min-width: 50em) {
|
||||
|
||||
.formDialogFooterItem {
|
||||
max-width: 80%;
|
||||
}
|
||||
|
@ -103,7 +104,6 @@
|
|||
}
|
||||
|
||||
@media all and (min-width: 80em) {
|
||||
|
||||
.formDialogFooterItem {
|
||||
max-width: 70%;
|
||||
}
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
define(['events', 'dom', 'apphost', 'browser'], function (events, dom, appHost, browser) {
|
||||
'use strict';
|
||||
|
||||
function fullscreenManager() {
|
||||
|
||||
}
|
||||
|
||||
fullscreenManager.prototype.requestFullscreen = function (element) {
|
||||
|
||||
element = element || document.documentElement;
|
||||
|
||||
if (element.requestFullscreen) {
|
||||
element.requestFullscreen();
|
||||
return;
|
||||
} else if (element.mozRequestFullScreen) {
|
||||
element.mozRequestFullScreen();
|
||||
return;
|
||||
} else if (element.webkitRequestFullscreen) {
|
||||
element.webkitRequestFullscreen();
|
||||
return;
|
||||
} else if (element.msRequestFullscreen) {
|
||||
element.msRequestFullscreen();
|
||||
return;
|
||||
}
|
||||
|
||||
// Hack - This is only available for video elements in ios safari
|
||||
if (element.tagName !== 'VIDEO') {
|
||||
element = document.querySelector('video') || element;
|
||||
}
|
||||
if (element.webkitEnterFullscreen) {
|
||||
element.webkitEnterFullscreen();
|
||||
}
|
||||
};
|
||||
|
||||
fullscreenManager.prototype.exitFullscreen = function () {
|
||||
|
||||
if (!this.isFullScreen()) {
|
||||
return;
|
||||
}
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.webkitExitFullscreen) {
|
||||
document.webkitExitFullscreen();
|
||||
} else if (document.webkitCancelFullscreen) {
|
||||
document.webkitCancelFullscreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen();
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: use screenfull.js
|
||||
fullscreenManager.prototype.isFullScreen = function () {
|
||||
return document.fullscreen ||
|
||||
document.mozFullScreen ||
|
||||
document.webkitIsFullScreen ||
|
||||
document.msFullscreenElement || /* IE/Edge syntax */
|
||||
document.fullscreenElement || /* Standard syntax */
|
||||
document.webkitFullscreenElement || /* Chrome, Safari and Opera syntax */
|
||||
document.mozFullScreenElement; /* Firefox syntax */
|
||||
};
|
||||
|
||||
var manager = new fullscreenManager();
|
||||
|
||||
function onFullScreenChange() {
|
||||
events.trigger(manager, 'fullscreenchange');
|
||||
}
|
||||
|
||||
dom.addEventListener(document, 'fullscreenchange', onFullScreenChange, {
|
||||
passive: true
|
||||
});
|
||||
|
||||
dom.addEventListener(document, 'webkitfullscreenchange', onFullScreenChange, {
|
||||
passive: true
|
||||
});
|
||||
|
||||
dom.addEventListener(document, 'mozfullscreenchange', onFullScreenChange, {
|
||||
passive: true
|
||||
});
|
||||
|
||||
function isTargetValid(target) {
|
||||
return !dom.parentWithTag(target, ['BUTTON', 'INPUT', 'TEXTAREA']);
|
||||
}
|
||||
if (appHost.supports("fullscreenchange") && (browser.edgeUwp || -1 !== navigator.userAgent.toLowerCase().indexOf("electron"))) {
|
||||
|
||||
dom.addEventListener(window, 'dblclick', function (e) {
|
||||
|
||||
if (isTargetValid(e.target)) {
|
||||
if (manager.isFullScreen()) {
|
||||
manager.exitFullscreen();
|
||||
} else {
|
||||
manager.requestFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
}, {
|
||||
passive: true
|
||||
});
|
||||
}
|
||||
|
||||
return manager;
|
||||
});
|
|
@ -1,28 +1,28 @@
|
|||
define(["dom", "appRouter", "connectionManager"], function (dom, appRouter, connectionManager) {
|
||||
"use strict";
|
||||
define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, connectionManager) {
|
||||
'use strict';
|
||||
|
||||
function onGroupedCardClick(e, card) {
|
||||
var itemId = card.getAttribute("data-id");
|
||||
var serverId = card.getAttribute("data-serverid");
|
||||
var itemId = card.getAttribute('data-id');
|
||||
var serverId = card.getAttribute('data-serverid');
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
var userId = apiClient.getCurrentUserId();
|
||||
var playedIndicator = card.querySelector(".playedIndicator");
|
||||
var playedIndicator = card.querySelector('.playedIndicator');
|
||||
var playedIndicatorHtml = playedIndicator ? playedIndicator.innerHTML : null;
|
||||
var options = {
|
||||
Limit: parseInt(playedIndicatorHtml || "10"),
|
||||
Fields: "PrimaryImageAspectRatio,DateCreated",
|
||||
Limit: parseInt(playedIndicatorHtml || '10'),
|
||||
Fields: 'PrimaryImageAspectRatio,DateCreated',
|
||||
ParentId: itemId,
|
||||
GroupItems: false
|
||||
};
|
||||
var actionableParent = dom.parentWithTag(e.target, ["A", "BUTTON", "INPUT"]);
|
||||
var actionableParent = dom.parentWithTag(e.target, ['A', 'BUTTON', 'INPUT']);
|
||||
|
||||
if (!actionableParent || actionableParent.classList.contains("cardContent")) {
|
||||
apiClient.getJSON(apiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function (items) {
|
||||
if (!actionableParent || actionableParent.classList.contains('cardContent')) {
|
||||
apiClient.getJSON(apiClient.getUrl('Users/' + userId + '/Items/Latest', options)).then(function (items) {
|
||||
if (1 === items.length) {
|
||||
return void appRouter.showItem(items[0]);
|
||||
}
|
||||
|
||||
var url = "itemdetails.html?id=" + itemId + "&serverId=" + serverId;
|
||||
var url = 'itemdetails.html?id=' + itemId + '&serverId=' + serverId;
|
||||
Dashboard.navigate(url);
|
||||
});
|
||||
e.stopPropagation();
|
||||
|
@ -32,7 +32,7 @@ define(["dom", "appRouter", "connectionManager"], function (dom, appRouter, conn
|
|||
}
|
||||
|
||||
function onItemsContainerClick(e) {
|
||||
var groupedCard = dom.parentWithClass(e.target, "groupedCard");
|
||||
var groupedCard = dom.parentWithClass(e.target, 'groupedCard');
|
||||
|
||||
if (groupedCard) {
|
||||
onGroupedCardClick(e, groupedCard);
|
||||
|
|
|
@ -89,20 +89,6 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
|
|||
}
|
||||
}
|
||||
|
||||
function onSortByChange() {
|
||||
var newValue = this.value;
|
||||
if (this.checked) {
|
||||
var changed = options.query.SortBy !== newValue;
|
||||
|
||||
options.query.SortBy = newValue.replace('_', ',');
|
||||
options.query.StartIndex = 0;
|
||||
|
||||
if (options.callback && changed) {
|
||||
options.callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showEditor(options) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
@ -171,4 +157,4 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
|
|||
return {
|
||||
show: showEditor
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<div class="formDialogHeader">
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="md-icon">arrow_back</i></button>
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" title="${LabelPrevious}" tabindex="-1">
|
||||
<span class="material-icons arrow_back" aria-hidden="true"></span>
|
||||
</button>
|
||||
<h3 class="formDialogHeaderTitle">
|
||||
${Settings}
|
||||
</h3>
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
}
|
||||
|
||||
.layout-desktop .tvGuideHeader {
|
||||
margin-bottom: .5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.guideHeaderDateSelection {
|
||||
font-size: 86%;
|
||||
padding: .4em 0;
|
||||
padding: 0.4em 0;
|
||||
}
|
||||
|
||||
.guide-headerTimeslots {
|
||||
|
@ -39,10 +39,10 @@
|
|||
|
||||
.guideProgramIndicator {
|
||||
text-transform: uppercase;
|
||||
border-radius: .25em;
|
||||
margin-right: .5em;
|
||||
border-radius: 0.25em;
|
||||
margin-right: 0.5em;
|
||||
font-size: 82%;
|
||||
padding: .2em .25em;
|
||||
padding: 0.2em 0.25em;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -51,6 +51,8 @@
|
|||
}
|
||||
|
||||
.guide-channelTimeslotHeader {
|
||||
border: 0 !important;
|
||||
border-right-color: transparent;
|
||||
flex-shrink: 0;
|
||||
justify-content: center;
|
||||
}
|
||||
|
@ -69,9 +71,14 @@
|
|||
}
|
||||
|
||||
.channelPrograms {
|
||||
height: 4.42em;
|
||||
contain: strict;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-style: solid;
|
||||
border-width: 1px 0 1px 0;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
contain: strict;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
@ -80,31 +87,32 @@
|
|||
}
|
||||
|
||||
.guideSpacer {
|
||||
width: .3em;
|
||||
width: 0.3em;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.channelPrograms, .timeslotHeadersInner {
|
||||
.channelPrograms,
|
||||
.timeslotHeadersInner {
|
||||
width: 1800vw;
|
||||
}
|
||||
|
||||
@media all and (min-width: 37.5em) {
|
||||
|
||||
.channelPrograms, .timeslotHeadersInner {
|
||||
.channelPrograms,
|
||||
.timeslotHeadersInner {
|
||||
width: 1400vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 50em) {
|
||||
|
||||
.channelPrograms, .timeslotHeadersInner {
|
||||
.channelPrograms,
|
||||
.timeslotHeadersInner {
|
||||
width: 1200vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 80em) {
|
||||
|
||||
.channelPrograms, .timeslotHeadersInner {
|
||||
.channelPrograms,
|
||||
.timeslotHeadersInner {
|
||||
width: 810vw;
|
||||
}
|
||||
}
|
||||
|
@ -112,11 +120,17 @@
|
|||
.timeslotHeader {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
text-indent: .25em;
|
||||
text-indent: 0.25em;
|
||||
width: 2.0833333333333333333333333333333%;
|
||||
}
|
||||
|
||||
.guide-channelHeaderCell, .guide-channelTimeslotHeader {
|
||||
.programCell,
|
||||
.guide-channelHeaderCell {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.guide-channelHeaderCell,
|
||||
.guide-channelTimeslotHeader {
|
||||
padding: 0 !important;
|
||||
cursor: pointer;
|
||||
outline: none !important;
|
||||
|
@ -130,11 +144,12 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
|
||||
/* Needed in firefox */
|
||||
text-align: left;
|
||||
contain: strict;
|
||||
flex-shrink: 0;
|
||||
border-radius: .12em;
|
||||
border-radius: 0.12em;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
|
@ -148,37 +163,38 @@
|
|||
background: transparent;
|
||||
}
|
||||
|
||||
.guide-channelTimeslotHeader {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
/* Important - have to put the fixed width on channelsContainer, not the individual channelHeaderCell
|
||||
This was causing channelsContainer to extend beyond the fixed width on ps4, tizen, lg and opera tv.
|
||||
*/
|
||||
.channelsContainer, .guide-channelTimeslotHeader {
|
||||
.channelsContainer,
|
||||
.guide-channelTimeslotHeader {
|
||||
width: 24vw;
|
||||
}
|
||||
|
||||
@media all and (min-width:31.25em) {
|
||||
.channelsContainer, .guide-channelTimeslotHeader {
|
||||
@media all and (min-width: 31.25em) {
|
||||
.channelsContainer,
|
||||
.guide-channelTimeslotHeader {
|
||||
width: 16vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width:37.5em) {
|
||||
.channelsContainer, .guide-channelTimeslotHeader {
|
||||
@media all and (min-width: 37.5em) {
|
||||
.channelsContainer,
|
||||
.guide-channelTimeslotHeader {
|
||||
width: 16vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width:50em) {
|
||||
.channelsContainer, .guide-channelTimeslotHeader {
|
||||
@media all and (min-width: 50em) {
|
||||
.channelsContainer,
|
||||
.guide-channelTimeslotHeader {
|
||||
width: 14vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width:80em) {
|
||||
.channelsContainer, .guide-channelTimeslotHeader {
|
||||
@media all and (min-width: 80em) {
|
||||
.channelsContainer,
|
||||
.guide-channelTimeslotHeader {
|
||||
width: 12vw;
|
||||
}
|
||||
}
|
||||
|
@ -197,34 +213,26 @@
|
|||
}
|
||||
|
||||
@media all and (max-width: 50em) {
|
||||
|
||||
.newTvProgram, .liveTvProgram, .premiereTvProgram, .guideHdIcon {
|
||||
.newTvProgram,
|
||||
.liveTvProgram,
|
||||
.premiereTvProgram,
|
||||
.guideHdIcon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.channelPrograms {
|
||||
height: 4.42em;
|
||||
contain: strict;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-style: solid;
|
||||
border-width: 1px 0 1px 0;
|
||||
.channelPrograms + .channelPrograms,
|
||||
.guide-channelHeaderCell + .guide-channelHeaderCell {
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.channelPrograms + .channelPrograms, .guide-channelHeaderCell + .guide-channelHeaderCell {
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.channelPrograms-tv, .guide-channelHeaderCell-tv {
|
||||
.channelPrograms-tv,
|
||||
.guide-channelHeaderCell-tv {
|
||||
height: 3em;
|
||||
}
|
||||
|
||||
.guide-channelTimeslotHeader {
|
||||
border-right-color: transparent;
|
||||
}
|
||||
|
||||
.guide-channelTimeslotHeader, .timeslotHeader {
|
||||
.guide-channelTimeslotHeader,
|
||||
.timeslotHeader {
|
||||
background: transparent !important;
|
||||
height: 2.8em;
|
||||
}
|
||||
|
@ -253,6 +261,7 @@
|
|||
text-decoration: none;
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
|
||||
/* Needed for Firefox */
|
||||
text-align: left;
|
||||
contain: strict;
|
||||
|
@ -261,7 +270,7 @@
|
|||
}
|
||||
|
||||
.guideProgramName {
|
||||
padding: 0 .7em 0;
|
||||
padding: 0 0.7em 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
align-items: center;
|
||||
|
@ -269,7 +278,8 @@
|
|||
position: relative;
|
||||
flex-grow: 1;
|
||||
contain: layout style paint;
|
||||
/*transition: transform 60ms ease-out;*/
|
||||
|
||||
/* transition: transform 60ms ease-out; */
|
||||
}
|
||||
|
||||
.guide-programNameCaret {
|
||||
|
@ -289,11 +299,11 @@
|
|||
.guideProgramSecondaryInfo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: .1em;
|
||||
margin-top: 0.1em;
|
||||
}
|
||||
|
||||
.programIcon {
|
||||
margin-left: .5em;
|
||||
margin-left: 0.5em;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
font-size: 1.6em;
|
||||
|
@ -304,16 +314,16 @@
|
|||
|
||||
.guide-programTextIcon {
|
||||
font-weight: bold;
|
||||
font-size: .9em;
|
||||
padding: .16em .3em;
|
||||
border-radius: .25em;
|
||||
margin-right: .35em;
|
||||
font-size: 0.9em;
|
||||
padding: 0.16em 0.3em;
|
||||
border-radius: 0.25em;
|
||||
margin-right: 0.35em;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.guide-programTextIcon-tv {
|
||||
font-size: .74em;
|
||||
font-size: 0.74em;
|
||||
}
|
||||
|
||||
.guideChannelNumber {
|
||||
|
@ -345,14 +355,12 @@
|
|||
}
|
||||
|
||||
@media all and (min-width: 62.5em) {
|
||||
|
||||
.guideChannelName {
|
||||
max-width: 40%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 62.5em) {
|
||||
|
||||
.guideChannelNumber {
|
||||
display: none;
|
||||
}
|
||||
|
@ -368,21 +376,19 @@
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
.channelsContainer, .programGrid {
|
||||
.channelsContainer,
|
||||
.programGrid {
|
||||
contain: layout style paint;
|
||||
}
|
||||
|
||||
.programCell, .guide-channelHeaderCell {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.timerIcon, .seriesTimerIcon {
|
||||
color: #cc3333 !important;
|
||||
.timerIcon,
|
||||
.seriesTimerIcon {
|
||||
color: #c33 !important;
|
||||
}
|
||||
|
||||
.seriesTimerIcon-inactive {
|
||||
color: inherit !important;
|
||||
opacity: .7;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.guideOptions {
|
||||
|
@ -392,7 +398,6 @@
|
|||
}
|
||||
|
||||
@media all and (max-width: 50em), all and (max-height: 37.5em) {
|
||||
|
||||
.tvGuideHeader {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
@ -415,16 +420,16 @@
|
|||
}
|
||||
|
||||
.guide-date-tab-button {
|
||||
padding: .3em .7em !important;
|
||||
margin: 0 .3em !important;
|
||||
padding: 0.3em 0.7em !important;
|
||||
margin: 0 0.3em !important;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.guide-date-tab-button.emby-tab-button-active {
|
||||
border-color: transparent !important;
|
||||
}
|
||||
.guide-date-tab-button.emby-tab-button-active {
|
||||
border-color: transparent !important;
|
||||
}
|
||||
|
||||
.guide-date-tab-button.show-focus:focus {
|
||||
border-radius: .15em !important;
|
||||
transform: none !important;
|
||||
}
|
||||
.guide-date-tab-button.show-focus:focus {
|
||||
border-radius: 0.15em !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', 'scrollHelper', 'serverNotifications', 'loading', 'datetime', 'focusManager', 'playbackManager', 'userSettings', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'dom', 'css!./guide.css', 'programStyles', 'material-icons', 'scrollStyles', 'emby-button', 'paper-icon-button-light', 'emby-tabs', 'emby-scroller', 'flexStyles', 'registerElement'], function (require, inputManager, browser, globalize, connectionManager, scrollHelper, serverNotifications, loading, datetime, focusManager, playbackManager, userSettings, imageLoader, events, layoutManager, itemShortcuts, dom) {
|
||||
define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', 'scrollHelper', 'serverNotifications', 'loading', 'datetime', 'focusManager', 'playbackManager', 'userSettings', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'dom', 'css!./guide.css', 'programStyles', 'material-icons', 'scrollStyles', 'emby-programcell', 'emby-button', 'paper-icon-button-light', 'emby-tabs', 'emby-scroller', 'flexStyles', 'registerElement'], function (require, inputManager, browser, globalize, connectionManager, scrollHelper, serverNotifications, loading, datetime, focusManager, playbackManager, userSettings, imageLoader, events, layoutManager, itemShortcuts, dom) {
|
||||
'use strict';
|
||||
|
||||
function showViewSettings(instance) {
|
||||
|
@ -29,7 +29,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
var offset = newPct - left;
|
||||
var pctOfWidth = (offset / width) * 100;
|
||||
|
||||
//console.log(pctOfWidth);
|
||||
var guideProgramName = cell.guideProgramName;
|
||||
if (!guideProgramName) {
|
||||
guideProgramName = cell.querySelector('.guideProgramName');
|
||||
|
@ -228,7 +227,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
channelQuery.Limit = channelLimit;
|
||||
channelQuery.AddCurrentProgram = false;
|
||||
channelQuery.EnableUserData = false;
|
||||
channelQuery.EnableImageTypes = "Primary";
|
||||
channelQuery.EnableImageTypes = 'Primary';
|
||||
|
||||
var categories = self.categoryOptions.categories || [];
|
||||
var displayMovieContent = !categories.length || categories.indexOf('movies') !== -1;
|
||||
|
@ -262,8 +261,8 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
}
|
||||
|
||||
if (userSettings.get('livetv-channelorder') === 'DatePlayed') {
|
||||
channelQuery.SortBy = "DatePlayed";
|
||||
channelQuery.SortOrder = "Descending";
|
||||
channelQuery.SortBy = 'DatePlayed';
|
||||
channelQuery.SortOrder = 'Descending';
|
||||
} else {
|
||||
channelQuery.SortBy = null;
|
||||
channelQuery.SortOrder = null;
|
||||
|
@ -330,7 +329,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
ImageTypeLimit: 1,
|
||||
EnableImages: false,
|
||||
//EnableImageTypes: layoutManager.tv ? "Primary,Backdrop" : "Primary",
|
||||
SortBy: "StartDate",
|
||||
SortBy: 'StartDate',
|
||||
EnableTotalRecordCount: false,
|
||||
EnableUserData: false
|
||||
};
|
||||
|
@ -396,7 +395,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
try {
|
||||
program.StartDateLocal = datetime.parseISO8601Date(program.StartDate, { toLocal: true });
|
||||
} catch (err) {
|
||||
console.log('error parsing timestamp for start date');
|
||||
console.error('error parsing timestamp for start date');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,7 +403,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
try {
|
||||
program.EndDateLocal = datetime.parseISO8601Date(program.EndDate, { toLocal: true });
|
||||
} catch (err) {
|
||||
console.log('error parsing timestamp for end date');
|
||||
console.error('error parsing timestamp for end date');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -416,7 +415,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
var status;
|
||||
|
||||
if (item.Type === 'SeriesTimer') {
|
||||
return '<i class="md-icon programIcon seriesTimerIcon">fiber_smart_record</i>';
|
||||
return '<span class="material-icons programIcon seriesTimerIcon fiber_smart_record"></span>';
|
||||
} else if (item.TimerId || item.SeriesTimerId) {
|
||||
|
||||
status = item.Status || 'Cancelled';
|
||||
|
@ -430,13 +429,13 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
if (item.SeriesTimerId) {
|
||||
|
||||
if (status !== 'Cancelled') {
|
||||
return '<i class="md-icon programIcon seriesTimerIcon">fiber_smart_record</i>';
|
||||
return '<span class="material-icons programIcon seriesTimerIcon fiber_smart_record"></span>';
|
||||
}
|
||||
|
||||
return '<i class="md-icon programIcon seriesTimerIcon seriesTimerIcon-inactive">fiber_smart_record</i>';
|
||||
return '<span class="material-icons programIcon seriesTimerIcon seriesTimerIcon-inactive fiber_smart_record"></span>';
|
||||
}
|
||||
|
||||
return '<i class="md-icon programIcon timerIcon">fiber_manual_record</i>';
|
||||
return '<span class="material-icons programIcon timerIcon fiber_manual_record"></span>';
|
||||
}
|
||||
|
||||
function getChannelProgramsHtml(context, date, channel, programs, options, listInfo) {
|
||||
|
@ -503,7 +502,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
var endPercent = (renderEndMs - renderStartMs) / msPerDay;
|
||||
endPercent *= 100;
|
||||
|
||||
var cssClass = "programCell itemAction";
|
||||
var cssClass = 'programCell itemAction';
|
||||
var accentCssClass = null;
|
||||
var displayInnerContent = true;
|
||||
|
||||
|
@ -526,11 +525,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
}
|
||||
|
||||
if (displayInnerContent && enableColorCodedBackgrounds && accentCssClass) {
|
||||
cssClass += " programCell-" + accentCssClass;
|
||||
cssClass += ' programCell-' + accentCssClass;
|
||||
}
|
||||
|
||||
if (now >= startDateLocalMs && now < endDateLocalMs) {
|
||||
cssClass += " programCell-active";
|
||||
cssClass += ' programCell-active';
|
||||
}
|
||||
|
||||
var timerAttributes = '';
|
||||
|
@ -546,11 +545,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
html += '<button' + isAttribute + ' data-action="' + clickAction + '"' + timerAttributes + ' data-channelid="' + program.ChannelId + '" data-id="' + program.Id + '" data-serverid="' + program.ServerId + '" data-startdate="' + program.StartDate + '" data-enddate="' + program.EndDate + '" data-type="' + program.Type + '" class="' + cssClass + '" style="left:' + startPercent + '%;width:' + endPercent + '%;">';
|
||||
|
||||
if (displayInnerContent) {
|
||||
var guideProgramNameClass = "guideProgramName";
|
||||
var guideProgramNameClass = 'guideProgramName';
|
||||
|
||||
html += '<div class="' + guideProgramNameClass + '">';
|
||||
|
||||
html += '<div class="guide-programNameCaret hide"><i class="guideProgramNameCaretIcon md-icon">keyboard_arrow_left</i></div>';
|
||||
html += '<div class="guide-programNameCaret hide"><span class="guideProgramNameCaretIcon material-icons keyboard_arrow_left"></span></div>';
|
||||
|
||||
html += '<div class="guideProgramNameText">' + program.Name;
|
||||
|
||||
|
@ -578,7 +577,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
html += '</div>';
|
||||
|
||||
if (program.IsHD && options.showHdIcon) {
|
||||
//html += '<i class="guideHdIcon md-icon programIcon">hd</i>';
|
||||
//html += '<span class="guideHdIcon material-icons programIcon hd"></span>';
|
||||
if (layoutManager.tv) {
|
||||
html += '<div class="programIcon guide-programTextIcon guide-programTextIcon-tv">HD</div>';
|
||||
} else {
|
||||
|
@ -631,7 +630,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
var url = apiClient.getScaledImageUrl(channel.Id, {
|
||||
maxHeight: 220,
|
||||
tag: channel.ImageTags.Primary,
|
||||
type: "Primary"
|
||||
type: 'Primary'
|
||||
});
|
||||
|
||||
html += '<div class="guideChannelImage lazy" data-src="' + url + '"></div>';
|
||||
|
@ -1106,7 +1105,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
|
||||
var icon = cell.querySelector('.timerIcon');
|
||||
if (!icon) {
|
||||
cell.querySelector('.guideProgramName').insertAdjacentHTML('beforeend', '<i class="timerIcon md-icon programIcon">fiber_manual_record</i>');
|
||||
cell.querySelector('.guideProgramName').insertAdjacentHTML('beforeend', '<span class="timerIcon material-icons programIcon fiber_manual_record"></span>');
|
||||
}
|
||||
|
||||
if (newTimerId) {
|
||||
|
@ -1253,18 +1252,5 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
|||
});
|
||||
}
|
||||
|
||||
var ProgramCellPrototype = Object.create(HTMLButtonElement.prototype);
|
||||
|
||||
ProgramCellPrototype.detachedCallback = function () {
|
||||
this.posLeft = null;
|
||||
this.posWidth = null;
|
||||
this.guideProgramName = null;
|
||||
};
|
||||
|
||||
document.registerElement('emby-programcell', {
|
||||
prototype: ProgramCellPrototype,
|
||||
extends: 'button'
|
||||
});
|
||||
|
||||
return Guide;
|
||||
});
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
.newTvProgram {
|
||||
background: #3388cc;
|
||||
background: #38c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.liveTvProgram {
|
||||
background: #cc3333;
|
||||
background: #c33;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.premiereTvProgram {
|
||||
background: #EF6C00;
|
||||
background: #ef6c00;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
<div class="guide-headerTimeslots">
|
||||
<div class="guide-channelTimeslotHeader">
|
||||
<button is="paper-icon-button-light" type="button" class="btnGuideViewSettings">
|
||||
<i class="md-icon btnGuideViewSettingsIcon">more_horiz</i>
|
||||
<button is="paper-icon-button-light" type="button" class="btnGuideViewSettings" title="${ButtonMore}">
|
||||
<span class="material-icons btnGuideViewSettingsIcon more_horiz" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="timeslotHeaders scrollX guideScroller"></div>
|
||||
|
@ -29,10 +29,10 @@
|
|||
</div>
|
||||
|
||||
<div class="guideOptions hide">
|
||||
<button is="paper-icon-button-light" type="button" class="btnPreviousPage">
|
||||
<i class="md-icon">arrow_back</i>
|
||||
<button is="paper-icon-button-light" type="button" class="btnPreviousPage" title="${LabelPrevious}">
|
||||
<span class="material-icons arrow_back" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button is="paper-icon-button-light" type="button" class="btnNextPage">
|
||||
<i class="md-icon">arrow_forward</i>
|
||||
<button is="paper-icon-button-light" type="button" class="btnNextPage" title="${LabelNext}">
|
||||
<span class="material-icons arrow_forward" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
.headroom {
|
||||
transition: transform 140ms linear;
|
||||
}
|
||||
|
||||
.headroom--pinned {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.headroom--unpinned:not(.headroomDisabled) {
|
||||
transform: translateY(-100%);
|
||||
}
|
|
@ -1,343 +0,0 @@
|
|||
/*!
|
||||
* headroom.js v0.7.0 - Give your page some headroom. Hide your header until you need it
|
||||
* Copyright (c) 2014 Nick Williams - http://wicky.nillia.ms/headroom.js
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, layoutManager, browser) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/* exported features */
|
||||
|
||||
var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
|
||||
|
||||
/**
|
||||
* Handles debouncing of events via requestAnimationFrame
|
||||
* @see http://www.html5rocks.com/en/tutorials/speed/animations/
|
||||
* @param {Function} callback The callback to handle whichever event
|
||||
*/
|
||||
function Debouncer(callback) {
|
||||
this.callback = callback;
|
||||
this.ticking = false;
|
||||
}
|
||||
Debouncer.prototype = {
|
||||
constructor: Debouncer,
|
||||
|
||||
/**
|
||||
* dispatches the event to the supplied callback
|
||||
* @private
|
||||
*/
|
||||
update: function () {
|
||||
if (this.callback) {
|
||||
this.callback();
|
||||
}
|
||||
this.ticking = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach this as the event listeners
|
||||
*/
|
||||
handleEvent: function () {
|
||||
if (!this.ticking) {
|
||||
requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this)));
|
||||
this.ticking = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function onHeadroomClearedExternally() {
|
||||
this.state = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* UI enhancement for fixed headers.
|
||||
* Hides header when scrolling down
|
||||
* Shows header when scrolling up
|
||||
* @constructor
|
||||
* @param {DOMElement} elem the header element
|
||||
* @param {Object} options options for the widget
|
||||
*/
|
||||
function Headroom(elems, options) {
|
||||
options = Object.assign(Headroom.options, options || {});
|
||||
|
||||
this.lastKnownScrollY = 0;
|
||||
this.elems = elems;
|
||||
|
||||
this.scroller = options.scroller;
|
||||
|
||||
this.debouncer = onScroll.bind(this);
|
||||
this.offset = options.offset;
|
||||
this.initialised = false;
|
||||
|
||||
this.initialClass = options.initialClass;
|
||||
this.unPinnedClass = options.unPinnedClass;
|
||||
this.pinnedClass = options.pinnedClass;
|
||||
|
||||
this.state = 'clear';
|
||||
|
||||
this.options = {
|
||||
offset: 0,
|
||||
scroller: window,
|
||||
initialClass: 'headroom',
|
||||
unPinnedClass: 'headroom--unpinned',
|
||||
pinnedClass: 'headroom--pinned'
|
||||
};
|
||||
|
||||
this.add = function (elem) {
|
||||
|
||||
if (browser.supportsCssAnimation()) {
|
||||
elem.classList.add(this.initialClass);
|
||||
elem.addEventListener('clearheadroom', onHeadroomClearedExternally.bind(this));
|
||||
this.elems.push(elem);
|
||||
}
|
||||
};
|
||||
|
||||
this.remove = function (elem) {
|
||||
|
||||
elem.classList.remove(this.unPinnedClass);
|
||||
elem.classList.remove(this.initialClass);
|
||||
elem.classList.remove(this.pinnedClass);
|
||||
|
||||
var i = this.elems.indexOf(elem);
|
||||
if (i !== -1) {
|
||||
this.elems.splice(i, 1);
|
||||
}
|
||||
};
|
||||
|
||||
this.pause = function () {
|
||||
this.paused = true;
|
||||
};
|
||||
|
||||
this.resume = function () {
|
||||
this.paused = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Unattaches events and removes any classes that were added
|
||||
*/
|
||||
this.destroy = function () {
|
||||
|
||||
this.initialised = false;
|
||||
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
|
||||
var classList = this.elems[i].classList;
|
||||
|
||||
classList.remove(this.unPinnedClass);
|
||||
classList.remove(this.initialClass);
|
||||
classList.remove(this.pinnedClass);
|
||||
}
|
||||
|
||||
var scrollEventName = this.scroller.getScrollEventName ? this.scroller.getScrollEventName() : 'scroll';
|
||||
|
||||
dom.removeEventListener(this.scroller, scrollEventName, this.debouncer, {
|
||||
capture: false,
|
||||
passive: true
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaches the scroll event
|
||||
* @private
|
||||
*/
|
||||
this.attachEvent = function () {
|
||||
if (!this.initialised) {
|
||||
this.lastKnownScrollY = this.getScrollY();
|
||||
this.initialised = true;
|
||||
|
||||
var scrollEventName = this.scroller.getScrollEventName ? this.scroller.getScrollEventName() : 'scroll';
|
||||
|
||||
dom.addEventListener(this.scroller, scrollEventName, this.debouncer, {
|
||||
capture: false,
|
||||
passive: true
|
||||
});
|
||||
|
||||
this.update();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Unpins the header if it's currently pinned
|
||||
*/
|
||||
this.clear = function () {
|
||||
|
||||
if (this.state === 'clear') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = 'clear';
|
||||
|
||||
var unpinnedClass = this.unPinnedClass;
|
||||
var pinnedClass = this.pinnedClass;
|
||||
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
var classList = this.elems[i].classList;
|
||||
|
||||
classList.remove(unpinnedClass);
|
||||
//classList.remove(pinnedClass);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Unpins the header if it's currently pinned
|
||||
*/
|
||||
this.pin = function () {
|
||||
|
||||
if (this.state === 'pin') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = 'pin';
|
||||
|
||||
var unpinnedClass = this.unPinnedClass;
|
||||
var pinnedClass = this.pinnedClass;
|
||||
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
var classList = this.elems[i].classList;
|
||||
|
||||
classList.remove(unpinnedClass);
|
||||
classList.add(pinnedClass);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Unpins the header if it's currently pinned
|
||||
*/
|
||||
this.unpin = function () {
|
||||
|
||||
if (this.state === 'unpin') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = 'unpin';
|
||||
|
||||
var unpinnedClass = this.unPinnedClass;
|
||||
var pinnedClass = this.pinnedClass;
|
||||
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
var classList = this.elems[i].classList;
|
||||
|
||||
classList.add(unpinnedClass);
|
||||
//classList.remove(pinnedClass);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the Y scroll position
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY
|
||||
* @return {Number} pixels the page has scrolled along the Y-axis
|
||||
*/
|
||||
this.getScrollY = function () {
|
||||
|
||||
var scroller = this.scroller;
|
||||
|
||||
if (scroller.getScrollPosition) {
|
||||
return scroller.getScrollPosition();
|
||||
}
|
||||
|
||||
var pageYOffset = scroller.pageYOffset;
|
||||
if (pageYOffset !== undefined) {
|
||||
return pageYOffset;
|
||||
}
|
||||
|
||||
var scrollTop = scroller.scrollTop;
|
||||
if (scrollTop !== undefined) {
|
||||
return scrollTop;
|
||||
}
|
||||
|
||||
return (document.documentElement || document.body).scrollTop;
|
||||
};
|
||||
|
||||
/**
|
||||
* determine if it is appropriate to unpin
|
||||
* @param {int} currentScrollY the current y scroll position
|
||||
* @return {bool} true if should unpin, false otherwise
|
||||
*/
|
||||
this.shouldUnpin = function (currentScrollY) {
|
||||
var scrollingDown = currentScrollY > this.lastKnownScrollY;
|
||||
var pastOffset = currentScrollY >= this.offset;
|
||||
|
||||
return scrollingDown && pastOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* determine if it is appropriate to pin
|
||||
* @param {int} currentScrollY the current y scroll position
|
||||
* @return {bool} true if should pin, false otherwise
|
||||
*/
|
||||
this.shouldPin = function (currentScrollY) {
|
||||
var scrollingUp = currentScrollY < this.lastKnownScrollY;
|
||||
var pastOffset = currentScrollY <= this.offset;
|
||||
|
||||
return scrollingUp || pastOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles updating the state of the widget
|
||||
*/
|
||||
this.update = function () {
|
||||
|
||||
if (this.paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
var currentScrollY = this.getScrollY();
|
||||
|
||||
var lastKnownScrollY = this.lastKnownScrollY;
|
||||
|
||||
var isTv = layoutManager.tv;
|
||||
|
||||
if (currentScrollY <= (isTv ? 120 : 10)) {
|
||||
this.clear();
|
||||
} else if (this.shouldUnpin(currentScrollY)) {
|
||||
this.unpin();
|
||||
} else if (this.shouldPin(currentScrollY)) {
|
||||
|
||||
var toleranceExceeded = Math.abs(currentScrollY - lastKnownScrollY) >= 14;
|
||||
|
||||
if (currentScrollY && isTv) {
|
||||
this.unpin();
|
||||
} else if (toleranceExceeded) {
|
||||
this.clear();
|
||||
}
|
||||
} else if (isTv) {
|
||||
//this.clear();
|
||||
}
|
||||
|
||||
this.lastKnownScrollY = currentScrollY;
|
||||
};
|
||||
|
||||
if (browser.supportsCssAnimation()) {
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
this.elems[i].classList.add(this.initialClass);
|
||||
this.elems[i].addEventListener('clearheadroom', onHeadroomClearedExternally.bind(this));
|
||||
}
|
||||
|
||||
this.attachEvent();
|
||||
}
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
|
||||
if (this.paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default options
|
||||
* @type {Object}
|
||||
*/
|
||||
Headroom.options = {
|
||||
offset: 0,
|
||||
scroller: window,
|
||||
initialClass: 'headroom',
|
||||
unPinnedClass: 'headroom--unpinned',
|
||||
pinnedClass: 'headroom--pinned'
|
||||
};
|
||||
|
||||
return Headroom;
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loading', 'connectionManager', 'homeSections', 'dom', 'events', 'listViewStyle', 'emby-select', 'emby-checkbox'], function (require, appHost, layoutManager, focusManager, globalize, loading, connectionManager, homeSections, dom, events) {
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var numConfigurableSections = 7;
|
||||
|
||||
|
@ -149,7 +149,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
|||
|
||||
currentHtml += '<div class="listItem viewItem" data-viewid="' + view.Id + '">';
|
||||
|
||||
currentHtml += '<i class="md-icon listItemIcon">folder_open</i>';
|
||||
currentHtml += '<span class="material-icons listItemIcon folder_open"></span>';
|
||||
|
||||
currentHtml += '<div class="listItemBody">';
|
||||
|
||||
|
@ -159,8 +159,8 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
|||
|
||||
currentHtml += '</div>';
|
||||
|
||||
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemUp btnViewItemMove autoSize" title="' + globalize.translate('Up') + '"><i class="md-icon">keyboard_arrow_up</i></button>';
|
||||
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemDown btnViewItemMove autoSize" title="' + globalize.translate('Down') + '"><i class="md-icon">keyboard_arrow_down</i></button>';
|
||||
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemUp btnViewItemMove autoSize" title="' + globalize.translate('Up') + '"><span class="material-icons keyboard_arrow_up"></span></button>';
|
||||
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemDown btnViewItemMove autoSize" title="' + globalize.translate('Down') + '"><span class="material-icons keyboard_arrow_down"></span></button>';
|
||||
|
||||
currentHtml += '</div>';
|
||||
|
||||
|
@ -276,7 +276,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
|||
updateHomeSectionValues(context, userSettings);
|
||||
|
||||
var promise1 = apiClient.getUserViews({ IncludeHidden: true }, user.Id);
|
||||
var promise2 = apiClient.getJSON(apiClient.getUrl("Users/" + user.Id + "/GroupingOptions"));
|
||||
var promise2 = apiClient.getJSON(apiClient.getUrl('Users/' + user.Id + '/GroupingOptions'));
|
||||
|
||||
Promise.all([promise1, promise2]).then(function (responses) {
|
||||
|
||||
|
@ -363,17 +363,17 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
|||
|
||||
user.Configuration.HidePlayedInLatest = context.querySelector('.chkHidePlayedFromLatest').checked;
|
||||
|
||||
user.Configuration.LatestItemsExcludes = getCheckboxItems(".chkIncludeInLatest", context, false).map(function (i) {
|
||||
user.Configuration.LatestItemsExcludes = getCheckboxItems('.chkIncludeInLatest', context, false).map(function (i) {
|
||||
|
||||
return i.getAttribute('data-folderid');
|
||||
});
|
||||
|
||||
user.Configuration.MyMediaExcludes = getCheckboxItems(".chkIncludeInMyMedia", context, false).map(function (i) {
|
||||
user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(function (i) {
|
||||
|
||||
return i.getAttribute('data-folderid');
|
||||
});
|
||||
|
||||
user.Configuration.GroupedFolders = getCheckboxItems(".chkGroupFolder", context, true).map(function (i) {
|
||||
user.Configuration.GroupedFolders = getCheckboxItems('.chkGroupFolder', context, true).map(function (i) {
|
||||
|
||||
return i.getAttribute('data-folderid');
|
||||
});
|
||||
|
|
|
@ -10,6 +10,13 @@
|
|||
<div class="fieldDescription">${LabelPleaseRestart}</div>
|
||||
</div>
|
||||
|
||||
<div class="verticalSection verticalSection-extrabottompadding">
|
||||
<label class="checkboxContainer">
|
||||
<input class="chkHidePlayedFromLatest" type="checkbox" is="emby-checkbox" />
|
||||
<span>${HideWatchedContentFromLatestMedia}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="selectContainer">
|
||||
<select is="emby-select" id="selectHomeSection1" label="{section1label}">
|
||||
<option value="smalllibrarytiles">${HeaderMyMedia}</option>
|
||||
|
@ -110,13 +117,6 @@
|
|||
|
||||
<div class="perLibrarySettings"></div>
|
||||
|
||||
<div class="verticalSection verticalSection-extrabottompadding">
|
||||
<label class="checkboxContainer">
|
||||
<input class="chkHidePlayedFromLatest" type="checkbox" is="emby-checkbox" />
|
||||
<span>${HideWatchedContentFromLatestMedia}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="verticalSection verticalSection-extrabottompadding">
|
||||
<h2 class="sectionTitle">${HeaderLibraryFolders}</h2>
|
||||
<div>
|
||||
|
@ -129,4 +129,4 @@
|
|||
<button is="emby-button" type="submit" class="raised button-submit block btnSave hide">
|
||||
<span>${Save}</span>
|
||||
</button>
|
||||
</form>
|
||||
</form>
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
.homeLibraryButton {
|
||||
min-width: 18%;
|
||||
margin: .5em !important;
|
||||
margin: 0.5em !important;
|
||||
}
|
||||
|
||||
@media all and (max-width: 50em) {
|
||||
|
||||
.homeLibraryButton {
|
||||
width: 46% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.homeLibraryIcon {
|
||||
margin-left: .5em;
|
||||
margin-right: .5em;
|
||||
flex-shrink: 0
|
||||
margin-left: 0.5em;
|
||||
margin-right: 0.5em;
|
||||
-webkit-flex-shrink: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.homeLibraryText {
|
||||
white-space: nowrap;
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
|
@ -40,26 +40,48 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
return getUserViews(apiClient, user.Id).then(function (userViews) {
|
||||
var html = '';
|
||||
|
||||
var sectionCount = 7;
|
||||
for (var i = 0; i < sectionCount; i++) {
|
||||
html += '<div class="verticalSection section' + i + '"></div>';
|
||||
}
|
||||
if (userViews.length) {
|
||||
var sectionCount = 7;
|
||||
for (var i = 0; i < sectionCount; i++) {
|
||||
html += '<div class="verticalSection section' + i + '"></div>';
|
||||
}
|
||||
|
||||
elem.innerHTML = html;
|
||||
elem.classList.add('homeSectionsContainer');
|
||||
elem.innerHTML = html;
|
||||
elem.classList.add('homeSectionsContainer');
|
||||
|
||||
var promises = [];
|
||||
var sections = getAllSectionsToShow(userSettings, sectionCount);
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
promises.push(loadSection(elem, apiClient, user, userSettings, userViews, sections, i));
|
||||
}
|
||||
var promises = [];
|
||||
var sections = getAllSectionsToShow(userSettings, sectionCount);
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
promises.push(loadSection(elem, apiClient, user, userSettings, userViews, sections, i));
|
||||
}
|
||||
|
||||
return Promise.all(promises).then(function () {
|
||||
return resume(elem, {
|
||||
refresh: true,
|
||||
returnPromise: false
|
||||
return Promise.all(promises).then(function () {
|
||||
return resume(elem, {
|
||||
refresh: true,
|
||||
returnPromise: false
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
var noLibDescription;
|
||||
if (user['Policy'] && user['Policy']['IsAdministrator']) {
|
||||
noLibDescription = globalize.translate('NoCreatedLibraries', '<br><a id="button-createLibrary" class="button-link">', '</a>');
|
||||
} else {
|
||||
noLibDescription = globalize.translate('AskAdminToCreateLibrary');
|
||||
}
|
||||
|
||||
html += '<div class="centerMessage padded-left padded-right">';
|
||||
html += '<h2>' + globalize.translate('MessageNothingHere') + '</h2>';
|
||||
html += '<p>' + noLibDescription + '</p>';
|
||||
html += '</div>';
|
||||
elem.innerHTML = html;
|
||||
|
||||
var createNowLink = elem.querySelector('#button-createLibrary');
|
||||
if (createNowLink) {
|
||||
createNowLink.addEventListener('click', function () {
|
||||
Dashboard.navigate('library.html');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -109,7 +131,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
} else if (section === 'librarytiles' || section === 'smalllibrarytiles' || section === 'smalllibrarytiles-automobile' || section === 'librarytiles-automobile') {
|
||||
loadLibraryTiles(elem, apiClient, user, userSettings, 'smallBackdrop', userViews, allSections);
|
||||
} else if (section === 'librarybuttons') {
|
||||
loadlibraryButtons(elem, apiClient, user, userSettings, userViews, allSections);
|
||||
loadlibraryButtons(elem, apiClient, user, userSettings, userViews);
|
||||
} else if (section === 'resume') {
|
||||
loadResumeVideo(elem, apiClient, userId);
|
||||
} else if (section === 'resumeaudio') {
|
||||
|
@ -150,7 +172,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
}
|
||||
|
||||
function getLibraryButtonsHtml(items) {
|
||||
var html = "";
|
||||
var html = '';
|
||||
|
||||
html += '<div class="verticalSection verticalSection-extrabottompadding">';
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
|
||||
|
@ -161,7 +183,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
for (var i = 0, length = items.length; i < length; i++) {
|
||||
var item = items[i];
|
||||
var icon = imageHelper.getLibraryIcon(item.CollectionType);
|
||||
html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item) + '" class="raised homeLibraryButton"><i class="md-icon homeLibraryIcon">' + icon + '</i><span class="homeLibraryText">' + item.Name + '</span></a>';
|
||||
html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item) + '" class="raised homeLibraryButton"><span class="material-icons homeLibraryIcon ' + icon + '"></span><span class="homeLibraryText">' + item.Name + '</span></a>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
|
@ -207,9 +229,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
|
||||
var options = {
|
||||
Limit: limit,
|
||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Thumb",
|
||||
EnableImageTypes: 'Primary,Backdrop,Thumb',
|
||||
ParentId: parentId
|
||||
};
|
||||
|
||||
|
@ -221,9 +243,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
return function (items) {
|
||||
var cardLayout = false;
|
||||
var shape;
|
||||
if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books') {
|
||||
if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books' || viewType === 'tvshows') {
|
||||
shape = getPortraitShape();
|
||||
} else if (viewType === 'music') {
|
||||
} else if (viewType === 'music' || viewType === 'homevideos') {
|
||||
shape = getSquareShape();
|
||||
} else {
|
||||
shape = getThumbShape();
|
||||
|
@ -260,7 +282,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
||||
html += globalize.translate('LatestFromLibrary', parent.Name);
|
||||
html += '</h2>';
|
||||
html += '<i class="md-icon">chevron_right</i>';
|
||||
html += '<span class="material-icons chevron_right"></span>';
|
||||
html += '</a>';
|
||||
} else {
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('LatestFromLibrary', parent.Name) + '</h2>';
|
||||
|
@ -268,7 +290,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
html += '</div>';
|
||||
|
||||
if (enableScrollX()) {
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">';
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x">';
|
||||
} else {
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer focuscontainer-x padded-left padded-right vertical-wrap">';
|
||||
|
@ -321,7 +343,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
if (userViews.length) {
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
|
||||
if (enableScrollX()) {
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">';
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x">';
|
||||
} else {
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right focuscontainer-x vertical-wrap">';
|
||||
|
@ -364,9 +386,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
var options = {
|
||||
Limit: limit,
|
||||
Recursive: true,
|
||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Thumb",
|
||||
EnableImageTypes: 'Primary,Backdrop,Thumb',
|
||||
EnableTotalRecordCount: false,
|
||||
MediaTypes: 'Video'
|
||||
};
|
||||
|
@ -401,7 +423,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
|
||||
if (enableScrollX()) {
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">';
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x" data-monitor="videoplayback,markplayed">';
|
||||
} else {
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x" data-monitor="videoplayback,markplayed">';
|
||||
|
@ -437,9 +459,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
var options = {
|
||||
Limit: limit,
|
||||
Recursive: true,
|
||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Thumb",
|
||||
EnableImageTypes: 'Primary,Backdrop,Thumb',
|
||||
EnableTotalRecordCount: false,
|
||||
MediaTypes: 'Audio'
|
||||
};
|
||||
|
@ -474,7 +496,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
|
||||
if (enableScrollX()) {
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">';
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x" data-monitor="audioplayback,markplayed">';
|
||||
} else {
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x" data-monitor="audioplayback,markplayed">';
|
||||
|
@ -502,9 +524,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
IsAiring: true,
|
||||
limit: 24,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Thumb,Backdrop",
|
||||
EnableImageTypes: 'Primary,Thumb,Backdrop',
|
||||
EnableTotalRecordCount: false,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio"
|
||||
Fields: 'ChannelInfo,PrimaryImageAspectRatio'
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -543,9 +565,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
IsAiring: true,
|
||||
limit: 1,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Thumb,Backdrop",
|
||||
EnableImageTypes: 'Primary,Thumb,Backdrop',
|
||||
EnableTotalRecordCount: false,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio"
|
||||
Fields: 'ChannelInfo,PrimaryImageAspectRatio'
|
||||
}).then(function (result) {
|
||||
var html = '';
|
||||
if (result.Items.length) {
|
||||
|
@ -560,7 +582,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
html += '</div>';
|
||||
|
||||
if (enableScrollX()) {
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true" data-scrollbuttons="false">';
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true" data-scrollbuttons="false">';
|
||||
html += '<div class="padded-top padded-bottom scrollSlider focuscontainer-x">';
|
||||
} else {
|
||||
html += '<div class="padded-top padded-bottom focuscontainer-x">';
|
||||
|
@ -608,7 +630,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
||||
html += globalize.translate('HeaderOnNow');
|
||||
html += '</h2>';
|
||||
html += '<i class="md-icon">chevron_right</i>';
|
||||
html += '<span class="material-icons chevron_right"></span>';
|
||||
html += '</a>';
|
||||
|
||||
} else {
|
||||
|
@ -617,8 +639,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
html += '</div>';
|
||||
|
||||
if (enableScrollX()) {
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x">'
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">';
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x">';
|
||||
} else {
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x">';
|
||||
}
|
||||
|
@ -645,10 +667,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
return apiClient.getNextUpEpisodes({
|
||||
Limit: enableScrollX() ? 24 : 15,
|
||||
Fields: "PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo",
|
||||
Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo',
|
||||
UserId: apiClient.getCurrentUserId(),
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
|
||||
EnableTotalRecordCount: false
|
||||
});
|
||||
};
|
||||
|
@ -683,7 +705,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
||||
html += globalize.translate('HeaderNextUp');
|
||||
html += '</h2>';
|
||||
html += '<i class="md-icon">chevron_right</i>';
|
||||
html += '<span class="material-icons chevron_right"></span>';
|
||||
html += '</a>';
|
||||
} else {
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('HeaderNextUp') + '</h2>';
|
||||
|
@ -691,8 +713,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
html += '</div>';
|
||||
|
||||
if (enableScrollX()) {
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x" data-monitor="videoplayback,markplayed">'
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">';
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x" data-monitor="videoplayback,markplayed">';
|
||||
} else {
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x" data-monitor="videoplayback,markplayed">';
|
||||
}
|
||||
|
@ -717,7 +739,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
return apiClient.getLiveTvRecordings({
|
||||
userId: apiClient.getCurrentUserId(),
|
||||
Limit: enableScrollX() ? 12 : 5,
|
||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||
EnableTotalRecordCount: false,
|
||||
IsLibraryItem: activeRecordingsOnly ? null : false,
|
||||
IsInProgress: activeRecordingsOnly ? true : null
|
||||
|
@ -763,8 +785,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
|||
html += '</div>';
|
||||
|
||||
if (enableScrollX()) {
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x">'
|
||||
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">';
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x">';
|
||||
} else {
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x">';
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
'use strict';
|
||||
|
||||
function getSavedVolume() {
|
||||
return appSettings.get("volume") || 1;
|
||||
return appSettings.get('volume') || 1;
|
||||
}
|
||||
|
||||
function saveVolume(value) {
|
||||
if (value) {
|
||||
appSettings.set("volume", value);
|
||||
appSettings.set('volume', value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
}
|
||||
|
||||
function enableHlsShakaPlayer(item, mediaSource, mediaType) {
|
||||
|
||||
/* eslint-disable-next-line compat/compat */
|
||||
if (!!window.MediaSource && !!MediaSource.isTypeSupported) {
|
||||
|
||||
if (canPlayNativeHls()) {
|
||||
|
@ -109,17 +109,17 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
var now = Date.now();
|
||||
|
||||
if (window.performance && window.performance.now) {
|
||||
now = performance.now();
|
||||
now = performance.now(); // eslint-disable-line compat/compat
|
||||
}
|
||||
|
||||
if (!recoverDecodingErrorDate || (now - recoverDecodingErrorDate) > 3000) {
|
||||
recoverDecodingErrorDate = now;
|
||||
console.log('try to recover media Error ...');
|
||||
console.debug('try to recover media Error ...');
|
||||
hlsPlayer.recoverMediaError();
|
||||
} else {
|
||||
if (!recoverSwapAudioCodecDate || (now - recoverSwapAudioCodecDate) > 3000) {
|
||||
recoverSwapAudioCodecDate = now;
|
||||
console.log('try to swap Audio Codec and recover media Error ...');
|
||||
console.debug('try to swap Audio Codec and recover media Error ...');
|
||||
hlsPlayer.swapAudioCodec();
|
||||
hlsPlayer.recoverMediaError();
|
||||
} else {
|
||||
|
@ -162,7 +162,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
}
|
||||
}
|
||||
|
||||
function seekOnPlaybackStart(instance, element, ticks) {
|
||||
function seekOnPlaybackStart(instance, element, ticks, onMediaReady) {
|
||||
|
||||
var seconds = (ticks || 0) / 10000000;
|
||||
|
||||
|
@ -171,13 +171,31 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
|
||||
// Appending #t=xxx to the query string doesn't seem to work with HLS
|
||||
// For plain video files, not all browsers support it either
|
||||
var delay = browser.safari ? 2500 : 0;
|
||||
if (delay) {
|
||||
setTimeout(function () {
|
||||
setCurrentTimeIfNeeded(element, seconds);
|
||||
}, delay);
|
||||
} else {
|
||||
|
||||
if (element.duration >= seconds) {
|
||||
// media is ready, seek immediately
|
||||
setCurrentTimeIfNeeded(element, seconds);
|
||||
if (onMediaReady) onMediaReady();
|
||||
} else {
|
||||
// update video player position when media is ready to be sought
|
||||
var events = ['durationchange', 'loadeddata', 'play', 'loadedmetadata'];
|
||||
var onMediaChange = function(e) {
|
||||
if (element.currentTime === 0 && element.duration >= seconds) {
|
||||
// seek only when video position is exactly zero,
|
||||
// as this is true only if video hasn't started yet or
|
||||
// user rewound to the very beginning
|
||||
// (but rewinding cannot happen as the first event with media of non-empty duration)
|
||||
console.debug(`seeking to ${seconds} on ${e.type} event`);
|
||||
setCurrentTimeIfNeeded(element, seconds);
|
||||
events.map(function(name) {
|
||||
element.removeEventListener(name, onMediaChange);
|
||||
});
|
||||
if (onMediaReady) onMediaReady();
|
||||
}
|
||||
};
|
||||
events.map(function (name) {
|
||||
return element.addEventListener(name, onMediaChange);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -233,7 +251,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
return Promise.resolve();
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('error calling video.play: ' + err);
|
||||
console.error('error calling video.play: ' + err);
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
|
@ -245,7 +263,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
try {
|
||||
player.unload();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
instance._castPlayer = null;
|
||||
|
@ -258,7 +276,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
try {
|
||||
player.destroy();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
instance._shakaPlayer = null;
|
||||
|
@ -271,7 +289,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
try {
|
||||
player.destroy();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
instance._hlsPlayer = null;
|
||||
|
@ -286,7 +304,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
player.detachMediaElement();
|
||||
player.destroy();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
instance._flvPlayer = null;
|
||||
|
@ -307,14 +325,14 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
|
||||
hls.on(Hls.Events.ERROR, function (event, data) {
|
||||
|
||||
console.log('HLS Error: Type: ' + data.type + ' Details: ' + (data.details || '') + ' Fatal: ' + (data.fatal || false));
|
||||
console.error('HLS Error: Type: ' + data.type + ' Details: ' + (data.details || '') + ' Fatal: ' + (data.fatal || false));
|
||||
|
||||
switch (data.type) {
|
||||
case Hls.ErrorTypes.NETWORK_ERROR:
|
||||
// try to recover network error
|
||||
if (data.response && data.response.code && data.response.code >= 400) {
|
||||
|
||||
console.log('hls.js response error code: ' + data.response.code);
|
||||
console.debug('hls.js response error code: ' + data.response.code);
|
||||
|
||||
// Trigger failure differently depending on whether this is prior to start of playback, or after
|
||||
hls.destroy();
|
||||
|
@ -343,7 +361,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
|
||||
// This could be a CORS error related to access control response headers
|
||||
|
||||
console.log('hls.js response error code: ' + data.response.code);
|
||||
console.debug('hls.js response error code: ' + data.response.code);
|
||||
|
||||
// Trigger failure differently depending on whether this is prior to start of playback, or after
|
||||
hls.destroy();
|
||||
|
@ -355,20 +373,20 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
onErrorInternal(instance, 'network');
|
||||
}
|
||||
} else {
|
||||
console.log("fatal network error encountered, try to recover");
|
||||
console.debug('fatal network error encountered, try to recover');
|
||||
hls.startLoad();
|
||||
}
|
||||
|
||||
break;
|
||||
case Hls.ErrorTypes.MEDIA_ERROR:
|
||||
console.log("fatal media error encountered, try to recover");
|
||||
console.debug('fatal media error encountered, try to recover');
|
||||
var currentReject = reject;
|
||||
reject = null;
|
||||
handleHlsJsMediaError(instance, currentReject);
|
||||
break;
|
||||
default:
|
||||
|
||||
console.log('Cannot recover from hls error - destroy and trigger error');
|
||||
console.debug('Cannot recover from hls error - destroy and trigger error');
|
||||
// cannot recover
|
||||
// Trigger failure differently depending on whether this is prior to start of playback, or after
|
||||
hls.destroy();
|
||||
|
@ -391,7 +409,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
|
||||
elem.src = '';
|
||||
elem.innerHTML = '';
|
||||
elem.removeAttribute("src");
|
||||
elem.removeAttribute('src');
|
||||
|
||||
destroyHlsPlayer(instance);
|
||||
destroyFlvPlayer(instance);
|
||||
|
@ -463,4 +481,4 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
|||
getCrossOriginValue: getCrossOriginValue,
|
||||
getBufferedRanges: getBufferedRanges
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
define(['events', 'browser', 'require', 'apphost', 'appSettings', 'htmlMediaHelper'], function (events, browser, require, appHost, appSettings, htmlMediaHelper) {
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
function getDefaultProfile() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
@ -16,7 +16,7 @@ define(['events', 'browser', 'require', 'apphost', 'appSettings', 'htmlMediaHelp
|
|||
// Need to record the starting volume on each pass rather than querying elem.volume
|
||||
// This is due to iOS safari not allowing volume changes and always returning the system volume value
|
||||
var newVolume = Math.max(0, startingVolume - 0.15);
|
||||
console.log('fading volume to ' + newVolume);
|
||||
console.debug('fading volume to ' + newVolume);
|
||||
elem.volume = newVolume;
|
||||
|
||||
if (newVolume <= 0) {
|
||||
|
@ -101,7 +101,7 @@ define(['events', 'browser', 'require', 'apphost', 'appSettings', 'htmlMediaHelp
|
|||
self._timeUpdated = false;
|
||||
self._currentTime = null;
|
||||
|
||||
var elem = createMediaElement(options);
|
||||
var elem = createMediaElement();
|
||||
return setCurrentSrc(elem, options);
|
||||
};
|
||||
|
||||
|
@ -113,7 +113,7 @@ define(['events', 'browser', 'require', 'apphost', 'appSettings', 'htmlMediaHelp
|
|||
bindEvents(elem);
|
||||
|
||||
var val = options.url;
|
||||
console.log('playing url: ' + val);
|
||||
console.debug('playing url: ' + val);
|
||||
|
||||
// Convert to seconds
|
||||
var seconds = (options.playerStartPositionTicks || 0) / 10000000;
|
||||
|
@ -298,7 +298,7 @@ define(['events', 'browser', 'require', 'apphost', 'appSettings', 'htmlMediaHelp
|
|||
|
||||
var errorCode = this.error ? (this.error.code || 0) : 0;
|
||||
var errorMessage = this.error ? (this.error.message || '') : '';
|
||||
console.log('Media element error: ' + errorCode.toString() + ' ' + errorMessage);
|
||||
console.error('media element error: ' + errorCode.toString() + ' ' + errorMessage);
|
||||
|
||||
var type;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackManager', 'appRouter', 'appSettings', 'connectionManager', 'htmlMediaHelper', 'itemHelper', 'fullscreenManager'], function (browser, require, events, appHost, loading, dom, playbackManager, appRouter, appSettings, connectionManager, htmlMediaHelper, itemHelper, fullscreenManager) {
|
||||
"use strict";
|
||||
define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackManager', 'appRouter', 'appSettings', 'connectionManager', 'htmlMediaHelper', 'itemHelper', 'screenfull', 'globalize'], function (browser, require, events, appHost, loading, dom, playbackManager, appRouter, appSettings, connectionManager, htmlMediaHelper, itemHelper, screenfull, globalize) {
|
||||
'use strict';
|
||||
/* globals cast */
|
||||
|
||||
var mediaManager;
|
||||
|
||||
|
@ -11,7 +12,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
try {
|
||||
parentNode.removeChild(elem);
|
||||
} catch (err) {
|
||||
console.log('Error removing dialog element: ' + err);
|
||||
console.error('error removing dialog element: ' + err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +80,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
if (track) {
|
||||
var format = (track.Codec || '').toLowerCase();
|
||||
if (format === 'ssa' || format === 'ass') {
|
||||
// libjass is needed here
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -95,23 +95,19 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
}
|
||||
|
||||
function getMediaStreamAudioTracks(mediaSource) {
|
||||
|
||||
return mediaSource.MediaStreams.filter(function (s) {
|
||||
return s.Type === 'Audio';
|
||||
});
|
||||
}
|
||||
|
||||
function getMediaStreamTextTracks(mediaSource) {
|
||||
|
||||
return mediaSource.MediaStreams.filter(function (s) {
|
||||
return s.Type === 'Subtitle';
|
||||
});
|
||||
}
|
||||
|
||||
function zoomIn(elem) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
var duration = 240;
|
||||
elem.style.animation = 'htmlvideoplayer-zoomin ' + duration + 'ms ease-in normal';
|
||||
dom.addEventListener(elem, dom.whichAnimationEvent(), resolve, {
|
||||
|
@ -120,8 +116,9 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
});
|
||||
}
|
||||
|
||||
function normalizeTrackEventText(text) {
|
||||
return text.replace(/\\N/gi, '\n');
|
||||
function normalizeTrackEventText(text, useHtml) {
|
||||
var result = text.replace(/\\N/gi, '\n').replace(/\r/gi, '');
|
||||
return useHtml ? result.replace(/\n/gi, '<br>') : result;
|
||||
}
|
||||
|
||||
function setTracks(elem, tracks, item, mediaSource) {
|
||||
|
@ -215,7 +212,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
function incrementFetchQueue() {
|
||||
if (self._fetchQueue <= 0) {
|
||||
self.isFetching = true;
|
||||
events.trigger(self, "beginFetch");
|
||||
events.trigger(self, 'beginFetch');
|
||||
}
|
||||
|
||||
self._fetchQueue++;
|
||||
|
@ -226,7 +223,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
if (self._fetchQueue <= 0) {
|
||||
self.isFetching = false;
|
||||
events.trigger(self, "endFetch");
|
||||
events.trigger(self, 'endFetch');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,7 +243,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
loading.show();
|
||||
|
||||
console.log('prefetching hls playlist: ' + hlsPlaylistUrl);
|
||||
console.debug('prefetching hls playlist: ' + hlsPlaylistUrl);
|
||||
|
||||
return connectionManager.getApiClient(item.ServerId).ajax({
|
||||
|
||||
|
@ -255,7 +252,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
}).then(function () {
|
||||
|
||||
console.log('completed prefetching hls playlist: ' + hlsPlaylistUrl);
|
||||
console.debug('completed prefetching hls playlist: ' + hlsPlaylistUrl);
|
||||
|
||||
loading.hide();
|
||||
streamInfo.url = hlsPlaylistUrl;
|
||||
|
@ -264,7 +261,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
}, function () {
|
||||
|
||||
console.log('error prefetching hls playlist: ' + hlsPlaylistUrl);
|
||||
console.error('error prefetching hls playlist: ' + hlsPlaylistUrl);
|
||||
|
||||
loading.hide();
|
||||
return Promise.resolve();
|
||||
|
@ -293,7 +290,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
return createMediaElement(options).then(function (elem) {
|
||||
|
||||
return updateVideoUrl(options, options.mediaSource).then(function () {
|
||||
return updateVideoUrl(options).then(function () {
|
||||
return setCurrentSrc(elem, options);
|
||||
});
|
||||
});
|
||||
|
@ -361,6 +358,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
return new Promise(function (resolve, reject) {
|
||||
|
||||
require(['shaka'], function () {
|
||||
/* globals shaka */
|
||||
|
||||
var player = new shaka.Player(elem);
|
||||
|
||||
|
@ -412,7 +410,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
lrd.media.streamType = cast.receiver.media.StreamType.OTHER;
|
||||
lrd.media.customData = options;
|
||||
|
||||
console.log('loading media url into mediaManager');
|
||||
console.debug('loading media url into media manager');
|
||||
|
||||
try {
|
||||
mediaManager.load(lrd);
|
||||
|
@ -422,7 +420,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
return Promise.resolve();
|
||||
} catch (err) {
|
||||
|
||||
console.log('mediaManager error: ' + err);
|
||||
console.debug('media manager error: ' + err);
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
|
@ -464,11 +462,11 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
protocol = cast.player.api.CreateSmoothStreamingProtocol(host);
|
||||
}
|
||||
|
||||
console.log('loading playback url: ' + url);
|
||||
console.log('contentType: ' + contentType);
|
||||
console.debug('loading playback url: ' + url);
|
||||
console.debug('content type: ' + contentType);
|
||||
|
||||
host.onError = function (errorCode) {
|
||||
console.log("Fatal Error - " + errorCode);
|
||||
console.error('fatal Error - ' + errorCode);
|
||||
};
|
||||
|
||||
mediaElement.autoplay = false;
|
||||
|
@ -503,7 +501,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
elem.removeEventListener('error', onError);
|
||||
|
||||
var val = options.url;
|
||||
console.log('playing url: ' + val);
|
||||
console.debug('playing url: ' + val);
|
||||
|
||||
// Convert to seconds
|
||||
var seconds = (options.playerStartPositionTicks || 0) / 10000000;
|
||||
|
@ -570,19 +568,19 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
self.resetSubtitleOffset = function() {
|
||||
currentTrackOffset = 0;
|
||||
showTrackOffset = false;
|
||||
}
|
||||
};
|
||||
|
||||
self.enableShowingSubtitleOffset = function() {
|
||||
showTrackOffset = true;
|
||||
}
|
||||
};
|
||||
|
||||
self.disableShowingSubtitleOffset = function() {
|
||||
showTrackOffset = false;
|
||||
}
|
||||
};
|
||||
|
||||
self.isShowingSubtitleOffsetEnabled = function() {
|
||||
return showTrackOffset;
|
||||
}
|
||||
};
|
||||
|
||||
function getTextTrack() {
|
||||
var videoElement = self._mediaElement;
|
||||
|
@ -602,8 +600,9 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
var offsetValue = parseFloat(offset);
|
||||
|
||||
// if .ass currently rendering
|
||||
if (currentAssRenderer) {
|
||||
if (currentSubtitlesOctopus) {
|
||||
updateCurrentTrackOffset(offsetValue);
|
||||
currentSubtitlesOctopus.timeOffset = (self._currentPlayOptions.transcodingOffsetTicks || 0) / 10000000 + offsetValue;
|
||||
} else {
|
||||
var trackElement = getTextTrack();
|
||||
// if .vtt currently rendering
|
||||
|
@ -612,7 +611,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
} else if (currentTrackEvents) {
|
||||
setTrackEventsSubtitleOffset(currentTrackEvents, offsetValue);
|
||||
} else {
|
||||
console.log("No available track, cannot apply offset: ", offsetValue);
|
||||
console.debug('No available track, cannot apply offset: ', offsetValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -654,7 +653,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
self.getSubtitleOffset = function() {
|
||||
return currentTrackOffset;
|
||||
}
|
||||
};
|
||||
|
||||
function isAudioStreamSupported(stream, deviceProfile) {
|
||||
|
||||
|
@ -731,22 +730,18 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
// https://msdn.microsoft.com/en-us/library/hh772507(v=vs.85).aspx
|
||||
|
||||
var elemAudioTracks = elem.audioTracks || [];
|
||||
console.log('found ' + elemAudioTracks.length + ' audio tracks');
|
||||
console.debug('found ' + elemAudioTracks.length + ' audio tracks');
|
||||
|
||||
for (i = 0, length = elemAudioTracks.length; i < length; i++) {
|
||||
|
||||
if (audioIndex === i) {
|
||||
console.log('setting audio track ' + i + ' to enabled');
|
||||
console.debug('setting audio track ' + i + ' to enabled');
|
||||
elemAudioTracks[i].enabled = true;
|
||||
} else {
|
||||
console.log('setting audio track ' + i + ' to disabled');
|
||||
console.debug('setting audio track ' + i + ' to disabled');
|
||||
elemAudioTracks[i].enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
elem.currentTime = elem.currentTime;
|
||||
}, 100);
|
||||
};
|
||||
|
||||
self.stop = function (destroyPlayer) {
|
||||
|
@ -800,7 +795,9 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
dlg.parentNode.removeChild(dlg);
|
||||
}
|
||||
|
||||
fullscreenManager.exitFullscreen();
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.exit();
|
||||
}
|
||||
};
|
||||
|
||||
function onEnded() {
|
||||
|
@ -862,7 +859,13 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
loading.hide();
|
||||
|
||||
htmlMediaHelper.seekOnPlaybackStart(self, e.target, self._currentPlayOptions.playerStartPositionTicks);
|
||||
htmlMediaHelper.seekOnPlaybackStart(self, e.target, self._currentPlayOptions.playerStartPositionTicks, function () {
|
||||
if (currentSubtitlesOctopus) {
|
||||
currentSubtitlesOctopus.timeOffset = (self._currentPlayOptions.transcodingOffsetTicks || 0) / 10000000 + currentTrackOffset;
|
||||
currentSubtitlesOctopus.resize();
|
||||
currentSubtitlesOctopus.resetRenderAheadCache(false);
|
||||
}
|
||||
});
|
||||
|
||||
if (self._currentPlayOptions.fullscreen) {
|
||||
|
||||
|
@ -915,7 +918,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
function onError() {
|
||||
var errorCode = this.error ? (this.error.code || 0) : 0;
|
||||
var errorMessage = this.error ? (this.error.message || '') : '';
|
||||
console.log('Media element error: ' + errorCode.toString() + ' ' + errorMessage);
|
||||
console.error('media element error: ' + errorCode.toString() + ' ' + errorMessage);
|
||||
|
||||
var type;
|
||||
|
||||
|
@ -1026,7 +1029,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
xhr.onerror = function (e) {
|
||||
reject(e);
|
||||
decrementFetchQueue();
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
});
|
||||
|
@ -1053,97 +1056,39 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
lastCustomTrackMs = 0;
|
||||
}
|
||||
|
||||
function renderWithSubtitlesOctopus(videoElement, track, item) {
|
||||
function renderSsaAss(videoElement, track, item) {
|
||||
var attachments = self._currentPlayOptions.mediaSource.MediaAttachments || [];
|
||||
var apiClient = connectionManager.getApiClient(item);
|
||||
var options = {
|
||||
video: videoElement,
|
||||
subUrl: getTextTrackUrl(track, item),
|
||||
fonts: attachments.map(i => i.DeliveryUrl),
|
||||
workerUrl: appRouter.baseUrl() + "/libraries/subtitles-octopus-worker.js",
|
||||
fonts: attachments.map(function (i) {
|
||||
return apiClient.getUrl(i.DeliveryUrl);
|
||||
}),
|
||||
workerUrl: appRouter.baseUrl() + '/libraries/subtitles-octopus-worker.js',
|
||||
legacyWorkerUrl: appRouter.baseUrl() + '/libraries/subtitles-octopus-worker-legacy.js',
|
||||
onError: function() {
|
||||
htmlMediaHelper.onErrorInternal(self, 'mediadecodeerror')
|
||||
}
|
||||
htmlMediaHelper.onErrorInternal(self, 'mediadecodeerror');
|
||||
},
|
||||
timeOffset: (self._currentPlayOptions.transcodingOffsetTicks || 0) / 10000000,
|
||||
|
||||
// new octopus options; override all, even defaults
|
||||
renderMode: 'blend',
|
||||
dropAllAnimations: false,
|
||||
libassMemoryLimit: 40,
|
||||
libassGlyphLimit: 40,
|
||||
targetFps: 24,
|
||||
prescaleTradeoff: 0.8,
|
||||
softHeightLimit: 1080,
|
||||
hardHeightLimit: 2160,
|
||||
resizeVariation: 0.2,
|
||||
renderAhead: 90
|
||||
};
|
||||
require(['JavascriptSubtitlesOctopus'], function(SubtitlesOctopus) {
|
||||
currentSubtitlesOctopus = new SubtitlesOctopus(options);
|
||||
});
|
||||
}
|
||||
|
||||
function renderWithLibjass(videoElement, track, item) {
|
||||
|
||||
var rendererSettings = {};
|
||||
|
||||
if (browser.ps4) {
|
||||
// Text outlines are not rendering very well
|
||||
rendererSettings.enableSvg = false;
|
||||
} else if (browser.edge || browser.msie) {
|
||||
// svg not rendering at all
|
||||
rendererSettings.enableSvg = false;
|
||||
}
|
||||
|
||||
// probably safer to just disable everywhere
|
||||
rendererSettings.enableSvg = false;
|
||||
|
||||
require(['libjass', 'ResizeObserver'], function (libjass, ResizeObserver) {
|
||||
|
||||
libjass.ASS.fromUrl(getTextTrackUrl(track, item)).then(function (ass) {
|
||||
|
||||
var clock = new libjass.renderers.ManualClock();
|
||||
currentClock = clock;
|
||||
|
||||
// Create a DefaultRenderer using the video element and the ASS object
|
||||
var renderer = new libjass.renderers.WebRenderer(ass, clock, videoElement.parentNode, rendererSettings);
|
||||
|
||||
currentAssRenderer = renderer;
|
||||
|
||||
renderer.addEventListener("ready", function () {
|
||||
try {
|
||||
renderer.resize(videoElement.offsetWidth, videoElement.offsetHeight, 0, 0);
|
||||
|
||||
if (!self._resizeObserver) {
|
||||
self._resizeObserver = new ResizeObserver(onVideoResize, {});
|
||||
self._resizeObserver.observe(videoElement);
|
||||
}
|
||||
//clock.pause();
|
||||
} catch (ex) {
|
||||
//alert(ex);
|
||||
}
|
||||
});
|
||||
}, function () {
|
||||
htmlMediaHelper.onErrorInternal(self, 'mediadecodeerror');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderSsaAss(videoElement, track, item) {
|
||||
if (supportsCanvas() && supportsWebWorkers()) {
|
||||
renderWithSubtitlesOctopus(videoElement, track, item);
|
||||
} else {
|
||||
console.log('rendering subtitles with libjass');
|
||||
renderWithLibjass(videoElement, track, item);
|
||||
}
|
||||
}
|
||||
|
||||
function onVideoResize() {
|
||||
if (browser.iOS) {
|
||||
// the new sizes will be delayed for about 500ms with wkwebview
|
||||
setTimeout(resetVideoRendererSize, 500);
|
||||
} else {
|
||||
resetVideoRendererSize();
|
||||
}
|
||||
}
|
||||
|
||||
function resetVideoRendererSize() {
|
||||
var renderer = currentAssRenderer;
|
||||
if (renderer) {
|
||||
var videoElement = self._mediaElement;
|
||||
var width = videoElement.offsetWidth;
|
||||
var height = videoElement.offsetHeight;
|
||||
console.log('videoElement resized: ' + width + 'x' + height);
|
||||
renderer.resize(width, height, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function requiresCustomSubtitlesElement() {
|
||||
|
||||
// after a system update, ps4 isn't showing anything when creating a track element dynamically
|
||||
|
@ -1233,7 +1178,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
if (!itemHelper.isLocalItem(item) || track.IsExternal) {
|
||||
var format = (track.Codec || '').toLowerCase();
|
||||
if (format === 'ssa' || format === 'ass') {
|
||||
// libjass is needed here
|
||||
renderSsaAss(videoElement, track, item);
|
||||
return;
|
||||
}
|
||||
|
@ -1256,7 +1200,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
trackElement.removeCue(trackElement.cues[0]);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Error removing cue from textTrack');
|
||||
console.error('error removing cue from textTrack');
|
||||
}
|
||||
|
||||
trackElement.mode = 'disabled';
|
||||
|
@ -1270,13 +1214,13 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
fetchSubtitles(track, item).then(function (data) {
|
||||
|
||||
// show in ui
|
||||
console.log('downloaded ' + data.TrackEvents.length + ' track events');
|
||||
console.debug('downloaded ' + data.TrackEvents.length + ' track events');
|
||||
// add some cues to show the text
|
||||
// in safari, the cues need to be added before setting the track mode to showing
|
||||
data.TrackEvents.forEach(function (trackEvent) {
|
||||
|
||||
var trackCueObject = window.VTTCue || window.TextTrackCue;
|
||||
var cue = new trackCueObject(trackEvent.StartPositionTicks / 10000000, trackEvent.EndPositionTicks / 10000000, normalizeTrackEventText(trackEvent.Text));
|
||||
var cue = new trackCueObject(trackEvent.StartPositionTicks / 10000000, trackEvent.EndPositionTicks / 10000000, normalizeTrackEventText(trackEvent.Text, false));
|
||||
|
||||
trackElement.addCue(cue);
|
||||
});
|
||||
|
@ -1286,17 +1230,12 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
function updateSubtitleText(timeMs) {
|
||||
|
||||
// handle offset for ass tracks
|
||||
if (currentTrackOffset) {
|
||||
timeMs += (currentTrackOffset * 1000);
|
||||
}
|
||||
|
||||
var clock = currentClock;
|
||||
if (clock) {
|
||||
try {
|
||||
clock.seek(timeMs / 1000);
|
||||
} catch (err) {
|
||||
console.log('Error in libjass: ' + err);
|
||||
console.error('error in libjass: ' + err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1317,8 +1256,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
}
|
||||
|
||||
if (selectedTrackEvent && selectedTrackEvent.Text) {
|
||||
|
||||
subtitleTextElement.innerHTML = normalizeTrackEventText(selectedTrackEvent.Text);
|
||||
subtitleTextElement.innerHTML = normalizeTrackEventText(selectedTrackEvent.Text, true);
|
||||
subtitleTextElement.classList.remove('hide');
|
||||
|
||||
} else {
|
||||
|
@ -1329,7 +1267,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
function setCurrentTrackElement(streamIndex) {
|
||||
|
||||
console.log('Setting new text track index to: ' + streamIndex);
|
||||
console.debug('setting new text track index to: ' + streamIndex);
|
||||
|
||||
var mediaStreamTextTracks = getMediaStreamTextTracks(self._currentPlayOptions.mediaSource);
|
||||
|
||||
|
@ -1350,38 +1288,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
}
|
||||
}
|
||||
|
||||
function updateTextStreamUrls(startPositionTicks) {
|
||||
|
||||
if (!supportsTextTracks()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var allTracks = self._mediaElement.textTracks; // get list of tracks
|
||||
var i;
|
||||
var track;
|
||||
|
||||
for (i = 0; i < allTracks.length; i++) {
|
||||
|
||||
track = allTracks[i];
|
||||
|
||||
// This throws an error in IE, but is fine in chrome
|
||||
// In IE it's not necessary anyway because changing the src seems to be enough
|
||||
try {
|
||||
while (track.cues.length) {
|
||||
track.removeCue(track.cues[0]);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Error removing cue from textTrack');
|
||||
}
|
||||
}
|
||||
|
||||
var tracks = self._mediaElement.querySelectorAll('track');
|
||||
for (i = 0; i < tracks.length; i++) {
|
||||
track = tracks[i];
|
||||
track.src = replaceQueryString(track.src, 'startPositionTicks', startPositionTicks);
|
||||
}
|
||||
}
|
||||
|
||||
function createMediaElement(options) {
|
||||
|
||||
if (browser.tv || browser.iOS || browser.mobile) {
|
||||
|
@ -1405,7 +1311,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
dlg.classList.add('videoPlayerContainer');
|
||||
|
||||
if (options.backdropUrl) {
|
||||
|
||||
dlg.classList.add('videoPlayerContainer-withBackdrop');
|
||||
dlg.style.backgroundImage = "url('" + options.backdropUrl + "')";
|
||||
}
|
||||
|
@ -1414,11 +1319,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
dlg.classList.add('videoPlayerContainer-onTop');
|
||||
}
|
||||
|
||||
// playsinline new for iOS 10
|
||||
// https://developer.apple.com/library/content/releasenotes/General/WhatsNewInSafari/Articles/Safari_10_0.html
|
||||
|
||||
var html = '';
|
||||
|
||||
var cssClass = 'htmlvideoplayer';
|
||||
|
||||
if (!browser.chromecast) {
|
||||
|
@ -1429,7 +1330,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
if (!appHost.supports('htmlvideoautoplay')) {
|
||||
html += '<video class="' + cssClass + '" preload="metadata" autoplay="autoplay" controls="controls" webkit-playsinline playsinline>';
|
||||
} else {
|
||||
|
||||
// Chrome 35 won't play with preload none
|
||||
html += '<video class="' + cssClass + '" preload="metadata" autoplay="autoplay" webkit-playsinline playsinline>';
|
||||
}
|
||||
|
@ -1454,7 +1354,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
self._mediaElement = videoElement;
|
||||
|
||||
if (mediaManager) {
|
||||
|
||||
if (!mediaManager.embyInit) {
|
||||
initMediaManager();
|
||||
mediaManager.embyInit = true;
|
||||
|
@ -1470,9 +1369,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
} else {
|
||||
resolve(videoElement);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
} else {
|
||||
if (options.backdropUrl) {
|
||||
dlg.classList.add('videoPlayerContainer-withBackdrop');
|
||||
|
@ -1520,12 +1417,12 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
var list = [];
|
||||
|
||||
var video = document.createElement('video');
|
||||
if (video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function" || document.pictureInPictureEnabled) {
|
||||
if (video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === 'function' || document.pictureInPictureEnabled) {
|
||||
list.push('PictureInPicture');
|
||||
} else if (browser.ipad) {
|
||||
// Unfortunately this creates a false positive on devices where its' not actually supported
|
||||
if (navigator.userAgent.toLowerCase().indexOf('os 9') === -1) {
|
||||
if (video.webkitSupportsPresentationMode && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function") {
|
||||
if (video.webkitSupportsPresentationMode && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === 'function') {
|
||||
list.push('PictureInPicture');
|
||||
}
|
||||
}
|
||||
|
@ -1536,11 +1433,11 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
}
|
||||
|
||||
if (browser.safari || browser.iOS || browser.iPad) {
|
||||
list.push('AirPlay')
|
||||
list.push('AirPlay');
|
||||
}
|
||||
|
||||
list.push('SetBrightness');
|
||||
list.push("SetAspectRatio")
|
||||
list.push('SetAspectRatio');
|
||||
|
||||
return list;
|
||||
}
|
||||
|
@ -1601,7 +1498,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
};
|
||||
|
||||
function onPictureInPictureError(err) {
|
||||
console.log('Picture in picture error: ' + err.toString());
|
||||
console.error('Picture in picture error: ' + err.toString());
|
||||
}
|
||||
|
||||
HtmlVideoPlayer.prototype.setPictureInPictureEnabled = function (isEnabled) {
|
||||
|
@ -1625,8 +1522,8 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
Windows.UI.ViewManagement.ApplicationView.getForCurrentView().tryEnterViewModeAsync(Windows.UI.ViewManagement.ApplicationViewMode.default);
|
||||
}
|
||||
} else {
|
||||
if (video && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function") {
|
||||
video.webkitSetPresentationMode(isEnabled ? "picture-in-picture" : "inline");
|
||||
if (video && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === 'function') {
|
||||
video.webkitSetPresentationMode(isEnabled ? 'picture-in-picture' : 'inline');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1640,7 +1537,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
} else {
|
||||
var video = this._mediaElement;
|
||||
if (video) {
|
||||
return video.webkitPresentationMode === "picture-in-picture";
|
||||
return video.webkitPresentationMode === 'picture-in-picture';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1662,9 +1559,13 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
if (document.AirPlayEnabled) {
|
||||
if (video) {
|
||||
if (isEnabled) {
|
||||
video.requestAirPlay().catch(onAirPlayError);
|
||||
video.requestAirPlay().catch(function(err) {
|
||||
console.error('Error requesting AirPlay', err);
|
||||
});
|
||||
} else {
|
||||
document.exitAirPLay().catch(onAirPlayError);
|
||||
document.exitAirPLay().catch(function(err) {
|
||||
console.error('Error exiting AirPlay', err);
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1795,30 +1696,30 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
HtmlVideoPlayer.prototype.setAspectRatio = function (val) {
|
||||
var mediaElement = this._mediaElement;
|
||||
if (mediaElement) {
|
||||
if ("auto" === val) {
|
||||
mediaElement.style.removeProperty("object-fit")
|
||||
if ('auto' === val) {
|
||||
mediaElement.style.removeProperty('object-fit');
|
||||
} else {
|
||||
mediaElement.style["object-fit"] = val
|
||||
mediaElement.style['object-fit'] = val;
|
||||
}
|
||||
}
|
||||
this._currentAspectRatio = val
|
||||
this._currentAspectRatio = val;
|
||||
};
|
||||
|
||||
HtmlVideoPlayer.prototype.getAspectRatio = function () {
|
||||
return this._currentAspectRatio;
|
||||
return this._currentAspectRatio || 'auto';
|
||||
};
|
||||
|
||||
HtmlVideoPlayer.prototype.getSupportedAspectRatios = function () {
|
||||
return [{
|
||||
name: "Auto",
|
||||
id: "auto"
|
||||
name: 'Auto',
|
||||
id: 'auto'
|
||||
}, {
|
||||
name: "Cover",
|
||||
id: "cover"
|
||||
name: 'Cover',
|
||||
id: 'cover'
|
||||
}, {
|
||||
name: "Fill",
|
||||
id: "fill"
|
||||
}]
|
||||
name: 'Fill',
|
||||
id: 'fill'
|
||||
}];
|
||||
};
|
||||
|
||||
HtmlVideoPlayer.prototype.togglePictureInPicture = function () {
|
||||
|
@ -1866,7 +1767,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
if (protocol) {
|
||||
mediaCategory.stats.push({
|
||||
label: 'Protocol:',
|
||||
label: globalize.translate('LabelProtocol'),
|
||||
value: protocol
|
||||
});
|
||||
}
|
||||
|
@ -1876,12 +1777,12 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
if (this._hlsPlayer || this._shakaPlayer) {
|
||||
mediaCategory.stats.push({
|
||||
label: 'Stream type:',
|
||||
label: globalize.translate('LabelStreamType'),
|
||||
value: 'HLS'
|
||||
});
|
||||
} else {
|
||||
mediaCategory.stats.push({
|
||||
label: 'Stream type:',
|
||||
label: globalize.translate('LabelStreamType'),
|
||||
value: 'Video'
|
||||
});
|
||||
}
|
||||
|
@ -1893,13 +1794,13 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
categories.push(videoCategory);
|
||||
|
||||
var rect = mediaElement.getBoundingClientRect ? mediaElement.getBoundingClientRect() : {};
|
||||
var height = rect.height;
|
||||
var width = rect.width;
|
||||
var height = parseInt(rect.height);
|
||||
var width = parseInt(rect.width);
|
||||
|
||||
// Don't show player dimensions on smart TVs because the app UI could be lower resolution than the video and this causes users to think there is a problem
|
||||
if (width && height && !browser.tv) {
|
||||
videoCategory.stats.push({
|
||||
label: 'Player dimensions:',
|
||||
label: globalize.translate('LabelPlayerDimensions'),
|
||||
value: width + 'x' + height
|
||||
});
|
||||
}
|
||||
|
@ -1909,7 +1810,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
if (width && height) {
|
||||
videoCategory.stats.push({
|
||||
label: 'Video resolution:',
|
||||
label: globalize.translate('LabelVideoResolution'),
|
||||
value: width + 'x' + height
|
||||
});
|
||||
}
|
||||
|
@ -1919,13 +1820,13 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
|
|||
|
||||
var droppedVideoFrames = playbackQuality.droppedVideoFrames || 0;
|
||||
videoCategory.stats.push({
|
||||
label: 'Dropped frames:',
|
||||
label: globalize.translate('LabelDroppedFrames'),
|
||||
value: droppedVideoFrames
|
||||
});
|
||||
|
||||
var corruptedVideoFrames = playbackQuality.corruptedVideoFrames || 0;
|
||||
videoCategory.stats.push({
|
||||
label: 'Corrupted frames:',
|
||||
label: globalize.translate('LabelCorruptedFrames'),
|
||||
value: corruptedVideoFrames
|
||||
});
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ video::-webkit-media-controls {
|
|||
.htmlvideoplayer::cue {
|
||||
background-color: transparent;
|
||||
text-shadow: 0.14em 0.14em 0.14em rgba(0, 0, 0, 1);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
|
@ -71,7 +72,7 @@ video::-webkit-media-controls {
|
|||
@keyframes htmlvideoplayer-zoomin {
|
||||
from {
|
||||
transform: scale3d(0.2, 0.2, 0.2);
|
||||
opacity: .6;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
to {
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
define(["datetime"], function (datetime) {
|
||||
"use strict";
|
||||
|
||||
function humaneDate(date_str) {
|
||||
var format;
|
||||
var time_formats = [
|
||||
[90, "a minute"],
|
||||
[3600, "minutes", 60],
|
||||
[5400, "an hour"],
|
||||
[86400, "hours", 3600],
|
||||
[129600, "a day"],
|
||||
[604800, "days", 86400],
|
||||
[907200, "a week"],
|
||||
[2628e3, "weeks", 604800],
|
||||
[3942e3, "a month"],
|
||||
[31536e3, "months", 2628e3],
|
||||
[47304e3, "a year"],
|
||||
[31536e5, "years", 31536e3]
|
||||
];
|
||||
var dt = new Date();
|
||||
var date = datetime.parseISO8601Date(date_str, true);
|
||||
var seconds = (dt - date) / 1000.0;
|
||||
var i = 0;
|
||||
|
||||
if (seconds < 0) {
|
||||
seconds = Math.abs(seconds);
|
||||
}
|
||||
for (; format = time_formats[i++];) {
|
||||
if (seconds < format[0]) {
|
||||
if (2 == format.length) {
|
||||
return format[1] + " ago";
|
||||
}
|
||||
|
||||
return Math.round(seconds / format[2]) + " " + format[1] + " ago";
|
||||
}
|
||||
}
|
||||
|
||||
if (seconds > 47304e5) {
|
||||
return Math.round(seconds / 47304e5) + " centuries ago";
|
||||
}
|
||||
|
||||
return date_str;
|
||||
}
|
||||
|
||||
function humaneElapsed(firstDateStr, secondDateStr) {
|
||||
// TODO replace this whole script with a library or something
|
||||
var dateOne = new Date(firstDateStr);
|
||||
var dateTwo = new Date(secondDateStr);
|
||||
var delta = (dateTwo.getTime() - dateOne.getTime()) / 1e3;
|
||||
var days = Math.floor(delta % 31536e3 / 86400);
|
||||
var hours = Math.floor(delta % 31536e3 % 86400 / 3600);
|
||||
var minutes = Math.floor(delta % 31536e3 % 86400 % 3600 / 60);
|
||||
var seconds = Math.round(delta % 31536e3 % 86400 % 3600 % 60);
|
||||
var elapsed = "";
|
||||
elapsed += 1 == days ? days + " day " : "";
|
||||
elapsed += days > 1 ? days + " days " : "";
|
||||
elapsed += 1 == hours ? hours + " hour " : "";
|
||||
elapsed += hours > 1 ? hours + " hours " : "";
|
||||
elapsed += 1 == minutes ? minutes + " minute " : "";
|
||||
elapsed += minutes > 1 ? minutes + " minutes " : "";
|
||||
elapsed += elapsed.length > 0 ? "and " : "";
|
||||
elapsed += 1 == seconds ? seconds + " second" : "";
|
||||
elapsed += 0 == seconds || seconds > 1 ? seconds + " seconds" : "";
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
window.humaneDate = humaneDate;
|
||||
window.humaneElapsed = humaneElapsed;
|
||||
return {
|
||||
humaneDate: humaneDate,
|
||||
humaneElapsed: humaneElapsed
|
||||
};
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader', 'browser', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'emby-checkbox', 'paper-icon-button-light', 'emby-button', 'formDialogStyle', 'cardStyle'], function (loading, appHost, dialogHelper, connectionManager, imageLoader, browser, layoutManager, scrollHelper, globalize, require) {
|
||||
define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader', 'browser', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'emby-checkbox', 'paper-icon-button-light', 'emby-button', 'formDialogStyle', 'cardStyle'], function (dom, loading, appHost, dialogHelper, connectionManager, imageLoader, browser, layoutManager, scrollHelper, globalize, require) {
|
||||
'use strict';
|
||||
|
||||
var enableFocusTransform = !browser.slow && !browser.edge;
|
||||
|
@ -109,15 +109,15 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader'
|
|||
html += '<span style="margin-right: 10px;">';
|
||||
|
||||
var startAtDisplay = totalRecordCount ? startIndex + 1 : 0;
|
||||
html += startAtDisplay + '-' + recordsEnd + ' of ' + totalRecordCount;
|
||||
html += globalize.translate('ListPaging', startAtDisplay, recordsEnd, totalRecordCount);
|
||||
|
||||
html += '</span>';
|
||||
|
||||
if (showControls) {
|
||||
html += '<div data-role="controlgroup" data-type="horizontal" style="display:inline-block;">';
|
||||
|
||||
html += '<button is="paper-icon-button-light" title="' + globalize.translate('Previous') + '" class="btnPreviousPage autoSize" ' + (startIndex ? '' : 'disabled') + '><i class="md-icon">arrow_back</i></button>';
|
||||
html += '<button is="paper-icon-button-light" title="' + globalize.translate('Next') + '" class="btnNextPage autoSize" ' + (startIndex + limit >= totalRecordCount ? 'disabled' : '') + '><i class="md-icon">arrow_forward</i></button>';
|
||||
html += '<button is="paper-icon-button-light" title="' + globalize.translate('Previous') + '" class="btnPreviousPage autoSize" ' + (startIndex ? '' : 'disabled') + '><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<button is="paper-icon-button-light" title="' + globalize.translate('Next') + '" class="btnNextPage autoSize" ' + (startIndex + limit >= totalRecordCount ? 'disabled' : '') + '><span class="material-icons arrow_forward"></span></button>';
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
|
@ -126,21 +126,7 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader'
|
|||
return html;
|
||||
}
|
||||
|
||||
function parentWithClass(elem, className) {
|
||||
|
||||
while (!elem.classList || !elem.classList.contains(className)) {
|
||||
elem = elem.parentNode;
|
||||
|
||||
if (!elem) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
function downloadRemoteImage(page, apiClient, url, type, provider) {
|
||||
|
||||
var options = getBaseRemoteOptions();
|
||||
|
||||
options.Type = type;
|
||||
|
@ -152,17 +138,16 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader'
|
|||
apiClient.downloadRemoteImage(options).then(function () {
|
||||
|
||||
hasChanges = true;
|
||||
var dlg = parentWithClass(page, 'dialog');
|
||||
var dlg = dom.parentWithClass(page, 'dialog');
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
}
|
||||
|
||||
function getDisplayUrl(url, apiClient) {
|
||||
return apiClient.getUrl("Images/Remote", { imageUrl: url });
|
||||
return apiClient.getUrl('Images/Remote', { imageUrl: url });
|
||||
}
|
||||
|
||||
function getRemoteImageHtml(image, imageType, apiClient) {
|
||||
|
||||
var tagName = layoutManager.tv ? 'button' : 'div';
|
||||
var enableFooterButtons = !layoutManager.tv;
|
||||
|
||||
|
@ -170,21 +155,21 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader'
|
|||
|
||||
var html = '';
|
||||
|
||||
var cssClass = "card scalableCard imageEditorCard";
|
||||
var cssClass = 'card scalableCard imageEditorCard';
|
||||
var cardBoxCssClass = 'cardBox visualCardBox';
|
||||
|
||||
var shape = 'backdrop';
|
||||
if (imageType === "Backdrop" || imageType === "Art" || imageType === "Thumb" || imageType === "Logo") {
|
||||
if (imageType === 'Backdrop' || imageType === 'Art' || imageType === 'Thumb' || imageType === 'Logo') {
|
||||
shape = 'backdrop';
|
||||
} else if (imageType === "Banner") {
|
||||
} else if (imageType === 'Banner') {
|
||||
shape = 'banner';
|
||||
} else if (imageType === "Disc") {
|
||||
} else if (imageType === 'Disc') {
|
||||
shape = 'square';
|
||||
} else {
|
||||
|
||||
if (currentItemType === "Episode") {
|
||||
if (currentItemType === 'Episode') {
|
||||
shape = 'backdrop';
|
||||
} else if (currentItemType === "MusicAlbum" || currentItemType === "MusicArtist") {
|
||||
} else if (currentItemType === 'MusicAlbum' || currentItemType === 'MusicArtist') {
|
||||
shape = 'square';
|
||||
} else {
|
||||
shape = 'portrait';
|
||||
|
@ -256,18 +241,18 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader'
|
|||
|
||||
html += '<div class="cardText cardText-secondary cardTextCentered">';
|
||||
|
||||
if (image.RatingType === "Likes") {
|
||||
html += image.CommunityRating + (image.CommunityRating === 1 ? " like" : " likes");
|
||||
if (image.RatingType === 'Likes') {
|
||||
html += image.CommunityRating + (image.CommunityRating === 1 ? ' like' : ' likes');
|
||||
} else {
|
||||
|
||||
if (image.CommunityRating) {
|
||||
html += image.CommunityRating.toFixed(1);
|
||||
|
||||
if (image.VoteCount) {
|
||||
html += ' • ' + image.VoteCount + (image.VoteCount === 1 ? " vote" : " votes");
|
||||
html += ' • ' + image.VoteCount + (image.VoteCount === 1 ? ' vote' : ' votes');
|
||||
}
|
||||
} else {
|
||||
html += "Unrated";
|
||||
html += 'Unrated';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,7 +262,7 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader'
|
|||
if (enableFooterButtons) {
|
||||
html += '<div class="cardText cardTextCentered">';
|
||||
|
||||
html += '<button is="paper-icon-button-light" class="btnDownloadRemoteImage autoSize" raised" title="' + globalize.translate('Download') + '"><i class="md-icon">cloud_download</i></button>';
|
||||
html += '<button is="paper-icon-button-light" class="btnDownloadRemoteImage autoSize" raised" title="' + globalize.translate('Download') + '"><span class="material-icons cloud_download"></span></button>';
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
|
@ -293,7 +278,6 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader'
|
|||
}
|
||||
|
||||
function initEditor(page, apiClient) {
|
||||
|
||||
page.querySelector('#selectBrowsableImageType').addEventListener('change', function () {
|
||||
browsableImageType = this.value;
|
||||
browsableImageStartIndex = 0;
|
||||
|
@ -319,14 +303,14 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader'
|
|||
|
||||
page.addEventListener('click', function (e) {
|
||||
|
||||
var btnDownloadRemoteImage = parentWithClass(e.target, 'btnDownloadRemoteImage');
|
||||
var btnDownloadRemoteImage = dom.parentWithClass(e.target, 'btnDownloadRemoteImage');
|
||||
if (btnDownloadRemoteImage) {
|
||||
var card = parentWithClass(btnDownloadRemoteImage, 'card');
|
||||
var card = dom.parentWithClass(btnDownloadRemoteImage, 'card');
|
||||
downloadRemoteImage(page, apiClient, card.getAttribute('data-imageurl'), card.getAttribute('data-imagetype'), card.getAttribute('data-imageprovider'));
|
||||
return;
|
||||
}
|
||||
|
||||
var btnImageCard = parentWithClass(e.target, 'btnImageCard');
|
||||
var btnImageCard = dom.parentWithClass(e.target, 'btnImageCard');
|
||||
if (btnImageCard) {
|
||||
downloadRemoteImage(page, apiClient, btnImageCard.getAttribute('data-imageurl'), btnImageCard.getAttribute('data-imagetype'), btnImageCard.getAttribute('data-imageprovider'));
|
||||
}
|
||||
|
@ -334,7 +318,6 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader'
|
|||
}
|
||||
|
||||
function showEditor(itemId, serverId, itemType) {
|
||||
|
||||
loading.show();
|
||||
|
||||
require(['text!./imagedownloader.template.html'], function (template) {
|
||||
|
@ -380,7 +363,6 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader'
|
|||
}
|
||||
|
||||
function onDialogClosed() {
|
||||
|
||||
var dlg = this;
|
||||
|
||||
if (layoutManager.tv) {
|
||||
|
@ -397,9 +379,7 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader'
|
|||
|
||||
return {
|
||||
show: function (itemId, serverId, itemType, imageType) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
currentResolve = resolve;
|
||||
currentReject = reject;
|
||||
hasChanges = false;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="formDialogHeader">
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="md-icon">arrow_back</i></button>
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>
|
||||
<h3 class="formDialogHeaderTitle">
|
||||
${Search}
|
||||
</h3>
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
|
||||
.first-imageEditor-buttons {
|
||||
margin-top: 2em;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,10 +99,10 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
|||
|
||||
var html = '';
|
||||
|
||||
var cssClass = "card scalableCard imageEditorCard";
|
||||
var cssClass = 'card scalableCard imageEditorCard';
|
||||
var cardBoxCssClass = 'cardBox visualCardBox';
|
||||
|
||||
cssClass += " backdropCard backdropCard-scalable";
|
||||
cssClass += ' backdropCard backdropCard-scalable';
|
||||
|
||||
if (tagName === 'button') {
|
||||
cssClass += ' btnImageCard';
|
||||
|
@ -152,26 +152,26 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
|||
if (enableFooterButtons) {
|
||||
html += '<div class="cardText cardTextCentered">';
|
||||
|
||||
if (image.ImageType === "Backdrop" || image.ImageType === "Screenshot") {
|
||||
if (image.ImageType === 'Backdrop' || image.ImageType === 'Screenshot') {
|
||||
|
||||
if (index > 0) {
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex - 1) + '" title="' + globalize.translate('MoveLeft') + '"><i class="md-icon">chevron_left</i></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex - 1) + '" title="' + globalize.translate('MoveLeft') + '"><span class="material-icons chevron_left"></span></button>';
|
||||
} else {
|
||||
html += '<button type="button" is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('MoveLeft') + '"><i class="md-icon">chevron_left</i></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('MoveLeft') + '"><span class="material-icons chevron_left"></span></button>';
|
||||
}
|
||||
|
||||
if (index < numImages - 1) {
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex + 1) + '" title="' + globalize.translate('MoveRight') + '"><i class="md-icon">chevron_right</i></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex + 1) + '" title="' + globalize.translate('MoveRight') + '"><span class="material-icons chevron_right"></span></button>';
|
||||
} else {
|
||||
html += '<button type="button" is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('MoveRight') + '"><i class="md-icon">chevron_right</i></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('MoveRight') + '"><span class="material-icons chevron_right"></span></button>';
|
||||
}
|
||||
} else {
|
||||
if (imageProviders.length) {
|
||||
html += '<button type="button" is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" class="btnSearchImages autoSize" title="' + globalize.translate('Search') + '"><i class="md-icon">search</i></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" class="btnSearchImages autoSize" title="' + globalize.translate('Search') + '"><span class="material-icons search"></span></button>';
|
||||
}
|
||||
}
|
||||
|
||||
html += '<button type="button" is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" data-index="' + (image.ImageIndex != null ? image.ImageIndex : "null") + '" class="btnDeleteImage autoSize" title="' + globalize.translate('Delete') + '"><i class="md-icon">delete</i></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" data-index="' + (image.ImageIndex != null ? image.ImageIndex : 'null') + '" class="btnDeleteImage autoSize" title="' + globalize.translate('Delete') + '"><span class="material-icons delete"></span></button>';
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
|||
function renderStandardImages(page, apiClient, item, imageInfos, imageProviders) {
|
||||
|
||||
var images = imageInfos.filter(function (i) {
|
||||
return i.ImageType !== "Screenshot" && i.ImageType !== "Backdrop" && i.ImageType !== "Chapter";
|
||||
return i.ImageType !== 'Screenshot' && i.ImageType !== 'Backdrop' && i.ImageType !== 'Chapter';
|
||||
});
|
||||
|
||||
renderImages(page, item, apiClient, images, imageProviders, page.querySelector('#images'));
|
||||
|
@ -260,7 +260,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
|||
function renderBackdrops(page, apiClient, item, imageInfos, imageProviders) {
|
||||
|
||||
var images = imageInfos.filter(function (i) {
|
||||
return i.ImageType === "Backdrop";
|
||||
return i.ImageType === 'Backdrop';
|
||||
|
||||
}).sort(function (a, b) {
|
||||
return a.ImageIndex - b.ImageIndex;
|
||||
|
@ -277,7 +277,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
|||
function renderScreenshots(page, apiClient, item, imageInfos, imageProviders) {
|
||||
|
||||
var images = imageInfos.filter(function (i) {
|
||||
return i.ImageType === "Screenshot";
|
||||
return i.ImageType === 'Screenshot';
|
||||
|
||||
}).sort(function (a, b) {
|
||||
return a.ImageIndex - b.ImageIndex;
|
||||
|
@ -425,7 +425,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
|||
addListeners(context, 'btnDeleteImage', 'click', function () {
|
||||
var type = this.getAttribute('data-imagetype');
|
||||
var index = this.getAttribute('data-index');
|
||||
index = index === "null" ? null : parseInt(index);
|
||||
index = index === 'null' ? null : parseInt(index);
|
||||
var apiClient = connectionManager.getApiClient(currentItem.ServerId);
|
||||
deleteImage(context, currentItem.Id, type, index, apiClient, true);
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="formDialogHeader">
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="md-icon">arrow_back</i></button>
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>
|
||||
<h3 class="formDialogHeaderTitle">
|
||||
${HeaderEditImages}
|
||||
</h3>
|
||||
|
@ -12,10 +12,10 @@
|
|||
<div class="imageEditor-buttons first-imageEditor-buttons">
|
||||
<h2 style="margin:0;">${Images}</h2>
|
||||
<button type="button" is="emby-button" class="btnBrowseAllImages fab mini autoSize" style="margin-left: 1em;">
|
||||
<i class="md-icon">search</i>
|
||||
<span class="material-icons search"></span>
|
||||
</button>
|
||||
<button type="button" is="emby-button" class="btnOpenUploadMenu fab mini hide" style="margin-left: .5em;">
|
||||
<i class="md-icon">add</i>
|
||||
<span class="material-icons add"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="images" class="itemsContainer vertical-wrap">
|
||||
|
@ -27,10 +27,10 @@
|
|||
<div class="imageEditor-buttons">
|
||||
<h2 style="margin:0;">${Backdrops}</h2>
|
||||
<button type="button" is="emby-button" class="btnBrowseAllImages fab mini autoSize" style="margin-left: 1em;" data-imagetype="Backdrop">
|
||||
<i class="md-icon">search</i>
|
||||
<span class="material-icons search"></span>
|
||||
</button>
|
||||
<button type="button" is="emby-button" class="btnOpenUploadMenu fab mini hide" style="margin-left: .5em;" data-imagetype="Backdrop">
|
||||
<i class="md-icon">add</i>
|
||||
<span class="material-icons add"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="backdrops" class="itemsContainer vertical-wrap">
|
||||
|
@ -42,10 +42,10 @@
|
|||
<div class="imageEditor-buttons">
|
||||
<h2 style="margin: 0;">${Screenshots}</h2>
|
||||
<button type="button" is="emby-button" class="btnBrowseAllImages fab mini autoSize" style="margin-left: 1em;" data-imagetype="Screenshot">
|
||||
<i class="md-icon">search</i>
|
||||
<span class="material-icons search"></span>
|
||||
</button>
|
||||
<button type="button" is="emby-button" class="btnOpenUploadMenu fab mini hide" style="margin-left: .5em;" data-imagetype="Screenshot">
|
||||
<i class="md-icon">add</i>
|
||||
<span class="material-icons add"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="screenshots" class="itemsContainer vertical-wrap">
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emby-input"], function (globalize, dom, dialogHelper) {
|
||||
"use strict";
|
||||
define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emby-input'], function (globalize, dom, dialogHelper) {
|
||||
'use strict';
|
||||
|
||||
function getDefaultImageConfig(itemType, type) {
|
||||
return {
|
||||
Type: type,
|
||||
MinWidth: 0,
|
||||
Limit: "Primary" === type ? 1 : 0
|
||||
Limit: 'Primary' === type ? 1 : 0
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -21,27 +21,27 @@ define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emb
|
|||
|
||||
function setVisibilityOfBackdrops(elem, visible) {
|
||||
if (visible) {
|
||||
elem.classList.remove("hide");
|
||||
elem.querySelector("input").setAttribute("required", "required");
|
||||
elem.classList.remove('hide');
|
||||
elem.querySelector('input').setAttribute('required', 'required');
|
||||
} else {
|
||||
elem.classList.add("hide");
|
||||
elem.querySelector("input").setAttribute("required", "");
|
||||
elem.querySelector("input").removeAttribute("required");
|
||||
elem.classList.add('hide');
|
||||
elem.querySelector('input').setAttribute('required', '');
|
||||
elem.querySelector('input').removeAttribute('required');
|
||||
}
|
||||
}
|
||||
|
||||
function loadValues(context, itemType, options, availableOptions) {
|
||||
var supportedImageTypes = availableOptions.SupportedImageTypes || [];
|
||||
setVisibilityOfBackdrops(context.querySelector(".backdropFields"), -1 != supportedImageTypes.indexOf("Backdrop"));
|
||||
setVisibilityOfBackdrops(context.querySelector(".screenshotFields"), -1 != supportedImageTypes.indexOf("Screenshot"));
|
||||
Array.prototype.forEach.call(context.querySelectorAll(".imageType"), function (i) {
|
||||
var imageType = i.getAttribute("data-imagetype");
|
||||
var container = dom.parentWithTag(i, "LABEL");
|
||||
setVisibilityOfBackdrops(context.querySelector('.backdropFields'), -1 != supportedImageTypes.indexOf('Backdrop'));
|
||||
setVisibilityOfBackdrops(context.querySelector('.screenshotFields'), -1 != supportedImageTypes.indexOf('Screenshot'));
|
||||
Array.prototype.forEach.call(context.querySelectorAll('.imageType'), function (i) {
|
||||
var imageType = i.getAttribute('data-imagetype');
|
||||
var container = dom.parentWithTag(i, 'LABEL');
|
||||
|
||||
if (-1 == supportedImageTypes.indexOf(imageType)) {
|
||||
container.classList.add("hide");
|
||||
container.classList.add('hide');
|
||||
} else {
|
||||
container.classList.remove("hide");
|
||||
container.classList.remove('hide');
|
||||
}
|
||||
|
||||
if (getImageConfig(options, availableOptions, imageType, itemType).Limit) {
|
||||
|
@ -50,31 +50,31 @@ define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emb
|
|||
i.checked = false;
|
||||
}
|
||||
});
|
||||
var backdropConfig = getImageConfig(options, availableOptions, "Backdrop", itemType);
|
||||
context.querySelector("#txtMaxBackdrops").value = backdropConfig.Limit;
|
||||
context.querySelector("#txtMinBackdropDownloadWidth").value = backdropConfig.MinWidth;
|
||||
var screenshotConfig = getImageConfig(options, availableOptions, "Screenshot", itemType);
|
||||
context.querySelector("#txtMaxScreenshots").value = screenshotConfig.Limit;
|
||||
context.querySelector("#txtMinScreenshotDownloadWidth").value = screenshotConfig.MinWidth;
|
||||
var backdropConfig = getImageConfig(options, availableOptions, 'Backdrop', itemType);
|
||||
context.querySelector('#txtMaxBackdrops').value = backdropConfig.Limit;
|
||||
context.querySelector('#txtMinBackdropDownloadWidth').value = backdropConfig.MinWidth;
|
||||
var screenshotConfig = getImageConfig(options, availableOptions, 'Screenshot', itemType);
|
||||
context.querySelector('#txtMaxScreenshots').value = screenshotConfig.Limit;
|
||||
context.querySelector('#txtMinScreenshotDownloadWidth').value = screenshotConfig.MinWidth;
|
||||
}
|
||||
|
||||
function saveValues(context, options) {
|
||||
options.ImageOptions = Array.prototype.map.call(context.querySelectorAll(".imageType:not(.hide)"), function (c) {
|
||||
options.ImageOptions = Array.prototype.map.call(context.querySelectorAll('.imageType:not(.hide)'), function (c) {
|
||||
return {
|
||||
Type: c.getAttribute("data-imagetype"),
|
||||
Type: c.getAttribute('data-imagetype'),
|
||||
Limit: c.checked ? 1 : 0,
|
||||
MinWidth: 0
|
||||
};
|
||||
});
|
||||
options.ImageOptions.push({
|
||||
Type: "Backdrop",
|
||||
Limit: context.querySelector("#txtMaxBackdrops").value,
|
||||
MinWidth: context.querySelector("#txtMinBackdropDownloadWidth").value
|
||||
Type: 'Backdrop',
|
||||
Limit: context.querySelector('#txtMaxBackdrops').value,
|
||||
MinWidth: context.querySelector('#txtMinBackdropDownloadWidth').value
|
||||
});
|
||||
options.ImageOptions.push({
|
||||
Type: "Screenshot",
|
||||
Limit: context.querySelector("#txtMaxScreenshots").value,
|
||||
MinWidth: context.querySelector("#txtMinScreenshotDownloadWidth").value
|
||||
Type: 'Screenshot',
|
||||
Limit: context.querySelector('#txtMaxScreenshots').value,
|
||||
MinWidth: context.querySelector('#txtMinScreenshotDownloadWidth').value
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -82,23 +82,23 @@ define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emb
|
|||
this.show = function (itemType, options, availableOptions) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "components/imageoptionseditor/imageoptionseditor.template.html", true);
|
||||
xhr.open('GET', 'components/imageoptionseditor/imageoptionseditor.template.html', true);
|
||||
|
||||
xhr.onload = function (e) {
|
||||
var template = this.response;
|
||||
var dlg = dialogHelper.createDialog({
|
||||
size: "medium-tall",
|
||||
size: 'medium-tall',
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
});
|
||||
dlg.classList.add("formDialog");
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.innerHTML = globalize.translateDocument(template);
|
||||
dlg.addEventListener("close", function () {
|
||||
dlg.addEventListener('close', function () {
|
||||
saveValues(dlg, options);
|
||||
});
|
||||
loadValues(dlg, itemType, options, availableOptions);
|
||||
dialogHelper.open(dlg).then(resolve, resolve);
|
||||
dlg.querySelector(".btnCancel").addEventListener("click", function () {
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="formDialogHeader">
|
||||
<button type="button" is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="md-icon">arrow_back</i></button>
|
||||
<button type="button" is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>
|
||||
<h3 class="formDialogHeaderTitle">
|
||||
${HeaderImageOptions}
|
||||
</h3>
|
||||
|
|
|
@ -7,7 +7,7 @@ define(['dom'], function (dom) {
|
|||
return Promise.reject('elem cannot be null');
|
||||
}
|
||||
|
||||
if (elem.tagName !== "IMG") {
|
||||
if (elem.tagName !== 'IMG') {
|
||||
|
||||
elem.style.backgroundImage = "url('" + url + "')";
|
||||
return Promise.resolve();
|
||||
|
@ -27,7 +27,7 @@ define(['dom'], function (dom) {
|
|||
dom.addEventListener(elem, 'load', resolve, {
|
||||
once: true
|
||||
});
|
||||
elem.setAttribute("src", url);
|
||||
elem.setAttribute('src', url);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -35,4 +35,4 @@ define(['dom'], function (dom) {
|
|||
loadImage: loadImage
|
||||
};
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,56 +1,82 @@
|
|||
define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings', 'require', 'css!./style'], function (lazyLoader, imageFetcher, layoutManager, browser, appSettings, require) {
|
||||
'use strict';
|
||||
|
||||
var requestIdleCallback = window.requestIdleCallback || function (fn) {
|
||||
fn();
|
||||
};
|
||||
|
||||
var self = {};
|
||||
|
||||
// seeing slow performance with firefox
|
||||
var enableFade = false;
|
||||
|
||||
function fillImage(elem, source, enableEffects) {
|
||||
|
||||
if (!elem) {
|
||||
throw new Error('elem cannot be null');
|
||||
}
|
||||
|
||||
if (!source) {
|
||||
source = elem.getAttribute('data-src');
|
||||
}
|
||||
import * as lazyLoader from 'lazyLoader';
|
||||
import * as userSettings from 'userSettings';
|
||||
import 'css!./style';
|
||||
/* eslint-disable indent */
|
||||
|
||||
export function lazyImage(elem, source = elem.getAttribute('data-src')) {
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
fillImageElement(elem, source, enableEffects);
|
||||
fillImageElement(elem, source);
|
||||
}
|
||||
|
||||
function fillImageElement(elem, source, enableEffects) {
|
||||
imageFetcher.loadImage(elem, source).then(function () {
|
||||
export function fillImage(entry) {
|
||||
if (!entry) {
|
||||
throw new Error('entry cannot be null');
|
||||
}
|
||||
|
||||
if (enableFade && enableEffects !== false) {
|
||||
fadeIn(elem);
|
||||
var source = undefined;
|
||||
if (entry.target) {
|
||||
source = entry.target.getAttribute('data-src');
|
||||
} else {
|
||||
source = entry;
|
||||
}
|
||||
|
||||
if (entry.intersectionRatio > 0) {
|
||||
if (source) fillImageElement(entry.target, source);
|
||||
} else if (!source) {
|
||||
emptyImageElement(entry.target);
|
||||
}
|
||||
}
|
||||
|
||||
function fillImageElement(elem, url) {
|
||||
if (url === undefined) {
|
||||
throw new Error('url cannot be undefined');
|
||||
}
|
||||
|
||||
let preloaderImg = new Image();
|
||||
preloaderImg.src = url;
|
||||
|
||||
preloaderImg.addEventListener('load', () => {
|
||||
if (elem.tagName !== 'IMG') {
|
||||
elem.style.backgroundImage = "url('" + url + "')";
|
||||
} else {
|
||||
elem.setAttribute('src', url);
|
||||
}
|
||||
|
||||
elem.removeAttribute("data-src");
|
||||
if (userSettings.enableFastFadein()) {
|
||||
elem.classList.add('lazy-image-fadein-fast');
|
||||
} else {
|
||||
elem.classList.add('lazy-image-fadein');
|
||||
}
|
||||
|
||||
elem.removeAttribute('data-src');
|
||||
});
|
||||
}
|
||||
|
||||
function fadeIn(elem) {
|
||||
function emptyImageElement(elem) {
|
||||
var url;
|
||||
|
||||
var cssClass = 'lazy-image-fadein';
|
||||
if (elem.tagName !== 'IMG') {
|
||||
url = elem.style.backgroundImage.slice(4, -1).replace(/"/g, '');
|
||||
elem.style.backgroundImage = 'none';
|
||||
} else {
|
||||
url = elem.getAttribute('src');
|
||||
elem.setAttribute('src', '');
|
||||
}
|
||||
|
||||
elem.classList.add(cssClass);
|
||||
elem.setAttribute('data-src', url);
|
||||
|
||||
elem.classList.remove('lazy-image-fadein-fast');
|
||||
elem.classList.remove('lazy-image-fadein');
|
||||
}
|
||||
|
||||
function lazyChildren(elem) {
|
||||
|
||||
export function lazyChildren(elem) {
|
||||
lazyLoader.lazyChildren(elem, fillImage);
|
||||
}
|
||||
|
||||
function getPrimaryImageAspectRatio(items) {
|
||||
export function getPrimaryImageAspectRatio(items) {
|
||||
|
||||
var values = [];
|
||||
|
||||
|
@ -110,7 +136,7 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings',
|
|||
return result;
|
||||
}
|
||||
|
||||
function fillImages(elems) {
|
||||
export function fillImages(elems) {
|
||||
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
var elem = elems[0];
|
||||
|
@ -118,10 +144,11 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings',
|
|||
}
|
||||
}
|
||||
|
||||
self.fillImages = fillImages;
|
||||
self.lazyImage = fillImage;
|
||||
self.lazyChildren = lazyChildren;
|
||||
self.getPrimaryImageAspectRatio = getPrimaryImageAspectRatio;
|
||||
|
||||
return self;
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
export default {
|
||||
fillImages: fillImages,
|
||||
fillImage: fillImage,
|
||||
lazyImage: lazyImage,
|
||||
lazyChildren: lazyChildren,
|
||||
getPrimaryImageAspectRatio: getPrimaryImageAspectRatio
|
||||
};
|
||||
|
|
|
@ -1,35 +1,13 @@
|
|||
.lazy-image-fadein {
|
||||
animation: lazy-image-fadein 330ms ease-in normal both;
|
||||
}
|
||||
|
||||
.lazy-image-fadein-fast {
|
||||
animation: lazy-image-fadein 160ms ease-in normal both;
|
||||
}
|
||||
|
||||
@keyframes lazy-image-fadein {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.lazy-image-fadein {
|
||||
.cardImageContainer.lazy {
|
||||
opacity: 0;
|
||||
animation-duration: .8s;
|
||||
animation-name: popInAnimation;
|
||||
animation-fill-mode: forwards;
|
||||
animation-timing-function: cubic-bezier(0,0,.5,1);
|
||||
}
|
||||
|
||||
@keyframes popInAnimation {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
.cardImageContainer.lazy.lazy-image-fadein {
|
||||
opacity: 1;
|
||||
transition: opacity 0.7s;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.cardImageContainer.lazy.lazy-image-fadein-fast {
|
||||
opacity: 1;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
|||
};
|
||||
reader.onabort = function () {
|
||||
loading.hide();
|
||||
console.log('File read cancelled');
|
||||
console.debug('File read cancelled');
|
||||
};
|
||||
|
||||
// Closure to capture the file information.
|
||||
|
@ -74,7 +74,7 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!file.type.startsWith("image/")) {
|
||||
if (!file.type.startsWith('image/')) {
|
||||
require(['toast'], function (toast) {
|
||||
toast(globalize.translate('MessageImageFileTypeAllowed'));
|
||||
});
|
||||
|
@ -87,9 +87,9 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
|||
var dlg = dom.parentWithClass(this, 'dialog');
|
||||
|
||||
var imageType = dlg.querySelector('#selectImageType').value;
|
||||
if (imageType === "None") {
|
||||
require(["toast"], function(toast) {
|
||||
toast(globalize.translate("MessageImageTypeNotSelected"));
|
||||
if (imageType === 'None') {
|
||||
require(['toast'], function(toast) {
|
||||
toast(globalize.translate('MessageImageTypeNotSelected'));
|
||||
});
|
||||
e.preventDefault();
|
||||
return false;
|
||||
|
@ -112,11 +112,11 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
|||
|
||||
page.querySelector('form').addEventListener('submit', onSubmit);
|
||||
|
||||
page.querySelector('#uploadImage').addEventListener("change", function () {
|
||||
page.querySelector('#uploadImage').addEventListener('change', function () {
|
||||
setFiles(page, this.files);
|
||||
});
|
||||
|
||||
page.querySelector('.btnBrowse').addEventListener("click", function () {
|
||||
page.querySelector('.btnBrowse').addEventListener('click', function () {
|
||||
page.querySelector('#uploadImage').click();
|
||||
});
|
||||
}
|
||||
|
|