diff --git a/.ci/azure-pipelines.yml b/.ci/azure-pipelines.yml index e6889afb1..0d6b018e0 100644 --- a/.ci/azure-pipelines.yml +++ b/.ci/azure-pipelines.yml @@ -20,24 +20,21 @@ jobs: steps: - task: NodeTool@0 - displayName: 'Install Node.js' + displayName: 'Install Node' inputs: versionSpec: '10.x' - - script: | - yarn install - displayName: 'Install dependencies' + - script: 'yarn install' + displayName: 'Install Dependencies' - - script: | - test -d dist - displayName: 'Check dist directory' + - script: 'test -d dist' + displayName: 'Check Build' - - script: | - yarn pack --filename jellyfin-web.tgz - displayName: 'Build package' + - script: 'yarn pack --filename jellyfin-web.tgz' + displayName: 'Bundle Release' - task: PublishPipelineArtifact@1 - displayName: 'Publish package' + displayName: 'Publish Release' condition: succeeded() inputs: targetPath: '$(Build.SourcesDirectory)/jellyfin-web.tgz' @@ -51,14 +48,12 @@ jobs: steps: - task: NodeTool@0 - displayName: 'Install Node.js' + displayName: 'Install Node' inputs: versionSpec: '10.x' - - script: | - yarn install - displayName: 'Install dependencies' + - script: 'yarn install' + displayName: 'Install Dependencies' - - script: | - yarn run lint + - script: 'yarn run lint' displayName: 'Run ESLint' diff --git a/package.json b/package.json index 76d01b184..09b793cd3 100644 --- a/package.json +++ b/package.json @@ -5,14 +5,12 @@ "repository": "https://github.com/jellyfin/jellyfin-web", "license": "GPL-2.0-or-later", "devDependencies": { - "autoprefixer": "^9.7.3", "clean-webpack-plugin": "^3.0.0", "copy-webpack-plugin": "^5.1.1", "css-loader": "^2.1.0", "eslint": "^5.16.0", "file-loader": "^3.0.1", "html-webpack-plugin": "^3.2.0", - "postcss-loader": "^3.0.0", "style-loader": "^0.23.1", "webpack": "^4.41.0", "webpack-cli": "^3.3.9", diff --git a/postcss.config.js b/postcss.config.js deleted file mode 100644 index a26de7e9f..000000000 --- a/postcss.config.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - plugins: [ - require('autoprefixer') - ] -} diff --git a/scripts/scdup.py b/scripts/scdup.py new file mode 100644 index 000000000..468e31f14 --- /dev/null +++ b/scripts/scdup.py @@ -0,0 +1,41 @@ +import sys +import os +import json + +# load every key in the source language +# check the keys in all translations +# remove keys that only exist in translations + +cwd = os.getcwd() +langdir = cwd + '/../src/strings' +langlst = os.listdir(langdir) + +langlst.remove('en-us.json') +print(langlst) +input('press enter to continue') + +keysus = [] +with open(langdir + '/' + 'en-us.json') as en: + langus = json.load(en) + for key in langus: + keysus.append(key) + +for lang in langlst: + with open(langdir + '/' + lang, 'r') as f: + inde = 2 + if '\n \"' in f.read(): + inde = 4 + f.close() + with open(langdir + '/' + lang, 'r+') as f: + langjson = json.load(f) + langjnew = {} + for key in langjson: + if key in keysus: + langjnew[key] = langjson[key] + f.seek(0) + f.write(json.dumps(langjnew, indent=inde, sort_keys=False, ensure_ascii=False)) + f.write('\n') + f.truncate() + f.close() + +print('DONE') diff --git a/scripts/scgen.py b/scripts/scgen.py new file mode 100644 index 000000000..0d831426e --- /dev/null +++ b/scripts/scgen.py @@ -0,0 +1,40 @@ +import os +import subprocess +import json + +# load all keys in the source language +# check entire codebase for usages +# print unused keys to a text file +# TODO: dynamic string usages cause false positives + +cwd = os.getcwd() +langdir = cwd + '/../src/strings' +langlst = [] +langlst.append('en-us.json') + +# unused keys +dep = [] + +def grep(key): + command = 'grep -r -E "(\(\\\"|\(\'|\{)%s(\\\"|\'|\})" --include=\*.{js,html} --exclude-dir=../src/strings ../src' % key + p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + output = p.stdout.readlines() + if output: + print('DONE: ' + key) + return True + print('UNUSED: ' + key) + dep.append(key) + return False + +for lang in langlst: + with open(langdir + '/' + lang) as f: + langjson = json.load(f) + for key in langjson: + grep(key) + +print(dep) +print('LENGTH: ' + str(len(dep))) +with open('scout.txt', 'w') as out: + for item in dep: + out.write(item + '\n') + out.close() diff --git a/scripts/scrm.py b/scripts/scrm.py new file mode 100644 index 000000000..9bd5bc2a4 --- /dev/null +++ b/scripts/scrm.py @@ -0,0 +1,34 @@ +import sys +import os +import json + +# load text file containing unused keys +# remove the keys from all string files + +cwd = os.getcwd() +langdir = cwd + '/../src/strings' +langlst = os.listdir(langdir) + +keys = [] + +with open('scout.txt', 'r') as f: + for line in f: + keys.append(line.strip('\n')) + +for lang in langlst: + with open(langdir + '/' + lang, 'r') as f: + inde = 2 + if '\n \"' in f.read(): + inde = 4 + f.close() + with open(langdir + '/' + lang, 'r+') as f: + langjson = json.load(f) + for key in keys: + langjson.pop(key, None) + f.seek(0) + f.write(json.dumps(langjson, indent=inde, sort_keys=False, ensure_ascii=False)) + f.write('\n') + f.truncate() + f.close() + +print('DONE') diff --git a/src/addplugin.html b/src/addplugin.html index 309f0f96c..83640033b 100644 --- a/src/addplugin.html +++ b/src/addplugin.html @@ -1,10 +1,7 @@
-
-
-

