@@ -204,8 +204,11 @@ Help [translate Materialious via Weblate](https://toolate.othing.xyz/projects/ma
|
||||
## Mobile
|
||||
<img src="./previews/mobile-preview.png" style="height: 500px"/>
|
||||
|
||||
## Android TV
|
||||

|
||||
## Android TV Home
|
||||

|
||||
|
||||
## Android TV Player
|
||||

|
||||
|
||||
## Player
|
||||

|
||||
|
||||
@@ -7,8 +7,8 @@ android {
|
||||
applicationId "us.materialio.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 131
|
||||
versionName "1.9.14"
|
||||
versionCode 132
|
||||
versionName "1.9.15"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
@@ -66,7 +66,11 @@
|
||||
|
||||
|
||||
|
||||
<release version="1.9.14" date="2025-6-23">
|
||||
|
||||
<release version="1.9.15" date="2025-6-23">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.9.15</url>
|
||||
</release>
|
||||
<release version="1.9.14" date="2025-6-23">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.9.14</url>
|
||||
</release>
|
||||
<release version="1.9.13" date="2025-6-19">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.9.14",
|
||||
"version": "1.9.15",
|
||||
"description": "Modern material design for Invidious.",
|
||||
"author": {
|
||||
"name": "Ward Pearce",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "materialious",
|
||||
"version": "1.9.14",
|
||||
"version": "1.9.15",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
|
||||
@@ -585,7 +585,7 @@
|
||||
playerElement.addEventListener('ended', async () => {
|
||||
if (!data.playlistId) {
|
||||
if ($playerAutoplayNextByDefaultStore) {
|
||||
goto(`/watch/${data.video.recommendedVideos[0].videoId}`);
|
||||
goto(`/${$isAndroidTvStore ? 'tv' : 'watch'}/${data.video.recommendedVideos[0].videoId}`);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -628,7 +628,9 @@
|
||||
});
|
||||
}
|
||||
|
||||
goto(`/watch/${goToVideo.videoId}?playlist=${data.playlistId}`);
|
||||
goto(
|
||||
`/${$isAndroidTvStore ? 'tv' : 'watch'}/${goToVideo.videoId}?playlist=${data.playlistId}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -32,10 +32,9 @@
|
||||
import ui from 'beercss';
|
||||
import 'material-dynamic-colors';
|
||||
import { onMount } from 'svelte';
|
||||
import { _, initI18n } from '$lib/i18n';
|
||||
import { _ } from '$lib/i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { pwaInfo } from 'virtual:pwa-info';
|
||||
import androidTv from '$lib/android/plugins/androidTv';
|
||||
import Mousetrap from 'mousetrap';
|
||||
|
||||
let { children } = $props();
|
||||
@@ -186,8 +185,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
$isAndroidTvStore = (await androidTv.isAndroidTv()).value;
|
||||
|
||||
if ($isAndroidTvStore) {
|
||||
const topContent = document.getElementById('top-content') as HTMLElement;
|
||||
Mousetrap.bind('down', () => {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import VideoList from '$lib/components/VideoList.svelte';
|
||||
import { getBestThumbnail, proxyGoogleImage } from '$lib/images';
|
||||
import { cleanNumber } from '$lib/numbers';
|
||||
import { authStore, interfaceLowBandwidthMode } from '$lib/store';
|
||||
import { authStore, interfaceLowBandwidthMode, isAndroidTvStore } from '$lib/store';
|
||||
import { Clipboard } from '@capacitor/clipboard';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { onMount } from 'svelte';
|
||||
@@ -131,39 +131,41 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="s12 m12 l5">
|
||||
<button class="border">
|
||||
<i>share</i>
|
||||
<span>{$_('player.share.title')}</span>
|
||||
<menu class="no-wrap mobile">
|
||||
{#if !Capacitor.isNativePlatform()}
|
||||
{#if !$isAndroidTvStore}
|
||||
<div class="s12 m12 l5">
|
||||
<button class="border">
|
||||
<i>share</i>
|
||||
<span>{$_('player.share.title')}</span>
|
||||
<menu class="no-wrap mobile">
|
||||
{#if !Capacitor.isNativePlatform()}
|
||||
<li
|
||||
class="row"
|
||||
role="presentation"
|
||||
onclick={async () => {
|
||||
await Clipboard.write({ string: location.href });
|
||||
(document.activeElement as HTMLElement)?.blur();
|
||||
}}
|
||||
>
|
||||
{$_('player.share.materialiousLink')}
|
||||
</li>
|
||||
{/if}
|
||||
|
||||
<li
|
||||
class="row"
|
||||
role="presentation"
|
||||
onclick={async () => {
|
||||
await Clipboard.write({ string: location.href });
|
||||
await Clipboard.write({
|
||||
string: `https://www.youtube.com/channel/${data.channel.authorId}`
|
||||
});
|
||||
(document.activeElement as HTMLElement)?.blur();
|
||||
}}
|
||||
>
|
||||
{$_('player.share.materialiousLink')}
|
||||
{$_('player.share.youtubeLink')}
|
||||
</li>
|
||||
{/if}
|
||||
|
||||
<li
|
||||
class="row"
|
||||
role="presentation"
|
||||
onclick={async () => {
|
||||
await Clipboard.write({
|
||||
string: `https://www.youtube.com/channel/${data.channel.authorId}`
|
||||
});
|
||||
(document.activeElement as HTMLElement)?.blur();
|
||||
}}
|
||||
>
|
||||
{$_('player.share.youtubeLink')}
|
||||
</li>
|
||||
</menu>
|
||||
</button>
|
||||
</div>
|
||||
</menu>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -58,36 +58,38 @@
|
||||
|
||||
<div class="space"></div>
|
||||
|
||||
<button class="border no-margin">
|
||||
<i>share</i>
|
||||
<span>{$_('player.share.title')}</span>
|
||||
<menu class="no-wrap mobile">
|
||||
{#if !Capacitor.isNativePlatform()}
|
||||
{#if !$isAndroidTvStore}
|
||||
<button class="border no-margin">
|
||||
<i>share</i>
|
||||
<span>{$_('player.share.title')}</span>
|
||||
<menu class="no-wrap mobile">
|
||||
{#if !Capacitor.isNativePlatform()}
|
||||
<li
|
||||
class="row"
|
||||
role="presentation"
|
||||
onclick={async () => {
|
||||
await Clipboard.write({ string: location.href });
|
||||
(document.activeElement as HTMLElement)?.blur();
|
||||
}}
|
||||
>
|
||||
{$_('player.share.materialiousLink')}
|
||||
</li>
|
||||
{/if}
|
||||
<li
|
||||
class="row"
|
||||
role="presentation"
|
||||
onclick={async () => {
|
||||
await Clipboard.write({ string: location.href });
|
||||
await Clipboard.write({
|
||||
string: `https://www.youtube.com/playlist?list=${data.playlist.info.playlistId}`
|
||||
});
|
||||
(document.activeElement as HTMLElement)?.blur();
|
||||
}}
|
||||
>
|
||||
{$_('player.share.materialiousLink')}
|
||||
{$_('player.share.youtubeLink')}
|
||||
</li>
|
||||
{/if}
|
||||
<li
|
||||
class="row"
|
||||
role="presentation"
|
||||
onclick={async () => {
|
||||
await Clipboard.write({
|
||||
string: `https://www.youtube.com/playlist?list=${data.playlist.info.playlistId}`
|
||||
});
|
||||
(document.activeElement as HTMLElement)?.blur();
|
||||
}}
|
||||
>
|
||||
{$_('player.share.youtubeLink')}
|
||||
</li>
|
||||
</menu>
|
||||
</button>
|
||||
</menu>
|
||||
</button>
|
||||
{/if}
|
||||
</article>
|
||||
|
||||
{#if data.playlist.videos}
|
||||
|
||||
@@ -127,25 +127,27 @@
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
<h5 style="margin-bottom: 0;">{$_('recommendedVideos')}</h5>
|
||||
<div class="grid">
|
||||
{#each data.video.recommendedVideos as recommendedVideo}
|
||||
<ContentColumn>
|
||||
<article
|
||||
onclick={() => {
|
||||
showInfo = false;
|
||||
}}
|
||||
role="presentation"
|
||||
style="height: 100%;"
|
||||
class="no-padding"
|
||||
>
|
||||
{#key recommendedVideo.videoId}
|
||||
<Thumbnail video={recommendedVideo} sideways={false} />
|
||||
{/key}
|
||||
</article>
|
||||
</ContentColumn>
|
||||
{/each}
|
||||
</div>
|
||||
{#if data.video.recommendedVideos.length > 0}
|
||||
<h5 style="margin-bottom: 0;">{$_('recommendedVideos')}</h5>
|
||||
<div class="grid">
|
||||
{#each data.video.recommendedVideos as recommendedVideo}
|
||||
<ContentColumn>
|
||||
<article
|
||||
onclick={() => {
|
||||
showInfo = false;
|
||||
}}
|
||||
role="presentation"
|
||||
style="height: 100%;"
|
||||
class="no-padding"
|
||||
>
|
||||
{#key recommendedVideo.videoId}
|
||||
<Thumbnail video={recommendedVideo} sideways={false} />
|
||||
{/key}
|
||||
</article>
|
||||
</ContentColumn>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</article>
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { browser } from '$app/environment';
|
||||
import { goto } from '$app/navigation';
|
||||
import androidTv from '$lib/android/plugins/androidTv';
|
||||
import { getResolveUrl } from '$lib/api';
|
||||
import '$lib/i18n'; // Import to initialize. Important :)
|
||||
import { initI18n } from '$lib/i18n';
|
||||
import { getPages } from '$lib/navPages.js';
|
||||
import { authStore, interfaceDefaultPage } from '$lib/store.js';
|
||||
import { authStore, interfaceDefaultPage, isAndroidTvStore } from '$lib/store.js';
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
export const ssr = false;
|
||||
@@ -14,6 +15,8 @@ export async function load({ url }) {
|
||||
await initI18n();
|
||||
}
|
||||
|
||||
isAndroidTvStore.set((await androidTv.isAndroidTv()).value);
|
||||
|
||||
if (url.pathname.startsWith('/@')) {
|
||||
const username = url.pathname.split('/')[1];
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.8 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.8 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.4 MiB |
+1
-1
@@ -3,7 +3,7 @@ import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
LATEST_VERSION = "1.9.14"
|
||||
LATEST_VERSION = "1.9.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")
|
||||
|
||||
Reference in New Issue
Block a user