Merge pull request #773 from Materialious/update/1.6.27

Update/1.6.27
This commit is contained in:
Ward
2025-01-23 19:09:56 +13:00
committed by GitHub
17 changed files with 1894 additions and 1374 deletions
+6
View File
@@ -18,6 +18,7 @@ Materialious allows you to customize various settings by overwriting the default
+ [Auto expand comments](#auto-expand-comments)
+ [Auto expand description](#auto-expand-desc)
+ [Low bandwidth mode](#low-bandwidth-mode)
+ [Display thumbnail avatars](#)
* [Player](#player)
+ [Mini player](#mini-player)
+ [Autoplay video](#autoplay-video)
@@ -137,6 +138,11 @@ Avoids loading images.
"lowBandwidthMode": true
```
### Enable thumbnail avatars
```json
"displayThumbnailAvatars": true
```
## Player
### Mini player
+33
View File
@@ -146,6 +146,28 @@
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="e3q" />
<option name="id" value="e3q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S24 Ultra" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1440" />
<option name="screenY" value="3120" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="eos" />
<option name="id" value="eos" />
<option name="manufacturer" value="Google" />
<option name="name" value="Eos" />
<option name="screenDensity" value="320" />
<option name="screenX" value="384" />
<option name="screenY" value="384" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
@@ -179,6 +201,17 @@
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="motorola" />
<option name="codename" value="fogona" />
<option name="id" value="fogona" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="moto g play - 2024" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
+2 -2
View File
@@ -7,8 +7,8 @@ android {
applicationId "us.materialio.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 77
versionName "1.6.26"
versionCode 78
versionName "1.6.27"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
+4 -3
View File
@@ -2358,11 +2358,12 @@
}
},
"node_modules/electron": {
"version": "33.3.1",
"resolved": "https://registry.npmjs.org/electron/-/electron-33.3.1.tgz",
"integrity": "sha512-Z7l2bVgpdKxHQMI4i0CirBX2n+iCYKOx5mbzNM3BpOyFELwlobEXKmzCmEnwP+3EcNeIhUQyIEBFQxN06QgdIw==",
"version": "33.3.2",
"resolved": "https://registry.npmjs.org/electron/-/electron-33.3.2.tgz",
"integrity": "sha512-2pWr0frM9UrZGX1d7eoFdMROw10h2vXIWJmXdjwlKnSWWUm18GCrEOUeDUr+IMgz5EjO7JM7FQDHDMApeMgHyg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@electron/get": "^2.0.0",
"@types/node": "^20.9.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "Materialious",
"version": "1.6.26",
"version": "1.6.27",
"description": "Modern material design for Invidious.",
"author": {
"name": "Ward Pearce",
+1696 -1352
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "materialious",
"version": "1.6.26",
"version": "1.6.27",
"private": true,
"scripts": {
"dev": "vite dev",
@@ -62,6 +62,7 @@
"he": "^1.2.0",
"human-number": "^2.0.4",
"iso-3166": "^4.3.0",
"iso-639-1": "^3.1.4",
"material-dynamic-colors": "^1.1.1",
"media-captions": "^1.0.4",
"media-icons": "^0.10.0",
@@ -75,4 +76,4 @@
"vidstack": "^1.12.9",
"youtubei.js": "^12.2.0"
}
}
}
+45 -1
View File
@@ -19,6 +19,7 @@
getBestThumbnail,
proxyVideoUrl,
pullBitratePreference,
setStatusBarColor,
videoLength,
type PhasedDescription
} from './misc';
@@ -30,6 +31,7 @@
playerAndroidBgPlayer,
playerAndroidLockOrientation,
playerAutoPlayStore,
playerDefaultLanguage,
playerProxyVideosStore,
playerSavePlaybackPositionStore,
silenceSkipperStore,
@@ -64,6 +66,8 @@
let sponsorBlockElements: Element[] = [];
let watchProgressTimeout: NodeJS.Timeout;
function setSponsorTimeline() {
if (get(sponsorBlockTimelineStore)) return;
if (segments.length === 0) return;
@@ -233,6 +237,9 @@
}
}
// Auto save watch progress every minute.
watchProgressTimeout = setInterval(() => savePlayerPos(), 60000);
player.addEventListener('pause', () => {
savePlayerPos();
if (get(silenceSkipperStore)) {
@@ -343,6 +350,19 @@
}
player.addEventListener('dash-can-play', async () => {
const defaultLanguage = get(playerDefaultLanguage);
if (defaultLanguage) {
let trackIndex = 0;
for (const track of player.audioTracks) {
console.log(player.audioTracks);
if (track.label.toLowerCase().includes(defaultLanguage)) {
player.remoteControl.changeAudioTrack(trackIndex);
break;
}
trackIndex++;
}
}
if (get(playerAutoPlayStore)) {
player.play();
}
@@ -403,13 +423,33 @@
await AudioPlayer.initialize(audioId);
}
if (get(playerAndroidLockOrientation)) {
if (Capacitor.getPlatform() === 'android') {
let initialFullscreen = true;
const videoFormats = data.video.adaptiveFormats.filter((format) =>
format.type.startsWith('video/')
);
originalOrigination = await ScreenOrientation.orientation();
player.addEventListener('fullscreen-change', async (event: FullscreenChangeEvent) => {
// A bit of a hack to fix Android automatically
// fullscreening when opening a video.
if (initialFullscreen) {
player.exitFullscreen();
initialFullscreen = false;
return;
}
if (event.detail) {
// Ensure bar color is black while in fullscreen
await StatusBar.setBackgroundColor({ color: '#000000' });
} else {
await setStatusBarColor();
}
if (!get(playerAndroidLockOrientation)) return;
if (event.detail && videoFormats[0].resolution) {
const widthHeight = videoFormats[0].resolution.split('x');
@@ -425,6 +465,7 @@
} else {
await StatusBar.setOverlaysWebView({ overlay: false });
await StatusBar.show();
await ScreenOrientation.lock({
orientation: (originalOrigination as ScreenOrientationResult).type
});
@@ -544,6 +585,9 @@
if (typeof silenceSkipperInterval !== 'undefined') {
clearInterval(silenceSkipperInterval);
}
if (watchProgressTimeout) {
clearTimeout(watchProgressTimeout);
}
try {
savePlayerPos();
} catch (error) {}
+52 -1
View File
@@ -5,10 +5,11 @@
import { Capacitor } from '@capacitor/core';
import ui from 'beercss';
import { iso31661 } from 'iso-3166';
import ISO6391 from 'iso-639-1';
import { onMount } from 'svelte';
import { _ } from 'svelte-i18n';
import { get } from 'svelte/store';
import { ensureNoTrailingSlash, letterCase, titleCases } from './misc';
import { ensureNoTrailingSlash, letterCase, titleCase, titleCases } from './misc';
import {
authStore,
darkModeStore,
@@ -20,6 +21,7 @@
interfaceAmoledTheme,
interfaceAutoExpandComments,
interfaceAutoExpandDesc,
interfaceDisplayThumbnailAvatars,
interfaceForceCase,
interfaceLowBandwidthMode,
interfacePreviewVideoOnHoverStore,
@@ -30,6 +32,7 @@
playerAndroidLockOrientation,
playerAutoPlayStore,
playerAutoplayNextByDefaultStore,
playerDefaultLanguage,
playerListenByDefaultStore,
playerMiniPlayerStore,
playerProxyVideosStore,
@@ -62,6 +65,11 @@
let deArrowThumbnailUrl = get(deArrowThumbnailInstanceStore);
let region = get(interfaceRegionStore);
let forceCase = get(interfaceForceCase);
let defaultLanguage = get(playerDefaultLanguage);
const languageNames = ISO6391.getAllCodes().map((code) =>
ISO6391.getName(code).toLocaleLowerCase()
);
const sponsorCategories = [
{ name: $_('layout.sponsors.sponsor'), category: 'sponsor' },
@@ -125,6 +133,15 @@
checkWidth();
addEventListener('resize', () => checkWidth());
// Set default language if not set already based off browser.
if (!get(playerDefaultLanguage)) {
const languageCode = navigator.language || navigator.languages[0];
const languageName = ISO6391.getName(languageCode.split('-')[0]);
if (languageName) {
playerDefaultLanguage.set(languageName.toLowerCase());
}
}
});
</script>
@@ -236,6 +253,23 @@
</div>
{/if}
<div class="field no-margin">
<nav class="no-padding">
<div class="max">
<div>{$_('layout.displayThumbnailAvatars')}</div>
</div>
<label class="switch">
<input
type="checkbox"
bind:checked={$interfaceDisplayThumbnailAvatars}
on:click={() =>
interfaceDisplayThumbnailAvatars.set(!$interfaceDisplayThumbnailAvatars)}
/>
<span></span>
</label>
</nav>
</div>
<div class="field no-margin">
<nav class="no-padding">
<div class="max">
@@ -363,6 +397,23 @@
{/if}
</div>
<div class="page padding" class:active={activeTab === 'player'}>
<div class="margin"></div>
<div class="field label suffix border">
<select
name="case"
bind:value={defaultLanguage}
on:change={() => playerDefaultLanguage.set(defaultLanguage)}
>
{#each languageNames as language}
<option selected={$playerDefaultLanguage === language} value={language}
>{titleCase(language)}</option
>
{/each}
</select>
<label for="case">{$_('player.defaultLanguage')}</label>
<i>arrow_drop_down</i>
</div>
<div class="field no-margin">
<nav class="no-padding">
<div class="max">
+4 -1
View File
@@ -18,6 +18,7 @@
authStore,
deArrowEnabledStore,
deArrowTitlesOnly,
interfaceDisplayThumbnailAvatars,
interfaceLowBandwidthMode,
interfacePreviewVideoOnHoverStore,
playerProxyVideosStore,
@@ -86,6 +87,8 @@
}
async function loadAuthor() {
if (!get(interfaceDisplayThumbnailAvatars)) return;
try {
const channel = await getChannel(video.authorId, { priority: 'low' });
const img = new Image();
@@ -370,7 +373,7 @@
</div>
<div class="thumbnail-details video-title">
{#if !sideways && !$interfaceLowBandwidthMode}
{#if !sideways && !$interfaceLowBandwidthMode && $interfaceDisplayThumbnailAvatars}
<div style="margin-right: 1em;">
{#if authorImg}
<img src={authorImg.src} alt="Author" class="circle small" />
+14 -2
View File
@@ -8,6 +8,7 @@ import {
interfaceAmoledTheme,
interfaceAutoExpandComments,
interfaceAutoExpandDesc,
interfaceDisplayThumbnailAvatars,
interfaceForceCase,
interfaceLowBandwidthMode,
interfacePreviewVideoOnHoverStore,
@@ -16,6 +17,7 @@ import {
playerAlwaysLoopStore,
playerAutoPlayStore,
playerAutoplayNextByDefaultStore,
playerDefaultLanguage,
playerListenByDefaultStore,
playerMiniPlayerStore,
playerProxyVideosStore,
@@ -33,9 +35,9 @@ import {
synciousStore,
themeColorStore
} from '$lib/store';
import { get } from 'svelte/store';
import { get, type Writable } from 'svelte/store';
const persistedStores = [
const persistedStores: { name: string, store: Writable<any>, type: 'string' | 'boolean' | 'array'; }[] = [
{
name: 'returnYTDislikesInstance',
store: returnYTDislikesInstanceStore,
@@ -195,6 +197,16 @@ const persistedStores = [
name: 'lowBandwidthMode',
store: interfaceLowBandwidthMode,
type: 'boolean'
},
{
name: 'displayThumbnailAvatars',
store: interfaceDisplayThumbnailAvatars,
type: 'boolean'
},
{
name: 'defaultLanguage',
store: playerDefaultLanguage,
type: 'boolean'
}
];
+3 -1
View File
@@ -88,7 +88,8 @@
"noPlaylists": "No playlists",
"unableToLoadComments": "Unable to load comments",
"addToPlaylist": "Add to playlist",
"youtubeJsFallBack": "Local video fallback being used"
"youtubeJsFallBack": "Local video fallback being used",
"defaultLanguage": "Default Language"
},
"layout": {
"interface": "Interface",
@@ -104,6 +105,7 @@
"logout": "Logout",
"customize": "Customize",
"lowBandwidthMode": "Low bandwidth mode",
"displayThumbnailAvatars": "Display channel avatars on thumbnail (Slow)",
"theme": {
"theme": "Theme",
"darkMode": "Dark mode",
+11
View File
@@ -1,11 +1,14 @@
import { pushState } from '$app/navigation';
import { page } from '$app/stores';
import { Capacitor } from '@capacitor/core';
import { StatusBar } from '@capacitor/status-bar';
import he from 'he';
import humanNumber from 'human-number';
import type Peer from 'peerjs';
import { get } from 'svelte/store';
import type { Image } from './api/model';
import { instanceStore, interfaceForceCase } from './store';
import { getDynamicTheme } from './theme';
export type TitleCase = 'uppercase' | 'lowercase' | 'sentence case' | 'title case' | null;
@@ -288,3 +291,11 @@ export function ensureNoTrailingSlash(url: any): string {
return url.endsWith('/') ? url.slice(0, -1) : url;
}
export async function setStatusBarColor() {
if (Capacitor.getPlatform() === 'android') {
await StatusBar.setBackgroundColor({
color: (await getDynamicTheme())['--surface-container']
});
}
}
+2
View File
@@ -44,6 +44,7 @@ export const playerYouTubeJsFallback = persisted('youTubeJsFallback', true);
export const playerYouTubeJsAlways = persisted('youTubeJsAlways', false);
export const playerAndroidBgPlayer = persisted('androidBgPlayer', true);
export const playerAndroidLockOrientation = persisted('androidLockOrientation', true);
export const playerDefaultLanguage = persisted('defaultLanguage', '');
export const returnYtDislikesStore = persisted('returnYtDislikes', false);
export const returnYTDislikesInstanceStore: Writable<string | null | undefined> = persisted(
@@ -65,6 +66,7 @@ export const interfaceAutoExpandComments: Writable<boolean> = persisted('autoExp
export const interfaceAutoExpandDesc: Writable<boolean> = persisted('autoExpandDesc', false);
export const interfaceAmoledTheme = persisted('amoledTheme', false);
export const interfaceLowBandwidthMode = persisted('lowBandwidthMode', false);
export const interfaceDisplayThumbnailAvatars = persisted('disableThumbnailAvatars', false);
export const sponsorBlockStore = persisted('sponsorBlock', true);
export const sponsorBlockUrlStore: Writable<string | null | undefined> = persisted(
+13 -6
View File
@@ -8,6 +8,7 @@
import { bookmarkletLoadFromUrl, loadSettingsFromEnv } from '$lib/externalSettings';
import Logo from '$lib/Logo.svelte';
import MiniPlayer from '$lib/MiniPlayer.svelte';
import { setStatusBarColor } from '$lib/misc';
import PageLoading from '$lib/PageLoading.svelte';
import Search from '$lib/Search.svelte';
import Settings from '$lib/Settings.svelte';
@@ -84,9 +85,11 @@
setAmoledTheme();
});
darkModeStore.subscribe(() => {
darkModeStore.subscribe(async () => {
setTheme();
setAmoledTheme();
await setStatusBarColor();
});
App.addListener('appUrlOpen', (data) => {
@@ -182,14 +185,18 @@
// So user preferences overwrite instance preferences.
bookmarkletLoadFromUrl();
const themeHex = get(themeColorStore);
let themeHex = get(themeColorStore);
if (themeHex) {
await ui('theme', themeHex);
} else if (Capacitor.getPlatform() === 'android') {
try {
const colorPalette = await colorTheme.getColorPalette();
await ui('theme', convertToHexColorCode(colorPalette.primary));
} catch {}
if (!themeHex) {
try {
const colorPalette = await colorTheme.getColorPalette();
themeHex = convertToHexColorCode(colorPalette.primary);
await ui('theme', themeHex);
await setStatusBarColor();
} catch {}
}
}
setTheme();
+4 -1
View File
@@ -38,6 +38,9 @@ export default defineConfig({
sveltekit()
],
optimizeDeps: {
exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util']
exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util'],
},
ssr: {
noExternal: ['beercss']
}
});
+1 -1
View File
@@ -5,7 +5,7 @@ import json
import os
import re
LATEST_VERSION = "1.6.26"
LATEST_VERSION = "1.6.27"
WORKING_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "materialious")
ROOT_PACKAGE = os.path.join(WORKING_DIR, "package.json")