@@ -13,9 +10,7 @@

-

-
@@ -27,12 +22,12 @@
-

+

${ServerRestartNeededAfterPluginInstall}
-

+

diff --git a/src/apikeys.html b/src/apikeys.html index 43cfae5b1..47f032c1f 100644 --- a/src/apikeys.html +++ b/src/apikeys.html @@ -2,9 +2,7 @@
-

- ${HeaderApiKeys} -

+

${HeaderApiKeys}

@@ -24,4 +22,4 @@
-
\ No newline at end of file +
diff --git a/src/assets/css/dashboard.css b/src/assets/css/dashboard.css index d4928db69..d1f0b540a 100644 --- a/src/assets/css/dashboard.css +++ b/src/assets/css/dashboard.css @@ -1,6 +1,8 @@ .dashboardColumn, .dashboardSections { flex-direction: column; + -webkit-box-orient: vertical; + -webkit-box-direction: normal } .dashboardFooter { @@ -14,6 +16,8 @@ progress { appearance: none; + -moz-appearance: none; + -webkit-appearance: none; margin: 0; background: #ccc !important } @@ -73,17 +77,23 @@ progress[aria-valuenow]:before { div[data-role=controlgroup] a[data-role=button] { display: inline-block !important; margin: 0 !important; + -webkit-box-shadow: none !important; box-shadow: none !important; + -webkit-border-radius: 0; border-radius: 0 } div[data-role=controlgroup] a[data-role=button]:first-child { + -webkit-border-bottom-left-radius: .3125em; border-bottom-left-radius: .3125em; + -webkit-border-top-left-radius: .3125em; border-top-left-radius: .3125em } div[data-role=controlgroup] a[data-role=button]:last-child { + -webkit-border-bottom-right-radius: .3125em; border-bottom-right-radius: .3125em; + -webkit-border-top-right-radius: .3125em; border-top-right-radius: .3125em } @@ -137,14 +147,23 @@ div[data-role=controlgroup] a.ui-btn-active { } .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 } @@ -153,6 +172,7 @@ div[data-role=controlgroup] a.ui-btn-active { } .dashboardSection { + -webkit-flex-shrink: 0; flex-shrink: 0; margin: 0 0 2em } @@ -168,7 +188,11 @@ div[data-role=controlgroup] a.ui-btn-active { @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 } @@ -273,6 +297,7 @@ div[data-role=controlgroup] a.ui-btn-active { } .sessionNowPlayingContent { + -webkit-background-size: cover; background-size: cover; background-repeat: no-repeat; background-position: center center; @@ -371,6 +396,7 @@ div[data-role=controlgroup] a.ui-btn-active { } .disabledUser { + -webkit-filter: grayscale(100%); filter: grayscale(100%) } @@ -392,6 +418,9 @@ div[data-role=controlgroup] a.ui-btn-active { a[data-role=button] { 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; @@ -403,21 +432,37 @@ a[data-role=button] { background: #292929 !important; } -@keyframes rotating { +@-webkit-keyframes rotating { from { + -webkit-transform: rotate(0); transform: rotate(0) } to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg) + } +} + +@keyframes rotating { + from { + -webkit-transform: rotate(0); + transform: rotate(0) + } + + to { + -webkit-transform: rotate(360deg); transform: rotate(360deg) } } .rotatingCircle { + -webkit-animation: rotating 2s linear infinite; animation: rotating 2s linear infinite } .pluginPreviewImg { + -webkit-box-shadow: 0 .0725em .29em 0 rgba(0, 0, 0, .37); box-shadow: 0 .0725em .29em 0 rgba(0, 0, 0, .37) } diff --git a/src/assets/css/fonts.css b/src/assets/css/fonts.css index da5515fc1..12f1eaf4b 100644 --- a/src/assets/css/fonts.css +++ b/src/assets/css/fonts.css @@ -4,6 +4,7 @@ html { html { font-size: 93%; + -webkit-text-size-adjust: 100%; text-size-adjust: 100%; } diff --git a/src/assets/css/librarybrowser.css b/src/assets/css/librarybrowser.css index a6af6dccd..1dd2bcea4 100644 --- a/src/assets/css/librarybrowser.css +++ b/src/assets/css/librarybrowser.css @@ -15,6 +15,7 @@ .headerSelectedPlayer, .itemMiscInfo, .navMenuOptionText { + -o-text-overflow: ellipsis; text-overflow: ellipsis; overflow: hidden } @@ -47,6 +48,8 @@ z-index: 1; margin: 0 !important; top: 6.9em !important; + -webkit-transition: -webkit-transform .2s ease-out; + -o-transition: transform .2s ease-out; transition: transform .2s ease-out } @@ -55,14 +58,17 @@ } .headerUserImage { + -webkit-background-size: contain; background-size: contain; background-repeat: no-repeat; background-position: center center; + -webkit-border-radius: 100em; border-radius: 100em; display: inline-block } .headerUserButtonRound div { + -webkit-border-radius: 100em; border-radius: 100em; background-size: cover; background-repeat: no-repeat; @@ -70,6 +76,7 @@ } .headerButton { + -webkit-flex-shrink: 0; flex-shrink: 0 } @@ -83,25 +90,35 @@ } .pageTitle { + display: -webkit-inline-box; + display: -webkit-inline-flex; display: inline-flex; margin: .3em 0 0 .5em; height: 1.7em; + -webkit-box-align: center; + -webkit-align-items: center; align-items: center; + -webkit-flex-shrink: 1; flex-shrink: 1 } .headerLeft, .skinHeader { - display: flex; + display: -webkit-box; + display: -webkit-flex } .detailButton, .skinHeader { flex-direction: column; + -webkit-flex-direction: column; + -webkit-box-orient: vertical; + -webkit-box-direction: normal } .pageTitleWithLogo { background-position: left center; + -webkit-background-size: contain; background-size: contain; background-repeat: no-repeat; width: 13.2em @@ -121,7 +138,7 @@ .headerLeft, .headerRight { - justify-content: center; + -webkit-box-align: center } .hiddenViewMenuBar .skinHeader { @@ -134,10 +151,13 @@ .headerLeft { display: flex; + -webkit-align-items: center; align-items: center; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; flex-grow: 1; overflow: hidden; - justify-content: left; + justify-content: flex-start; } .sectionTabs { @@ -145,8 +165,13 @@ } .headerRight { + display: -webkit-box; + display: -webkit-flex; display: flex; + -webkit-align-items: center; align-items: center; + -webkit-box-pack: end; + -webkit-justify-content: flex-end; justify-content: flex-end } @@ -155,19 +180,27 @@ } .navMenuOption { + display: -webkit-box !important; + display: -webkit-flex !important; display: flex !important; + -webkit-box-align: center; + -webkit-align-items: center; align-items: center; text-decoration: none; color: inherit; padding: .9em 0 .9em 2.4em !important; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; flex-grow: 1; font-weight: 400 !important; margin: 0 !important; + -webkit-border-radius: 0 !important; border-radius: 0 !important } .navMenuOptionIcon { margin-right: 1.2em; + -webkit-flex-shrink: 0; flex-shrink: 0 } @@ -181,6 +214,8 @@ } .dashboardDocument .skinBody { + -webkit-transition: left ease-in-out .3s, padding ease-in-out .3s; + -o-transition: left ease-in-out .3s, padding ease-in-out .3s; transition: left ease-in-out .3s, padding ease-in-out .3s; position: absolute; top: 0; @@ -210,7 +245,9 @@ z-index: inherit !important; left: 0 !important; top: 0 !important; + -webkit-transform: none !important; transform: none !important; + -webkit-box-shadow: none !important; box-shadow: none !important; width: 20.205em !important; font-size: 94% @@ -293,6 +330,8 @@ } .flexPageTabContent.is-active { + display: -webkit-box !important; + display: -webkit-flex !important; display: flex !important } @@ -308,6 +347,7 @@ margin: 1.5em 0; background: #222; padding: .8em .8em .8em 3em; + -webkit-border-radius: .3em; border-radius: .3em; position: relative } @@ -366,6 +406,7 @@ } .itemBackdrop { + -webkit-background-size: cover; background-size: cover; background-repeat: no-repeat; background-position: center; @@ -468,6 +509,7 @@ position: absolute; top: 14.5%; right: 10.5%; + -webkit-background-size: contain; background-size: contain } @@ -498,6 +540,7 @@ .itemDetailImage { width: 100% !important; box-shadow: 0 .0725em .29em 0 rgba(0, 0, 0, .37); + -webkit-box-shadow: 0 .0725em .29em 0 rgba(0, 0, 0, .37); } @media all and (max-width:62.5em) { @@ -528,8 +571,7 @@ top: 50%; left: 50%; margin: -2.2em 0 0 -2.2em; - border: 2.7px solid rgba(255, 255, 255, .6); - padding: .38em !important; + padding: 0.4em !important; color: rgba(255, 255, 255, .76) } @@ -566,6 +608,8 @@ .detailButton, .mainDetailButtons { display: flex; + display: -webkit-box; + display: -webkit-flex } .itemName { @@ -586,7 +630,10 @@ .mainDetailButtons { display: flex; + -webkit-box-align: center; + -webkit-align-items: center; align-items: center; + -webkit-flex-wrap: wrap; flex-wrap: wrap; margin: 1em 0; } @@ -594,6 +641,7 @@ .recordingFields button { margin-left: 0; margin-right: .5em; + -webkit-flex-shrink: 0; flex-shrink: 0 } @@ -604,7 +652,11 @@ .detailButton { display: flex; flex-direction: column; + -webkit-box-pack: center; + -webkit-justify-content: center; justify-content: center; + -webkit-box-align: center; + -webkit-align-items: center; align-items: center; margin: 0 !important; padding: .5em .7em !important @@ -632,9 +684,18 @@ } .detailButton-content { + display: -webkit-box; + display: -webkit-flex; display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; flex-direction: column; + -webkit-box-pack: center; + -webkit-justify-content: center; justify-content: center; + -webkit-box-align: center; + -webkit-align-items: center; align-items: center } @@ -706,14 +767,21 @@ } .itemMiscInfo { + display: -webkit-box; + display: -webkit-flex; display: flex; + -webkit-flex-wrap: wrap; flex-wrap: wrap; + -webkit-box-align: center; + -webkit-align-items: center; align-items: center } @media all and (max-width:31.25em) { .mobileDetails .itemMiscInfo { text-align: center; + -webkit-box-pack: center; + -webkit-justify-content: center; justify-content: center } @@ -793,6 +861,7 @@ } .btnSyncComplete i { + -webkit-border-radius: 100em; border-radius: 100em } @@ -801,9 +870,14 @@ } .mediaInfoIcons { + display: -webkit-box; + display: -webkit-flex; display: flex; + -webkit-box-align: center; + -webkit-align-items: center; align-items: center; margin: 1em 0; + -webkit-flex-wrap: wrap; flex-wrap: wrap } @@ -841,6 +915,7 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards { .sectionTitleButton { margin-left: 1.5em !important; + -webkit-flex-shrink: 0; flex-shrink: 0 } @@ -850,17 +925,22 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards { .sectionTitleIconButton { margin-left: 1.5em !important; + -webkit-flex-shrink: 0; flex-shrink: 0; font-size: 84% !important; padding: .5em !important } .horizontalItemsContainer { + display: -webkit-box; + display: -webkit-flex; display: flex } .sectionTitleTextButton { margin: 0 !important; + display: -webkit-inline-box !important; + display: -webkit-inline-flex !important; display: inline-flex !important; color: inherit !important } @@ -932,6 +1012,8 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards { } .itemsViewSettingsContainer { + -webkit-box-pack: center; + -webkit-justify-content: center; justify-content: center } diff --git a/src/assets/css/metadataeditor.css b/src/assets/css/metadataeditor.css index c5de6f3ef..542c7c8f2 100644 --- a/src/assets/css/metadataeditor.css +++ b/src/assets/css/metadataeditor.css @@ -28,13 +28,17 @@ .jstree-wholerow-hovered { background: #38c !important; + -webkit-border-radius: 0 !important; border-radius: 0 !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 } diff --git a/src/assets/css/scrollstyles.css b/src/assets/css/scrollstyles.css index 69039ce34..431cd2ba1 100644 --- a/src/assets/css/scrollstyles.css +++ b/src/assets/css/scrollstyles.css @@ -1,5 +1,6 @@ .scrollX { overflow-x: auto; + -webkit-overflow-scrolling: touch; overflow-y: hidden; white-space: nowrap; } @@ -9,11 +10,11 @@ } .hiddenScrollX, .layout-tv .scrollX { - scrollbar-width: none; + -ms-overflow-style: none; } .hiddenScrollX-forced { - scrollbar-width: none; + overflow: -moz-scrollbars-none; } .hiddenScrollX::-webkit-scrollbar, .layout-tv .scrollX::-webkit-scrollbar { @@ -23,21 +24,25 @@ .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; + -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 { diff --git a/src/assets/css/site.css b/src/assets/css/site.css index 649179911..292fc6745 100644 --- a/src/assets/css/site.css +++ b/src/assets/css/site.css @@ -20,12 +20,18 @@ html { .layout-mobile, .layout-tv { + -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 { diff --git a/src/assets/css/videoosd.css b/src/assets/css/videoosd.css index f20abf9d0..c43696dd4 100644 --- a/src/assets/css/videoosd.css +++ b/src/assets/css/videoosd.css @@ -1,6 +1,9 @@ .chapterThumbTextContainer, .videoOsdBottom { user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none } .osdPoster img, @@ -12,10 +15,13 @@ } .osdHeader { + -webkit-transition: opacity .3s ease-out; + -o-transition: opacity .3s ease-out; transition: opacity .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; } @@ -29,13 +35,17 @@ } .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 } .chapterThumb { background-position: center center; + -webkit-background-size: contain; background-size: contain; background-repeat: no-repeat; border: 0; @@ -81,12 +91,20 @@ 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 { @@ -94,35 +112,51 @@ } .osdControls { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; flex-grow: 1 } .videoOsdBottom .buttons { padding: .25em 0 0; + display: -webkit-box; + display: -webkit-flex; display: flex; + -webkit-flex-wrap: wrap; flex-wrap: wrap; + -webkit-box-align: center; + -webkit-align-items: center; align-items: center } .osdVolumeSliderContainer { width: 9em; + -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; display: flex; + -webkit-align-items: center; align-items: center } .osdTimeText { margin-left: 1em; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; user-select: none } @@ -136,10 +170,15 @@ 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; 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, @@ -149,6 +188,7 @@ .osdMediaInfo { display: flex; + -webkit-align-items: center; align-items: center } @@ -157,14 +197,23 @@ } .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 } .osdMainTextContainer { + -webkit-box-align: baseline; + -webkit-align-items: baseline; align-items: baseline } @@ -172,13 +221,28 @@ margin-left: auto; } +@-moz-keyframes spin { + 100% { + -moz-transform: rotate(360deg); + } +} + +@-webkit-keyframes spin { + 100% { + -webkit-transform: rotate(360deg); + } +} + @keyframes spin { 100% { + -webkit-transform: rotate(360deg); transform:rotate(360deg); } } .osdMediaStatus .animate { + -webkit-animation:spin 4s linear infinite; + -moz-animation:spin 4s linear infinite; animation:spin 4s linear infinite; } diff --git a/src/themes/logodark.png b/src/assets/img/banner-dark.png similarity index 100% rename from src/themes/logodark.png rename to src/assets/img/banner-dark.png diff --git a/src/themes/logowhite.png b/src/assets/img/banner-light.png similarity index 100% rename from src/themes/logowhite.png rename to src/assets/img/banner-light.png diff --git a/src/assets/img/logo.png b/src/assets/img/icon-transparent.png similarity index 100% rename from src/assets/img/logo.png rename to src/assets/img/icon-transparent.png diff --git a/src/bundle.js b/src/bundle.js index 54623fab7..28626c2a0 100644 --- a/src/bundle.js +++ b/src/bundle.js @@ -17,7 +17,7 @@ _define("fetch", function() { }); // flvjs -var flvjs = require("flv.js").default; +var flvjs = require("flv.js/dist/flv").default; _define("flvjs", function() { return flvjs; }); diff --git a/src/components/backdrop/backdrop.js b/src/components/backdrop/backdrop.js index ae07ac3ab..7320978f7 100644 --- a/src/components/backdrop/backdrop.js +++ b/src/components/backdrop/backdrop.js @@ -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) { @@ -236,16 +236,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 +316,4 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./backdro clear: clearBackdrop, externalBackdrop: externalBackdrop }; -}); \ No newline at end of file +}); diff --git a/src/components/cardbuilder/card.css b/src/components/cardbuilder/card.css index 5520ce2c7..96d0698f4 100644 --- a/src/components/cardbuilder/card.css +++ b/src/components/cardbuilder/card.css @@ -18,6 +18,7 @@ button { padding: 0; display: block; color: inherit !important; + -webkit-tap-highlight-color: rgba(0,0,0,0); outline: none !important; cursor: pointer; contain: layout style; @@ -79,6 +80,8 @@ 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; @@ -146,6 +149,7 @@ button { background-size: cover; background-repeat: no-repeat; background-position: center center; + display: -webkit-flex; display: flex; align-items: center; justify-content: center; @@ -179,6 +183,7 @@ button { margin: 0 !important; /* Needed in safari */ height: 100%; + -webkit-tap-highlight-color: rgba(0,0,0,0); outline: none !important; contain: strict; } @@ -342,6 +347,7 @@ button { border: 0 !important; padding: 0 !important; cursor: pointer; + -webkit-tap-highlight-color: rgba(0,0,0,0); outline: none !important; color: inherit; vertical-align: middle; diff --git a/src/components/dialogHelper/dialoghelper.css b/src/components/dialogHelper/dialoghelper.css index aa4145e01..2cc20b5ff 100644 --- a/src/components/dialogHelper/dialoghelper.css +++ b/src/components/dialogHelper/dialoghelper.css @@ -16,6 +16,7 @@ .dialog { margin: 0; border-radius: .2em; + -webkit-font-smoothing: antialiased; border: 0; padding: 0; will-change: transform, opacity; diff --git a/src/components/emby-scroller/emby-scroller.js b/src/components/emby-scroller/emby-scroller.js index 0b36483be..f943047f5 100644 --- a/src/components/emby-scroller/emby-scroller.js +++ b/src/components/emby-scroller/emby-scroller.js @@ -155,7 +155,7 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro initCenterFocus(this, this.scroller); } - if (bindHeader) { + if (bindHeader && layoutManager.mobile) { initHeadroom(this); } diff --git a/src/components/filterdialog/style.css b/src/components/filterdialog/style.css index 69a82d240..9851c2d7b 100644 --- a/src/components/filterdialog/style.css +++ b/src/components/filterdialog/style.css @@ -5,6 +5,7 @@ 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 @@ -28,8 +29,8 @@ @media all and (min-width:400px) { .dynamicFilterDialog { - width: 300px; - margin-left: -150px !important; + width: 20.16em; + margin-left: -10.08em !important; left: 50% !important } } diff --git a/src/components/homesections/homesections.css b/src/components/homesections/homesections.css index 5df2440f8..45df67c48 100644 --- a/src/components/homesections/homesections.css +++ b/src/components/homesections/homesections.css @@ -13,11 +13,13 @@ .homeLibraryIcon { margin-left: .5em; margin-right: .5em; + -webkit-flex-shrink: 0; flex-shrink: 0 } .homeLibraryText { white-space: nowrap; + -o-text-overflow: ellipsis; text-overflow: ellipsis; overflow: hidden } diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index e52ac0ec7..a71b053a2 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -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, { @@ -1429,7 +1425,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa if (!appHost.supports('htmlvideoautoplay')) { html += '
- -
@@ -118,5 +116,4 @@
- diff --git a/src/dashboardgeneral.html b/src/dashboardgeneral.html index 91708f382..6387128d5 100644 --- a/src/dashboardgeneral.html +++ b/src/dashboardgeneral.html @@ -1,10 +1,7 @@
-
-
-

${TabSettings}

@@ -31,9 +28,7 @@ ${LaunchWebAppOnStartup} -
- ${LaunchWebAppOnStartupHelp} -
+
${LaunchWebAppOnStartupHelp}
@@ -94,7 +89,6 @@
-
diff --git a/src/device.html b/src/device.html index b63d298ca..11fc9671b 100644 --- a/src/device.html +++ b/src/device.html @@ -1,11 +1,7 @@
-
- -
-

@@ -18,10 +14,11 @@
- +
-
-
\ No newline at end of file + diff --git a/src/devices.html b/src/devices.html index b05f10fa1..4e6552f05 100644 --- a/src/devices.html +++ b/src/devices.html @@ -7,9 +7,7 @@ ${Help} - -
-
+
- \ No newline at end of file + diff --git a/src/dlnasettings.html b/src/dlnasettings.html index 8c44f751a..872d546a5 100644 --- a/src/dlnasettings.html +++ b/src/dlnasettings.html @@ -8,7 +8,7 @@

${TabSettings}

- ${Help} + ${Help}
diff --git a/src/elements/emby-button/emby-button.css b/src/elements/emby-button/emby-button.css index ee15e2e12..2201b2cd7 100644 --- a/src/elements/emby-button/emby-button.css +++ b/src/elements/emby-button/emby-button.css @@ -9,6 +9,9 @@ font-family: inherit; color: inherit; outline-width: 0; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; user-select: none; cursor: pointer; z-index: 0; @@ -21,6 +24,8 @@ outline: none !important; position: relative; font-weight: 600; + /* Disable webkit tap highlighting */ + -webkit-tap-highlight-color: rgba(0,0,0,0); text-decoration: none; /* Not crazy about this but it normalizes heights between anchors and buttons */ line-height: 1.35; @@ -94,6 +99,9 @@ font-size: inherit; font-family: inherit; color: inherit; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; user-select: none; cursor: pointer; z-index: 0; @@ -110,6 +118,8 @@ position: relative; overflow: hidden; border-radius: 50%; + /* Disable webkit tap highlighting */ + -webkit-tap-highlight-color: rgba(0,0,0,0); justify-content: center; transform-origin: center; transition: 0.2s; diff --git a/src/elements/emby-checkbox/emby-checkbox.css b/src/elements/emby-checkbox/emby-checkbox.css index 4e27928e2..a31691f9d 100644 --- a/src/elements/emby-checkbox/emby-checkbox.css +++ b/src/elements/emby-checkbox/emby-checkbox.css @@ -38,6 +38,9 @@ margin: 0; padding: 0; opacity: 0; + -ms-appearance: none; + -moz-appearance: none; + -webkit-appearance: none; appearance: none; border: none; } @@ -121,3 +124,13 @@ padding: 0; } } + +@-webkit-keyframes repaintChrome { + from { + padding: 0; + } + + to { + padding: 0; + } +} diff --git a/src/elements/emby-input/emby-input.css b/src/elements/emby-input/emby-input.css index 57a46ec7b..d888eb570 100644 --- a/src/elements/emby-input/emby-input.css +++ b/src/elements/emby-input/emby-input.css @@ -10,8 +10,10 @@ font-weight: inherit; padding: .4em .25em; /* Prevent padding from causing width overflow */ + -webkit-box-sizing: border-box; box-sizing: border-box; outline: none !important; + -webkit-tap-highlight-color: rgba(0,0,0,0); width: 100%; } @@ -33,5 +35,6 @@ } .emby-input-iconbutton { + -webkit-align-self: flex-end; align-self: flex-end; } diff --git a/src/elements/emby-radio/emby-radio.css b/src/elements/emby-radio/emby-radio.css index 6b8575bc8..25fdc5b93 100644 --- a/src/elements/emby-radio/emby-radio.css +++ b/src/elements/emby-radio/emby-radio.css @@ -27,6 +27,9 @@ margin: 0; padding: 0; opacity: 0; + -ms-appearance: none; + -moz-appearance: none; + -webkit-appearance: none; appearance: none; border: none; } @@ -67,13 +70,17 @@ cursor: pointer; transition-duration: 0.28s; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-property: -webkit-transform; transition-property: transform; + transition-property: transform, -webkit-transform; + -webkit-transform: scale3d(0, 0, 0); transform: scale3d(0, 0, 0); border-radius: 50%; background: #00a4dc; } .mdl-radio__button:checked + .mdl-radio__label + .mdl-radio__outer-circle + .mdl-radio__inner-circle { + -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } diff --git a/src/elements/emby-select/emby-select.css b/src/elements/emby-select/emby-select.css index 4aff8cab9..76b28c420 100644 --- a/src/elements/emby-select/emby-select.css +++ b/src/elements/emby-select/emby-select.css @@ -12,6 +12,7 @@ /* Prevent padding from causing width overflow */ box-sizing: border-box; outline: none !important; + -webkit-tap-highlight-color: rgba(0,0,0,0); width: 100%; } @@ -19,6 +20,8 @@ background: none !important; border-color: transparent !important; color: inherit !important; + -webkit-appearance: none; + -moz-appearance: none; appearance: none; } @@ -38,6 +41,7 @@ .emby-select-focusscale { transition: transform 180ms ease-out !important; + -webkit-transform-origin: center center; transform-origin: center center; } @@ -73,6 +77,7 @@ } .emby-select-withcolor { + -webkit-appearance: none; appearance: none; border-radius: .2em; } diff --git a/src/elements/emby-slider/emby-slider.css b/src/elements/emby-slider/emby-slider.css index 6fc861deb..71f260772 100644 --- a/src/elements/emby-slider/emby-slider.css +++ b/src/elements/emby-slider/emby-slider.css @@ -1,21 +1,32 @@ _:-ms-input-placeholder { appearance: none; + -ms-appearance: none; height: 2.223em; margin: 0; } .mdl-slider { width: 100%; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; appearance: none; height: 150%;/*150% is needed, else ie and edge won't display the thumb properly*/ background: transparent; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; user-select: none; outline: 0; color: #00a4dc; + -webkit-align-self: center; + -ms-flex-item-align: center; align-self: center; z-index: 1; cursor: pointer; margin: 0; + /* Disable webkit tap highlighting */ + -webkit-tap-highlight-color: rgba(0,0,0,0); display: block; } @@ -59,7 +70,7 @@ _:-ms-input-placeholder { } .mdl-slider::-webkit-slider-thumb { - appearance: none; + -webkit-appearance: none; width: 1.2em; height: 1.2em; box-sizing: border-box; @@ -98,7 +109,7 @@ _:-ms-input-placeholder { } .mdl-slider::-ms-thumb { - appearance: none; + -webkit-appearance: none; width: 1.8em; height: 1.8em; box-sizing: border-box; diff --git a/src/elements/emby-textarea/emby-textarea.css b/src/elements/emby-textarea/emby-textarea.css index 0dab1b1ec..6ac826223 100644 --- a/src/elements/emby-textarea/emby-textarea.css +++ b/src/elements/emby-textarea/emby-textarea.css @@ -13,6 +13,7 @@ /* Prevent padding from causing width overflow */ box-sizing: border-box; outline: none !important; + -webkit-tap-highlight-color: rgba(0,0,0,0); width: 100%; } diff --git a/src/elements/emby-toggle/emby-toggle.css b/src/elements/emby-toggle/emby-toggle.css index 3b14b8cf0..fb91419cb 100644 --- a/src/elements/emby-toggle/emby-toggle.css +++ b/src/elements/emby-toggle/emby-toggle.css @@ -9,6 +9,10 @@ margin: 0; padding: 0; overflow: visible; + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; user-select: none; flex-direction: row-reverse; justify-content: flex-end; @@ -24,6 +28,9 @@ margin: 0; padding: 0; opacity: 0; + -ms-appearance: none; + -moz-appearance: none; + -webkit-appearance: none; appearance: none; border: none; } @@ -82,6 +89,7 @@ position: absolute; top: 50%; left: 50%; + -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); display: inline-block; box-sizing: border-box; diff --git a/src/encodingsettings.html b/src/encodingsettings.html index da7f6c9c6..3d67544c0 100644 --- a/src/encodingsettings.html +++ b/src/encodingsettings.html @@ -22,6 +22,7 @@
${LabelHardwareAccelerationTypeHelp}
+
${LabelVaapiDeviceHelp}
@@ -142,9 +143,11 @@
- +
- \ No newline at end of file + diff --git a/src/forgotpassword.html b/src/forgotpassword.html index aac53ed29..d4ed0d417 100644 --- a/src/forgotpassword.html +++ b/src/forgotpassword.html @@ -1,9 +1,6 @@
-
-
-

