Merge pull request #1138 from Materialious/update/1.10.15
Update/1.10.15
@@ -174,9 +174,6 @@ Help [translate Materialious via Weblate](https://toolate.othing.xyz/projects/ma
|
||||
## Player
|
||||

|
||||
|
||||
## Transcript
|
||||

|
||||
|
||||
## Settings
|
||||

|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2025-10-08T03:32:17.403921789Z">
|
||||
<DropdownSelection timestamp="2025-10-14T13:17:54.830930475Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="LocalEmulator" identifier="path=/home/ward/.android/avd/Television_4K.avd" />
|
||||
<DeviceId pluginId="LocalEmulator" identifier="path=/home/ward/.android/avd/Pixel_9.avd" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
|
||||
@@ -7,8 +7,8 @@ android {
|
||||
applicationId "us.materialio.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 155
|
||||
versionName "1.10.14"
|
||||
versionCode 156
|
||||
versionName "1.10.15"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
@@ -72,7 +72,11 @@
|
||||
|
||||
|
||||
|
||||
<release version="1.10.14" date="2025-10-08">
|
||||
|
||||
<release version="1.10.15" date="2025-10-15">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.10.15</url>
|
||||
</release>
|
||||
<release version="1.10.14" date="2025-10-08">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.10.14</url>
|
||||
</release>
|
||||
<release version="1.10.13" date="2025-10-08">
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.10.13",
|
||||
"version": "1.10.15",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "Materialious",
|
||||
"version": "1.10.13",
|
||||
"version": "1.10.15",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.0",
|
||||
@@ -22,7 +22,7 @@
|
||||
"jsonfile": "^6.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^38.2.1",
|
||||
"electron": "^38.2.2",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-rebuild": "^3.2.9",
|
||||
"typescript": "^5.9.3"
|
||||
@@ -2558,9 +2558,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "38.2.1",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-38.2.1.tgz",
|
||||
"integrity": "sha512-P4pE2RpRg3kM8IeOK+heg6iAxR5wcXnNHrbVchn7M3GBnYAhjfJRkROusdOro5PlKzdtfKjesbbqaG4MqQXccg==",
|
||||
"version": "38.2.2",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-38.2.2.tgz",
|
||||
"integrity": "sha512-OXSaVNXDlonXDjMRsFNQo1j5tzTKwKXh5/m46IjAFccBcZJZMISI+EjSI07oexIuhvKM8AZLuFuihVn4YjWWrA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.10.14",
|
||||
"version": "1.10.15",
|
||||
"description": "Modern material design for Invidious.",
|
||||
"author": {
|
||||
"name": "Ward Pearce",
|
||||
@@ -35,7 +35,7 @@
|
||||
"jsonfile": "^6.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^38.2.1",
|
||||
"electron": "^38.2.2",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-rebuild": "^3.2.9",
|
||||
"typescript": "^5.9.3"
|
||||
@@ -44,4 +44,4 @@
|
||||
"capacitor",
|
||||
"electron"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,8 +104,8 @@ export class ElectronCapacitorApp {
|
||||
join(app.getAppPath(), 'assets', process.platform === 'win32' ? 'appIcon.ico' : 'appIcon.png')
|
||||
);
|
||||
this.mainWindowState = windowStateKeeper({
|
||||
defaultWidth: 1000,
|
||||
defaultHeight: 800
|
||||
defaultWidth: 1920,
|
||||
defaultHeight: 1080
|
||||
});
|
||||
// Setup preload script path and construct our main window.
|
||||
const preloadPath = join(app.getAppPath(), 'build', 'src', 'preload.js');
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
{
|
||||
"name": "materialious",
|
||||
"version": "1.10.12",
|
||||
"version": "1.10.15",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "materialious",
|
||||
"version": "1.10.12",
|
||||
"version": "1.10.15",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.1",
|
||||
"@capacitor-community/safe-area": "^7.0.0-alpha.1",
|
||||
"@capacitor/android": "^7.0.0",
|
||||
"@capacitor/android": "^7.4.3",
|
||||
"@capacitor/app": "^7.1.0",
|
||||
"@capacitor/browser": "^7.0.0",
|
||||
"@capacitor/clipboard": "^7.0.0",
|
||||
"@capacitor/core": "^7.4.3",
|
||||
"@capacitor/screen-orientation": "^7.0.0",
|
||||
"beercss": "^3.8.0",
|
||||
"beercss": "^3.12.11",
|
||||
"bgutils-js": "^3.2.0",
|
||||
"capacitor-nodejs": "https://github.com/hampoelz/capacitor-nodejs/releases/download/v1.0.0-beta.9/capacitor-nodejs.tgz",
|
||||
"fuse.js": "^7.0.0",
|
||||
@@ -42,7 +42,7 @@
|
||||
"@capacitor/cli": "^7.4.3",
|
||||
"@sveltejs/adapter-auto": "^6.0.1",
|
||||
"@sveltejs/adapter-static": "^3.0.8",
|
||||
"@sveltejs/kit": "^2.37.0",
|
||||
"@sveltejs/kit": "^2.46.5",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.1.4",
|
||||
"@types/eslint": "^8.56.7",
|
||||
"@types/event-source-polyfill": "^1.0.5",
|
||||
@@ -59,7 +59,7 @@
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"svelte": "^5.19.7",
|
||||
"svelte-check": "^4.0.0",
|
||||
"svelte-check": "^4.3.3",
|
||||
"tslib": "^2.7.0",
|
||||
"typescript": "^5.6.3",
|
||||
"vite": "^7.1.9"
|
||||
@@ -1727,9 +1727,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/android": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/android/-/android-7.4.2.tgz",
|
||||
"integrity": "sha512-FZ7M9NwFkljR7EP5eXiE32mAIfZNcYw2CzRMCG3rQu0u0ZaIoeOeq5/oK4YcDnGpNmu8jpngKJqZ+9OiSQSwDg==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/android/-/android-7.4.3.tgz",
|
||||
"integrity": "sha512-VpjvnOcmYGPLgvXRhe3CGLs62Cg7sxOyp77NddCr+Y06qqgnoaj6OGeBVTc2DZlqZ6bSmh15JvFu82pkvmdgfQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@capacitor/core": "^7.4.0"
|
||||
@@ -3272,9 +3272,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/kit": {
|
||||
"version": "2.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.37.0.tgz",
|
||||
"integrity": "sha512-xgKtpjQ6Ry4mdShd01ht5AODUsW7+K1iValPDq7QX8zI1hWOKREH9GjG8SRCN5tC4K7UXmMhuQam7gbLByVcnw==",
|
||||
"version": "2.46.5",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.46.5.tgz",
|
||||
"integrity": "sha512-7TSvMrCdmig5TMyYDW876C5FljhA0wlGixtvASCiqUqtLfmyEEpaysXjC7GhR5mWcGRrCGF+L2Bl1eEaW1wTCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -4307,9 +4307,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/beercss": {
|
||||
"version": "3.10.8",
|
||||
"resolved": "https://registry.npmjs.org/beercss/-/beercss-3.10.8.tgz",
|
||||
"integrity": "sha512-LWwkkhF5F3VAD2z3pkDuWD540l/OUKdway9n+ZW+6naX+bKYPl9PKh/nD47/djYqYeH4jGu9QZcpk7p3Xv7YfQ==",
|
||||
"version": "3.12.11",
|
||||
"resolved": "https://registry.npmjs.org/beercss/-/beercss-3.12.11.tgz",
|
||||
"integrity": "sha512-9NQWL3kxSOb5RPWAV5BPVs64CS72F5Z4HgxusqD07Ho4asaTJB33/SkJBMclQeUQs7hFH2CJOgGgDnIsRk2RyQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"material-dynamic-colors": "^1.1.2"
|
||||
@@ -11673,9 +11673,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-check": {
|
||||
"version": "4.1.6",
|
||||
"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.1.6.tgz",
|
||||
"integrity": "sha512-P7w/6tdSfk3zEVvfsgrp3h3DFC75jCdZjTQvgGJtjPORs1n7/v2VMPIoty3PWv7jnfEm3x0G/p9wH4pecTb0Wg==",
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.3.3.tgz",
|
||||
"integrity": "sha512-RYP0bEwenDXzfv0P1sKAwjZSlaRyqBn0Fz1TVni58lqyEiqgwztTpmodJrGzP6ZT2aHl4MbTvWP6gbmQ3FOnBg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "materialious",
|
||||
"version": "1.10.14",
|
||||
"version": "1.10.15",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
@@ -18,7 +18,7 @@
|
||||
"@capacitor/cli": "^7.4.3",
|
||||
"@sveltejs/adapter-auto": "^6.0.1",
|
||||
"@sveltejs/adapter-static": "^3.0.8",
|
||||
"@sveltejs/kit": "^2.37.0",
|
||||
"@sveltejs/kit": "^2.46.5",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.1.4",
|
||||
"@types/eslint": "^8.56.7",
|
||||
"@types/event-source-polyfill": "^1.0.5",
|
||||
@@ -35,7 +35,7 @@
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"svelte": "^5.19.7",
|
||||
"svelte-check": "^4.0.0",
|
||||
"svelte-check": "^4.3.3",
|
||||
"tslib": "^2.7.0",
|
||||
"typescript": "^5.6.3",
|
||||
"vite": "^7.1.9"
|
||||
@@ -44,13 +44,13 @@
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.1",
|
||||
"@capacitor-community/safe-area": "^7.0.0-alpha.1",
|
||||
"@capacitor/android": "^7.0.0",
|
||||
"@capacitor/android": "^7.4.3",
|
||||
"@capacitor/app": "^7.1.0",
|
||||
"@capacitor/browser": "^7.0.0",
|
||||
"@capacitor/clipboard": "^7.0.0",
|
||||
"@capacitor/core": "^7.4.3",
|
||||
"@capacitor/screen-orientation": "^7.0.0",
|
||||
"beercss": "^3.8.0",
|
||||
"beercss": "^3.12.11",
|
||||
"bgutils-js": "^3.2.0",
|
||||
"capacitor-nodejs": "https://github.com/hampoelz/capacitor-nodejs/releases/download/v1.0.0-beta.9/capacitor-nodejs.tgz",
|
||||
"fuse.js": "^7.0.0",
|
||||
@@ -70,4 +70,4 @@
|
||||
"svelte-persisted-store": "^0.12.0",
|
||||
"youtubei.js": "^15.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
interface Props {
|
||||
comment: Comment;
|
||||
videoId: string;
|
||||
isSubComp?: boolean;
|
||||
}
|
||||
|
||||
let { comment, videoId }: Props = $props();
|
||||
let { comment, videoId, isSubComp = false }: Props = $props();
|
||||
|
||||
let replies: Comments | undefined = $state(undefined);
|
||||
|
||||
@@ -53,7 +54,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="comment">
|
||||
<article class="comment" class:border={!isSubComp}>
|
||||
{#if !$interfaceLowBandwidthMode}
|
||||
<div class="comment-header">
|
||||
{#if userPfp}
|
||||
@@ -95,17 +96,16 @@
|
||||
{#if replies}
|
||||
<div style="margin-left: 5em;">
|
||||
{#each replies.comments as reply}
|
||||
<CommentSelf comment={reply} {videoId} />
|
||||
<CommentSelf comment={reply} {videoId} isSubComp={true} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<style>
|
||||
.comment {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 1em;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
}
|
||||
|
||||
function setupAndroidTVNavigation() {
|
||||
console.log('gridElement', gridElement);
|
||||
if (!$isAndroidTvStore || !gridElement) return;
|
||||
|
||||
focusableItems = Array.from(
|
||||
@@ -117,6 +116,11 @@
|
||||
|
||||
switch (direction) {
|
||||
case 'left':
|
||||
if (currentFocusIndex % columns === 0) {
|
||||
lastFocusIndex = currentFocusIndex;
|
||||
updateTabIndex(currentFocusIndex);
|
||||
return true;
|
||||
}
|
||||
newIndex = Math.max(0, currentFocusIndex - 1);
|
||||
break;
|
||||
case 'right':
|
||||
@@ -128,7 +132,6 @@
|
||||
// Store current position before leaving and ensure it stays focusable
|
||||
lastFocusIndex = currentFocusIndex;
|
||||
updateTabIndex(currentFocusIndex);
|
||||
// Allow the event to bubble up to parent navigation
|
||||
return true;
|
||||
}
|
||||
newIndex = Math.max(0, currentFocusIndex - columns);
|
||||
@@ -218,12 +221,11 @@
|
||||
</script>
|
||||
|
||||
<div class={classes} class:android-container={$isAndroidTvStore}>
|
||||
<div class="space"></div>
|
||||
<div class="grid" bind:this={gridElement}>
|
||||
{#each items as item, index}
|
||||
<ContentColumn>
|
||||
<article
|
||||
class="no-padding android-tv-item"
|
||||
class="no-padding android-tv-item border"
|
||||
class:android-tv-focused={$isAndroidTvStore}
|
||||
style="height: 100%;"
|
||||
id={extractUniqueId(item)}
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
class={classes}
|
||||
height="100%"
|
||||
width="70px"
|
||||
xml:space="preserve"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="50.17 104.37 109.67 88.27"
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
}
|
||||
];
|
||||
|
||||
const tabIds = tabs.map((tab) => tab.id);
|
||||
|
||||
let dialogType = $state('');
|
||||
|
||||
function checkWidth() {
|
||||
@@ -81,14 +83,35 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<dialog id="dialog-settings" class={dialogType}>
|
||||
<nav style="margin-bottom: 1em;">
|
||||
<dialog id="dialog-settings" class={dialogType + ' surface-container'}>
|
||||
<nav class="s m" style="margin-bottom: 1em;">
|
||||
<h4 class="max">{$_('layout.settings')}</h4>
|
||||
<button class="circle transparent" data-ui="#dialog-settings"><i>close</i></button>
|
||||
</nav>
|
||||
|
||||
<div>
|
||||
<nav class="tabbed small" style="outline: none" role="tablist" tabindex="0">
|
||||
<nav class="wrap s">
|
||||
<button class="large small-round secondary max" data-ui="#tab-menu">
|
||||
<i>{tabs[tabIds.indexOf(activeTab)].icon}</i>
|
||||
<span>{tabs[tabIds.indexOf(activeTab)].label}</span>
|
||||
<menu style="width: 100%;" data-ui="#tab-menu" id="tab-menu">
|
||||
{#each tabs as tab, _}
|
||||
<li
|
||||
data-ui="#tab-menu"
|
||||
onclick={() => {
|
||||
activeTab = tab.id;
|
||||
}}
|
||||
role="presentation"
|
||||
>
|
||||
<i>{tab.icon}</i>
|
||||
<span>{tab.label}</span>
|
||||
</li>
|
||||
{/each}
|
||||
</menu>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<nav class="tabbed small m l" style="outline: none" role="tablist" tabindex="0">
|
||||
{#each tabs as tab, index}
|
||||
<a
|
||||
role="tab"
|
||||
@@ -128,6 +151,8 @@
|
||||
</a>
|
||||
{/if}
|
||||
</nav>
|
||||
<div class="space"></div>
|
||||
<div class="divider"></div>
|
||||
{#each tabs as tab, _}
|
||||
<div
|
||||
class="page padding"
|
||||
@@ -146,35 +171,7 @@
|
||||
</dialog>
|
||||
|
||||
<style>
|
||||
dialog {
|
||||
width: 1320px;
|
||||
}
|
||||
|
||||
.tabbed > a {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1320px) {
|
||||
.tabbed {
|
||||
display: flex !important;
|
||||
gap: 0 !important;
|
||||
flex: 0 !important;
|
||||
align-items: start !important;
|
||||
padding: 1em 0 !important;
|
||||
overflow-x: scroll !important;
|
||||
background-color: transparent;
|
||||
border-bottom: solid 1px var(--outline-variant);
|
||||
}
|
||||
|
||||
.tabbed > a {
|
||||
font-size: 1.5rem !important;
|
||||
padding: 0.5em 0.3em !important;
|
||||
border-radius: 3em !important;
|
||||
}
|
||||
|
||||
.tabbed.small {
|
||||
block-size: 100% !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
}
|
||||
|
||||
.sideways-root {
|
||||
height: 110px;
|
||||
height: 112px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
{numberWithCommas(video.viewCount)}
|
||||
{$_('views')} • {video.publishedText}
|
||||
</div>
|
||||
<i>expand_more</i>
|
||||
</nav>
|
||||
</summary>
|
||||
<div class="space"></div>
|
||||
@@ -30,13 +29,15 @@
|
||||
<div style="white-space: pre-line; overflow-wrap: break-word;">
|
||||
{@html description}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="scroll">
|
||||
{#if video.keywords}
|
||||
{#each video.keywords as keyword}
|
||||
<a href={`/search/${encodeURIComponent(keyword)}`} class="chip">{keyword}</a>
|
||||
{/each}
|
||||
{/if}
|
||||
</nav>
|
||||
<article class="border">
|
||||
<nav class="scroll">
|
||||
{#if video.keywords}
|
||||
{#each video.keywords as keyword}
|
||||
<a href={`/search/${encodeURIComponent(keyword)}`} class="chip">{keyword}</a>
|
||||
{/each}
|
||||
{/if}
|
||||
</nav>
|
||||
</article>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
@@ -9,21 +9,19 @@
|
||||
</script>
|
||||
|
||||
{#await returnYTDislikes then returnYTDislikes}
|
||||
{#if returnYTDislikes}
|
||||
<nav class="no-space">
|
||||
<button style="cursor: default;" class="border left-round">
|
||||
<nav class="no-space">
|
||||
{#if returnYTDislikes}
|
||||
<button style="cursor: default;margin-right: 0.5em;" class="border">
|
||||
<i class="small">thumb_up</i>
|
||||
<span>{cleanNumber(returnYTDislikes.likes)}</span>
|
||||
</button>
|
||||
<button style="cursor: default;margin-right: 0.5em;" class="border right-round">
|
||||
<i class="small">thumb_down_alt</i>
|
||||
<i class="small" style="margin-left: 0.5em;">thumb_down_alt</i>
|
||||
<span>{cleanNumber(returnYTDislikes.dislikes)}</span>
|
||||
</button>
|
||||
</nav>
|
||||
{:else}
|
||||
<button style="cursor: default;margin-right: 0.5em;" class="border">
|
||||
<i class="small">thumb_up</i>
|
||||
<span>{cleanNumber(video.likeCount)}</span>
|
||||
</button>
|
||||
{/if}
|
||||
{:else}
|
||||
<button style="cursor: default;margin-right: 0.5em;" class="border">
|
||||
<i class="small">thumb_up</i>
|
||||
<span>{cleanNumber(video.likeCount)}</span>
|
||||
</button>
|
||||
{/if}
|
||||
</nav>
|
||||
{/await}
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
article {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
a,
|
||||
button,
|
||||
.button {
|
||||
border-radius: 0.5rem !important;
|
||||
}
|
||||
|
||||
.thumbnail-corner {
|
||||
padding: 0.1em 0.4em;
|
||||
}
|
||||
@@ -20,45 +30,20 @@ nav.bottom {
|
||||
}
|
||||
|
||||
main.root {
|
||||
padding-top: 7em !important;
|
||||
padding-bottom: 5em !important;
|
||||
max-height: 100vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
nav.left {
|
||||
padding-top: 2em;
|
||||
}
|
||||
|
||||
dialog {
|
||||
padding-top: calc(var(--safe-area-inset-top) + 1rem) !important;
|
||||
}
|
||||
|
||||
.root-not-tv {
|
||||
padding-left: 7em !important;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 1em !important;
|
||||
}
|
||||
|
||||
button.row {
|
||||
background-color: transparent !important;
|
||||
border: none !important;
|
||||
color: var(--on-surface) !important;
|
||||
width: 100%;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
button.row:hover {
|
||||
box-shadow: none !important;
|
||||
background-color: transparent !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1000px) {
|
||||
menu.mobile {
|
||||
z-index: 9999 !important;
|
||||
position: fixed !important;
|
||||
top: 20% !important;
|
||||
width: 100% !important;
|
||||
|
||||
@@ -18,12 +18,14 @@
|
||||
visibility: visible !important;
|
||||
z-index: 99999999 !important;
|
||||
pointer-events: auto !important;
|
||||
pointer-events: auto !important;
|
||||
max-height: 400px !important;
|
||||
}
|
||||
|
||||
.shaka-overflow-menu button,
|
||||
.shaka-settings-menu button {
|
||||
color: var(--text) !important;
|
||||
border: none !important;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 650px) {
|
||||
@@ -44,7 +46,6 @@
|
||||
left: 50% !important;
|
||||
height: 50vh !important;
|
||||
transform: translate(-50%, -50%) !important;
|
||||
pointer-events: all !important;
|
||||
pointer-events: auto !important;
|
||||
opacity: 1 !important;
|
||||
visibility: visible !important;
|
||||
|
||||
@@ -174,7 +174,8 @@
|
||||
"searchHistory": "Suchverlauf",
|
||||
"companionUrl": "Companion URL",
|
||||
"expandChapters": "Kapitel standardmäßig ausklappen",
|
||||
"displayThumbnailAvatars": "Vorschaubild-Avatare (Langsam)"
|
||||
"displayThumbnailAvatars": "Vorschaubild-Avatare (Langsam)",
|
||||
"about": "Über"
|
||||
},
|
||||
"subscribe": "Abonnieren",
|
||||
"recommendedVideos": "Vorgeschlagene Videos",
|
||||
@@ -185,5 +186,7 @@
|
||||
"invalidInstance": "Bitte prüfe die URL. Wenn sie korrekt ist, ist die Instanz möglicherweise außer Betrieb oder unterstützt keine Clients von Drittanbietern.",
|
||||
"login": "Anmeldung",
|
||||
"premium": "YouTube-Premium-Inhalte können auf Materialious nicht angeschaut werden.",
|
||||
"isUpcoming": "Video ist noch nicht in einem anschaubaren Zustand."
|
||||
"isUpcoming": "Video ist noch nicht in einem anschaubaren Zustand.",
|
||||
"version": "Version",
|
||||
"contributors": "Mitwirkende"
|
||||
}
|
||||
|
||||
@@ -86,7 +86,8 @@
|
||||
"syncPartyWarning": "Bitte denk dra, dass dini IP für die vo dir iigladne Benutzer sichtbar isch.",
|
||||
"displayThumbnailAvatars": "Vorschaubild-Avatar (Langsam)",
|
||||
"expandDescription": "Beschriibig standardmässig erwiitere",
|
||||
"disableAutoUpdate": "Automatischi Updates deaktiviere"
|
||||
"disableAutoUpdate": "Automatischi Updates deaktiviere",
|
||||
"about": "Über"
|
||||
},
|
||||
"videos": "Videos",
|
||||
"cancel": "Abbreche",
|
||||
@@ -185,5 +186,7 @@
|
||||
"invalidInstance": "Bitte prüef d URL. Wenn si korrekt isch, isch d Instanz möglicherwiis usser Betriib oder unterstützt kei Clients vo Drittaabüüter.",
|
||||
"loginRequired": "Aameldig erforderlich",
|
||||
"isUpcoming": "Video isch nonig imene aaluegbare Zuestand.",
|
||||
"premium": "YouTube-Premium-Inhält chönd uf Materialious nonig aagluegt werde."
|
||||
"premium": "YouTube-Premium-Inhält chönd uf Materialious nonig aagluegt werde.",
|
||||
"version": "Version",
|
||||
"contributors": "Mitwirkendi"
|
||||
}
|
||||
|
||||
@@ -107,7 +107,8 @@
|
||||
"titleOnly": "Csak cím"
|
||||
},
|
||||
"logout": "Kijelentkezés",
|
||||
"companionUrl": "Kiegészítő webcím"
|
||||
"companionUrl": "Kiegészítő webcím",
|
||||
"about": "Névjegy"
|
||||
},
|
||||
"enabled": "Engedélyezve",
|
||||
"donate": "Adományozás",
|
||||
@@ -185,5 +186,7 @@
|
||||
"letterCase": "Címek nagybetűs írásmódja",
|
||||
"unsubscribe": "Leiratkozás",
|
||||
"subscribe": "Feliratkozás",
|
||||
"invidiousBlockWarning": "Az Invidious jelenleg le van tiltva a Google által. Ha ebben az esetben a videók nem töltődnek be, akkor használja ezt a példányt a Materialious-on {android} vagy {desktop} platformon, hogy helyi videó visszatéréssel megkerülje ezt a problémát."
|
||||
"invidiousBlockWarning": "Az Invidious jelenleg le van tiltva a Google által. Ha ebben az esetben a videók nem töltődnek be, akkor használja ezt a példányt a Materialious-on {android} vagy {desktop} platformon, hogy helyi videó visszatéréssel megkerülje ezt a problémát.",
|
||||
"version": "Verzió",
|
||||
"contributors": "Közreműködők"
|
||||
}
|
||||
|
||||
@@ -253,14 +253,7 @@
|
||||
<svelte:head>
|
||||
{@html webManifestLink}
|
||||
|
||||
{#if $isAndroidTvStore}
|
||||
<style>
|
||||
:focus {
|
||||
outline: 4px solid var(--primary);
|
||||
box-shadow: none !important;
|
||||
}
|
||||
</style>
|
||||
{:else if Capacitor.getPlatform() === 'android'}
|
||||
{#if Capacitor.getPlatform() === 'android' && !$isAndroidTvStore}
|
||||
<style>
|
||||
nav.top {
|
||||
height: 120px;
|
||||
@@ -269,166 +262,136 @@
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
{#if !$isAndroidTvStore}
|
||||
<nav class="left m l small">
|
||||
<header></header>
|
||||
<div>
|
||||
<nav class="left m l surface-container" class:tv-nav={$isAndroidTvStore}>
|
||||
<header
|
||||
role="presentation"
|
||||
onclick={() => goto($interfaceDefaultPage)}
|
||||
style="cursor: pointer;"
|
||||
tabindex="-1"
|
||||
class="small-padding"
|
||||
>
|
||||
<Logo />
|
||||
</header>
|
||||
{#each getPages() as navPage}
|
||||
{#if !navPage.requiresAuth || isLoggedIn}
|
||||
<a
|
||||
href={navPage.href}
|
||||
class:active={$page.url.href.endsWith(navPage.href)}
|
||||
data-sveltekit-preload-data="off"
|
||||
<a href={navPage.href} class:active={$page.url.href.endsWith(navPage.href)}
|
||||
><i>{navPage.icon}</i>
|
||||
<div>{navPage.name}</div>
|
||||
</a>
|
||||
{/if}
|
||||
{/each}
|
||||
</nav>
|
||||
{/if}
|
||||
|
||||
<nav class="top" id="top-content">
|
||||
{#if !mobileSearchShow}
|
||||
<button
|
||||
onclick={() => (mobileSearchShow = !mobileSearchShow)}
|
||||
class="transparent s circle large"
|
||||
>
|
||||
<i>search</i>
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if Capacitor.getPlatform() === 'electron'}
|
||||
<nav class="no-space">
|
||||
<button onclick={() => window.history.back()} class="border left-round">
|
||||
<i>arrow_back</i>
|
||||
<nav class="top" id="top-content" class:tv-nav={$isAndroidTvStore}>
|
||||
{#if !mobileSearchShow}
|
||||
<button
|
||||
onclick={() => (mobileSearchShow = !mobileSearchShow)}
|
||||
class="transparent s circle large"
|
||||
>
|
||||
<i>search</i>
|
||||
</button>
|
||||
<button onclick={() => window.history.forward()} class="border right-round">
|
||||
<i>arrow_forward</i>
|
||||
</button>
|
||||
</nav>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<nav
|
||||
role="presentation"
|
||||
onclick={() => goto($interfaceDefaultPage)}
|
||||
style="cursor: pointer;"
|
||||
class="m l"
|
||||
tabindex="-1"
|
||||
>
|
||||
<Logo />
|
||||
<h6 class="l">Materialious</h6>
|
||||
</nav>
|
||||
{#if Capacitor.getPlatform() === 'electron'}
|
||||
<nav class="no-space">
|
||||
<button onclick={() => window.history.back()} class="border">
|
||||
<i>arrow_back</i>
|
||||
</button>
|
||||
<button onclick={() => window.history.forward()} class="border">
|
||||
<i>arrow_forward</i>
|
||||
</button>
|
||||
</nav>
|
||||
{/if}
|
||||
|
||||
<div class="max m l"></div>
|
||||
<div class="max m l"></div>
|
||||
|
||||
<div class="m l">
|
||||
<Search />
|
||||
</div>
|
||||
|
||||
{#if !mobileSearchShow}
|
||||
<div class="max"></div>
|
||||
{/if}
|
||||
|
||||
{#if mobileSearchShow}
|
||||
<div style="width: 100%;">
|
||||
<Search on:searchCancelled={() => (mobileSearchShow = false)} />
|
||||
<div class="m l">
|
||||
<Search />
|
||||
</div>
|
||||
{:else}
|
||||
{#if !Capacitor.isNativePlatform()}
|
||||
<button data-ui="#sync-party" class="circle large transparent">
|
||||
<i class:primary-text={$syncPartyPeerStore}>group</i>
|
||||
<div class="tooltip bottom">{$_('layout.syncParty')}</div>
|
||||
</button>
|
||||
{/if}
|
||||
{#if isLoggedIn}
|
||||
<button class="circle large transparent" onclick={() => ui('#dialog-notifications')}
|
||||
><i>notifications</i>
|
||||
<div class="tooltip bottom">{$_('layout.notifications')}</div>
|
||||
</button>
|
||||
{/if}
|
||||
<button class="circle large transparent" onclick={() => ui('#dialog-settings')}>
|
||||
<i>settings</i>
|
||||
<div class="tooltip bottom">{$_('layout.settings')}</div>
|
||||
</button>
|
||||
|
||||
{#if !isLoggedIn}
|
||||
<button onclick={login} class="circle large transparent">
|
||||
<i>login</i>
|
||||
<div class="tooltip bottom">{$_('layout.login')}</div>
|
||||
</button>
|
||||
{#if !mobileSearchShow}
|
||||
<div class="max"></div>
|
||||
{/if}
|
||||
|
||||
{#if mobileSearchShow}
|
||||
<div style="width: 100%;">
|
||||
<Search on:searchCancelled={() => (mobileSearchShow = false)} />
|
||||
</div>
|
||||
{:else}
|
||||
<button onclick={logout} class="circle large transparent">
|
||||
<i>logout</i>
|
||||
<div class="tooltip bottom">{$_('layout.logout')}</div>
|
||||
{#if !Capacitor.isNativePlatform()}
|
||||
<button data-ui="#sync-party" class="circle large transparent">
|
||||
<i class:primary-text={$syncPartyPeerStore}>group</i>
|
||||
<div class="tooltip bottom">{$_('layout.syncParty')}</div>
|
||||
</button>
|
||||
{/if}
|
||||
{#if isLoggedIn}
|
||||
<button class="circle large transparent" onclick={() => ui('#dialog-notifications')}
|
||||
><i>notifications</i>
|
||||
<div class="tooltip bottom">{$_('layout.notifications')}</div>
|
||||
</button>
|
||||
{/if}
|
||||
<button class="circle large transparent" onclick={() => ui('#dialog-settings')}>
|
||||
<i>settings</i>
|
||||
<div class="tooltip bottom">{$_('layout.settings')}</div>
|
||||
</button>
|
||||
|
||||
{#if !isLoggedIn}
|
||||
<button onclick={login} class="circle large transparent">
|
||||
<i>login</i>
|
||||
<div class="tooltip bottom">{$_('layout.login')}</div>
|
||||
</button>
|
||||
{:else}
|
||||
<button onclick={logout} class="circle large transparent">
|
||||
<i>logout</i>
|
||||
<div class="tooltip bottom">{$_('layout.logout')}</div>
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
</nav>
|
||||
|
||||
<nav class="bottom s">
|
||||
{#each getPages() as navPage}
|
||||
{#if !navPage.requiresAuth || isLoggedIn}
|
||||
<a
|
||||
class="round"
|
||||
href={navPage.href}
|
||||
class:active={$page.url.href.endsWith(navPage.href)}
|
||||
data-sveltekit-preload-data="off"
|
||||
><i>{navPage.icon}</i>
|
||||
<span style="font-size: .8em;">{navPage.name}</span>
|
||||
</a>
|
||||
{/if}
|
||||
{/each}
|
||||
</nav>
|
||||
|
||||
<Settings />
|
||||
|
||||
<dialog class="right" id="dialog-notifications">
|
||||
<nav>
|
||||
<h5 class="max">{$_('layout.notifications')}</h5>
|
||||
<button class="circle transparent" data-ui="#dialog-notifications"><i>close</i></button>
|
||||
</nav>
|
||||
{#if notifications.length === 0}
|
||||
<p>{$_('layout.noNewNotifications')}</p>
|
||||
{:else}
|
||||
{#each notifications as notification}
|
||||
<article class="no-padding">
|
||||
<Thumbnail video={notification}></Thumbnail>
|
||||
</article>
|
||||
|
||||
<nav class="bottom s">
|
||||
{#each getPages() as navPage}
|
||||
{#if !navPage.requiresAuth || isLoggedIn}
|
||||
<a
|
||||
class="round"
|
||||
href={navPage.href}
|
||||
class:active={$page.url.href.endsWith(navPage.href)}
|
||||
data-sveltekit-preload-data="off"
|
||||
><i>{navPage.icon}</i>
|
||||
<span style="font-size: .8em;">{navPage.name}</span>
|
||||
</a>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
</dialog>
|
||||
</nav>
|
||||
|
||||
<main
|
||||
id="main-content"
|
||||
class="responsive max root"
|
||||
tabindex="0"
|
||||
role="region"
|
||||
class:root-not-tv={!$isAndroidTvStore}
|
||||
>
|
||||
{#if $isAndroidTvStore}
|
||||
<div class="tabs">
|
||||
{#each getPages() as navPage}
|
||||
{#if !navPage.requiresAuth || isLoggedIn}
|
||||
<a
|
||||
href={navPage.href}
|
||||
class:active={$page.url.href.endsWith(navPage.href)}
|
||||
class="active"
|
||||
data-sveltekit-preload-data="off"
|
||||
>
|
||||
<i>{navPage.icon}</i>
|
||||
<span>{navPage.name}</span>
|
||||
</a>
|
||||
{/if}
|
||||
<Settings />
|
||||
|
||||
<dialog class="right" id="dialog-notifications">
|
||||
<nav>
|
||||
<h5 class="max">{$_('layout.notifications')}</h5>
|
||||
<button class="circle transparent" data-ui="#dialog-notifications"><i>close</i></button>
|
||||
</nav>
|
||||
{#if notifications.length === 0}
|
||||
<p>{$_('layout.noNewNotifications')}</p>
|
||||
{:else}
|
||||
{#each notifications as notification}
|
||||
<article class="no-padding border">
|
||||
<Thumbnail video={notification}></Thumbnail>
|
||||
</article>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{#if $navigating}
|
||||
<PageLoading />
|
||||
{:else}
|
||||
{@render children?.()}
|
||||
{/if}
|
||||
{/if}
|
||||
</dialog>
|
||||
|
||||
<SyncParty />
|
||||
</main>
|
||||
<main id="main-content" class="responsive max root" tabindex="0" role="region">
|
||||
{#if $navigating}
|
||||
<PageLoading />
|
||||
{:else}
|
||||
{@render children?.()}
|
||||
{/if}
|
||||
|
||||
<SyncParty />
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<dialog class="modal" id="tv-login">
|
||||
<h5>{$_('loginRequired')}</h5>
|
||||
@@ -458,7 +421,8 @@
|
||||
</dialog>
|
||||
|
||||
<style>
|
||||
nav.left a {
|
||||
font-size: 0.8em;
|
||||
.tv-nav {
|
||||
min-inline-size: 0.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
</script>
|
||||
|
||||
{#if data.popularDisabled}
|
||||
<div class="space"></div>
|
||||
|
||||
<nav class="center-align">
|
||||
<p>Popular page has been disabled</p>
|
||||
</nav>
|
||||
|
||||
@@ -10,9 +10,7 @@
|
||||
let { data } = $props();
|
||||
</script>
|
||||
|
||||
<div class="space"></div>
|
||||
|
||||
<article>
|
||||
<article class="border padding">
|
||||
{#if data.playlist.videos}
|
||||
<nav>
|
||||
<a
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div style="margin-top: 1em;">
|
||||
<div style="margin-bottom: 1em;">
|
||||
<div class="tabs left-align min scroll">
|
||||
<a class:active={currentType === 'all'} href="#all" onclick={async () => changeType('all')}>
|
||||
<i>home</i>
|
||||
|
||||
@@ -22,14 +22,6 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="space"></div>
|
||||
<nav class="right-align">
|
||||
<a class="button" href="/subscriptions/manage">
|
||||
<i>subscriptions</i>
|
||||
<span>{$_('subscriptions.manageSubscriptions')}</span>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<ItemsList items={videos ?? []} />
|
||||
|
||||
<InfiniteLoading on:infinite={loadMore} />
|
||||
|
||||
@@ -303,7 +303,7 @@
|
||||
clearTimeout(pauseTimeout);
|
||||
}
|
||||
pauseTimeout = setTimeout(() => {
|
||||
// player.pause();
|
||||
playerElement?.pause();
|
||||
pauseTimerSeconds = 0;
|
||||
clearTimeout(pauseTimeout);
|
||||
}, pauseTimerSeconds * 1000);
|
||||
@@ -313,11 +313,9 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.video.title} | Materialious</title>
|
||||
<title>{data.video.title}</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="space"></div>
|
||||
|
||||
<div class="grid">
|
||||
<div class={`s12 m12 l${theatreMode ? '12' : '9'}`}>
|
||||
<div style="display: flex;justify-content: center;">
|
||||
@@ -343,15 +341,14 @@
|
||||
{#if data.video.lengthSeconds > 360 && !data.video.hlsUrl}
|
||||
<button
|
||||
onclick={() => {
|
||||
if (pauseTimeout) {
|
||||
clearTimeout(pauseTimeout);
|
||||
if (pauseTimerSeconds < 1) {
|
||||
pauseTimerSeconds = 300;
|
||||
}
|
||||
pauseTimerSeconds = 0;
|
||||
ui('#pause-timer');
|
||||
}}
|
||||
class:border={pauseTimerSeconds < 1}
|
||||
>
|
||||
<i>schedule</i>
|
||||
<i>snooze</i>
|
||||
<div class="tooltip">{$_('player.pauseTimer')}</div>
|
||||
</button>
|
||||
{/if}
|
||||
@@ -417,22 +414,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<article class="border">
|
||||
<Description video={data.video} description={data.content.description} />
|
||||
</article>
|
||||
|
||||
{#if data.content.timestamps.length > 0}
|
||||
<article>
|
||||
<article class="border">
|
||||
<details>
|
||||
<summary id="chapter-section" class="bold none">
|
||||
<nav>
|
||||
<div class="max">
|
||||
<p>{$_('player.chapters')}</p>
|
||||
</div>
|
||||
<i>expand_more</i>
|
||||
</nav>
|
||||
</summary>
|
||||
<div class="space"></div>
|
||||
<div class="chapter-list" id="chapters">
|
||||
<ul class="list">
|
||||
{#each data.content.timestamps as timestamp}
|
||||
@@ -465,12 +460,11 @@
|
||||
{/if}
|
||||
|
||||
{#if comments && comments.comments.length > 0}
|
||||
<article>
|
||||
<article class="border">
|
||||
<details>
|
||||
<summary id="comment-section" class="none bold">
|
||||
<nav>
|
||||
<div class="max">{numberWithCommas(comments.commentCount)} {$_('comments')}</div>
|
||||
<i>expand_more</i>
|
||||
</nav>
|
||||
</summary>
|
||||
|
||||
@@ -497,9 +491,9 @@
|
||||
<article
|
||||
style="height: 85vh; position: relative;scrollbar-width: none;"
|
||||
id="playlist"
|
||||
class="scroll no-padding surface-container-high"
|
||||
class="scroll no-padding surface-container border"
|
||||
>
|
||||
<article class="no-elevate" style="position: sticky; top: 0; z-index: 3;">
|
||||
<article class="no-elevate border" style="position: sticky; top: 0; z-index: 3;">
|
||||
<h6>{$playlistCacheStore[data.playlistId].info.title}</h6>
|
||||
<p>
|
||||
{cleanNumber($playlistCacheStore[data.playlistId].info.viewCount)}
|
||||
@@ -552,10 +546,10 @@
|
||||
|
||||
{#each $playlistCacheStore[data.playlistId].videos as playlistVideo}
|
||||
<article
|
||||
class="no-padding primary-border"
|
||||
class="no-padding border"
|
||||
style="margin: .7em;"
|
||||
id={playlistVideo.videoId}
|
||||
class:border={playlistVideo.videoId === data.video.videoId}
|
||||
class:primary-border={playlistVideo.videoId === data.video.videoId}
|
||||
>
|
||||
{#key playlistVideo.videoId}
|
||||
<Thumbnail
|
||||
@@ -569,7 +563,7 @@
|
||||
</article>
|
||||
{:else if data.video.recommendedVideos}
|
||||
{#each data.video.recommendedVideos as recommendedVideo}
|
||||
<article class="no-padding">
|
||||
<article class="no-padding border">
|
||||
{#key recommendedVideo.videoId}
|
||||
<Thumbnail video={recommendedVideo} sideways={true} />
|
||||
{/key}
|
||||
@@ -580,34 +574,39 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<dialog class="modal" id="pause-timer">
|
||||
<div class="field middle-align">
|
||||
<label class="slider">
|
||||
<input
|
||||
type="range"
|
||||
bind:value={pauseTimerSeconds}
|
||||
min="0"
|
||||
step="60"
|
||||
max={data.video.lengthSeconds - playerCurrentTime - 60}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
{#if pauseTimerSeconds > 0}
|
||||
<span class="helper">{$_('player.pauseVideoIn')} {humanizeSeconds(pauseTimerSeconds)}</span>
|
||||
{/if}
|
||||
<dialog
|
||||
id="pause-timer"
|
||||
onclose={(event: Event) => {
|
||||
if (pauseTimerSeconds > 0) setPauseTimer();
|
||||
(event.target as HTMLDialogElement).close();
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<h6>{$_('player.pauseVideoIn')} {humanizeSeconds(pauseTimerSeconds)}</h6>
|
||||
|
||||
<nav class="group">
|
||||
<button onclick={() => (pauseTimerSeconds += 300)} class="left-round">+5 mins</button>
|
||||
<button onclick={() => (pauseTimerSeconds += 1800)} class="no-round">+30 mins</button>
|
||||
<button onclick={() => (pauseTimerSeconds += 3600)} class="no-round">+1 hr</button>
|
||||
<button onclick={() => (pauseTimerSeconds += 7200)} class="right-round">+2 hrs</button>
|
||||
</nav>
|
||||
|
||||
<div class="space"></div>
|
||||
|
||||
<nav class="wrap">
|
||||
<button
|
||||
onclick={() => {
|
||||
pauseTimerSeconds = 0;
|
||||
clearTimeout(pauseTimeout);
|
||||
ui('#pause-timer');
|
||||
}}
|
||||
class="secondary max"
|
||||
>
|
||||
<i>delete</i>
|
||||
<span>Clear</span>
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
<nav class="right-align no-space">
|
||||
<button
|
||||
class="transparent link"
|
||||
onclick={() => {
|
||||
ui('#pause-timer');
|
||||
pauseTimerSeconds = 0;
|
||||
}}>Cancel</button
|
||||
>
|
||||
<button disabled={pauseTimerSeconds < 1} class="transparent link" onclick={setPauseTimer}
|
||||
>Confirm</button
|
||||
>
|
||||
</nav>
|
||||
</dialog>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -123,7 +123,6 @@
|
||||
<article id="shown-info" transition:fade>
|
||||
<h5>{letterCase(data.video.title)}</h5>
|
||||
<Author bind:subscribed video={data.video} />
|
||||
<div class="space"></div>
|
||||
<LikesDislikes video={data.video} returnYTDislikes={data.streamed.returnYTDislikes} />
|
||||
<article class="border">
|
||||
<Description video={data.video} description={data.content.description} />
|
||||
@@ -176,5 +175,7 @@
|
||||
height: 50%;
|
||||
z-index: 101;
|
||||
overflow-y: scroll;
|
||||
border-bottom-left-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { isAndroidTvStore } from '$lib/store';
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
{#if $isAndroidTvStore}
|
||||
<style>
|
||||
:focus {
|
||||
outline: 4px solid var(--primary);
|
||||
box-shadow: none !important;
|
||||
}
|
||||
</style>
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
{@render children?.()}
|
||||
|
Before Width: | Height: | Size: 4.8 MiB After Width: | Height: | Size: 5.7 MiB |
|
Before Width: | Height: | Size: 2.8 MiB After Width: | Height: | Size: 2.3 MiB |
|
Before Width: | Height: | Size: 3.4 MiB After Width: | Height: | Size: 2.9 MiB |
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 3.7 MiB After Width: | Height: | Size: 3.3 MiB |
|
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 928 KiB |
|
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 2.5 MiB |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 923 KiB |
@@ -3,7 +3,7 @@ import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
LATEST_VERSION = "1.10.14"
|
||||
LATEST_VERSION = "1.10.15"
|
||||
RELEASE_DATE = datetime.now().strftime("%Y-%-m-%d") # Format: YYYY-M-D
|
||||
|
||||
WORKING_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "materialious")
|
||||
|
||||