${HeaderForgotPassword}

@@ -23,6 +20,5 @@
-
- \ No newline at end of file + diff --git a/src/forgotpasswordpin.html b/src/forgotpasswordpin.html index 0eb8b8a1a..3b1ba0d37 100644 --- a/src/forgotpasswordpin.html +++ b/src/forgotpasswordpin.html @@ -1,9 +1,6 @@
-
-
-

${HeaderPasswordReset}

@@ -22,6 +19,5 @@
-
- \ No newline at end of file + diff --git a/src/itemdetails.html b/src/itemdetails.html index 038b4b11f..8e3584e29 100644 --- a/src/itemdetails.html +++ b/src/itemdetails.html @@ -45,7 +45,7 @@ diff --git a/src/librarydisplay.html b/src/librarydisplay.html index b5510ddb1..25dce4822 100644 --- a/src/librarydisplay.html +++ b/src/librarydisplay.html @@ -47,11 +47,11 @@
${OptionSaveMetadataAsHiddenHelp}
-
+
- \ No newline at end of file + diff --git a/src/livetvguideprovider.html b/src/livetvguideprovider.html index 86bf3ea7d..d0d52aac2 100644 --- a/src/livetvguideprovider.html +++ b/src/livetvguideprovider.html @@ -1,11 +1,7 @@
-
- -
- -
+
-
\ No newline at end of file + diff --git a/src/login.html b/src/login.html index 629f43431..21c9d8a34 100644 --- a/src/login.html +++ b/src/login.html @@ -1,11 +1,7 @@
-
-
-

${HeaderPleaseSignIn}

-
@@ -27,13 +23,14 @@ +
-
-
+
+
@@ -56,6 +53,5 @@

-
-
\ No newline at end of file +
diff --git a/src/manifest.json b/src/manifest.json index a87b086da..fed1177e2 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,5 +1,4 @@ { - "name": "Jellyfin", "description": "Jellyfin: the Free Software Media System.", "lang": "en-US", @@ -8,7 +7,8 @@ "theme_color": "#101010", "background_color": "#101010", "display": "standalone", - "icons": [{ + "icons": [ + { "sizes": "72x72", "src": "touchicon72.png", "type": "image/png" diff --git a/src/networking.html b/src/networking.html index 35468a94c..0a08166cc 100644 --- a/src/networking.html +++ b/src/networking.html @@ -5,7 +5,7 @@

${TabNetworking}

- ${Help} + ${Help}
diff --git a/src/nowplaying.html b/src/nowplaying.html index 44b7e3816..bc595a6c9 100644 --- a/src/nowplaying.html +++ b/src/nowplaying.html @@ -72,67 +72,72 @@
- diff --git a/src/usernew.html b/src/usernew.html index 2e091e8d9..bca1e72fe 100644 --- a/src/usernew.html +++ b/src/usernew.html @@ -5,7 +5,7 @@

${HeaderAddUser}

- ${Help} + ${Help}
@@ -59,4 +59,4 @@
- \ No newline at end of file + diff --git a/src/userparentalcontrol.html b/src/userparentalcontrol.html index 302969b6c..6c3591333 100644 --- a/src/userparentalcontrol.html +++ b/src/userparentalcontrol.html @@ -4,7 +4,7 @@

- ${Help} + ${Help}
diff --git a/src/userpassword.html b/src/userpassword.html index 3f65c214f..f38e39599 100644 --- a/src/userpassword.html +++ b/src/userpassword.html @@ -4,7 +4,7 @@

- ${Help} + ${Help}
diff --git a/src/videoosd.html b/src/videoosd.html index e4089468b..4d18787a5 100644 --- a/src/videoosd.html +++ b/src/videoosd.html @@ -1,27 +1,19 @@
-
- -
-
-
- +
+
- -
- -
+
-

- autorenew ${FetchingData} + autorenew + ${FetchingData}
-
-
+
@@ -76,7 +68,11 @@ airplay -
+
+ + + +