@@ -1,19 +1,19 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
namespace "us.materialio.app"
|
||||
compileSdk rootProject.ext.compileSdkVersion
|
||||
namespace = "us.materialio.app"
|
||||
compileSdk = rootProject.ext.compileSdkVersion
|
||||
defaultConfig {
|
||||
applicationId "us.materialio.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 180
|
||||
versionName "1.12.8"
|
||||
versionCode 181
|
||||
versionName "1.12.9"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
// Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
|
||||
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
|
||||
ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
|
||||
}
|
||||
ndk {
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<activity
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation|density"
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/title_activity_main"
|
||||
android:theme="@style/AppTheme.NoActionBarLaunch"
|
||||
|
||||
@@ -6,8 +6,8 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.10.1'
|
||||
classpath 'com.google.gms:google-services:4.4.2'
|
||||
classpath 'com.android.tools.build:gradle:8.13.2'
|
||||
classpath 'com.google.gms:google-services:4.4.4'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
||||
Binary file not shown.
Vendored
+14
-11
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -83,7 +85,8 @@ done
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -111,7 +114,7 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -144,7 +147,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
@@ -152,7 +155,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
@@ -201,16 +204,16 @@ fi
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
Vendored
+14
-12
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -57,22 +59,22 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
ext {
|
||||
minSdkVersion = 23
|
||||
compileSdkVersion = 35
|
||||
targetSdkVersion = 35
|
||||
androidxActivityVersion = '1.9.2'
|
||||
androidxAppCompatVersion = '1.7.0'
|
||||
androidxCoordinatorLayoutVersion = '1.2.0'
|
||||
androidxCoreVersion = '1.15.0'
|
||||
androidxFragmentVersion = '1.8.4'
|
||||
coreSplashScreenVersion = '1.0.1'
|
||||
androidxWebkitVersion = '1.12.1'
|
||||
minSdkVersion = 24
|
||||
compileSdkVersion = 36
|
||||
targetSdkVersion = 36
|
||||
androidxActivityVersion = '1.11.0'
|
||||
androidxAppCompatVersion = '1.7.1'
|
||||
androidxCoordinatorLayoutVersion = '1.3.0'
|
||||
androidxCoreVersion = '1.17.0'
|
||||
androidxFragmentVersion = '1.8.9'
|
||||
coreSplashScreenVersion = '1.2.0'
|
||||
androidxWebkitVersion = '1.14.0'
|
||||
junitVersion = '4.13.2'
|
||||
androidxJunitVersion = '1.2.1'
|
||||
androidxEspressoCoreVersion = '3.6.1'
|
||||
cordovaAndroidVersion = '10.1.1'
|
||||
androidxJunitVersion = '1.3.0'
|
||||
androidxEspressoCoreVersion = '3.7.0'
|
||||
cordovaAndroidVersion = '14.0.1'
|
||||
}
|
||||
@@ -7,6 +7,9 @@ const config: CapacitorConfig = {
|
||||
plugins: {
|
||||
CapacitorNodeJS: {
|
||||
nodeDir: 'nodejs-android'
|
||||
},
|
||||
SystemBars: {
|
||||
insetsHandling: 'disable'
|
||||
}
|
||||
},
|
||||
server: {
|
||||
|
||||
@@ -7,6 +7,9 @@ const config: CapacitorConfig = {
|
||||
plugins: {
|
||||
CapacitorNodeJS: {
|
||||
nodeDir: 'nodejs-android'
|
||||
},
|
||||
SystemBars: {
|
||||
insetsHandling: 'disable'
|
||||
}
|
||||
},
|
||||
server: {
|
||||
|
||||
@@ -77,7 +77,11 @@
|
||||
|
||||
|
||||
|
||||
<release version="1.12.8" date="2025-12-23">
|
||||
|
||||
<release version="1.12.9" date="2025-12-28">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.12.9</url>
|
||||
</release>
|
||||
<release version="1.12.8" date="2025-12-23">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.12.8</url>
|
||||
</release>
|
||||
<release version="1.12.7" date="2025-12-22">
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.12.8",
|
||||
"version": "1.12.9",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "Materialious",
|
||||
"version": "1.12.8",
|
||||
"version": "1.12.9",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.12.8",
|
||||
"version": "1.12.9",
|
||||
"description": "Modern material design for Invidious.",
|
||||
"author": {
|
||||
"name": "Ward Pearce",
|
||||
@@ -44,4 +44,4 @@
|
||||
"capacitor",
|
||||
"electron"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+14028
-14071
File diff suppressed because it is too large
Load Diff
+77
-76
@@ -1,78 +1,79 @@
|
||||
{
|
||||
"name": "materialious",
|
||||
"version": "1.12.8",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"eslint": "eslint .",
|
||||
"format": "prettier --write .",
|
||||
"patch:shaka": "node ./scripts/patchShaka.mjs",
|
||||
"postinstall": "npm run patch:shaka"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capacitor/assets": "^3.0.5",
|
||||
"@capacitor/cli": "^7.4.4",
|
||||
"@sveltejs/adapter-auto": "^6.0.1",
|
||||
"@sveltejs/adapter-static": "^3.0.10",
|
||||
"@sveltejs/kit": "^2.49.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
||||
"@types/event-source-polyfill": "^1.0.5",
|
||||
"@types/he": "^1.2.3",
|
||||
"@types/human-number": "^1.0.2",
|
||||
"@types/mousetrap": "^1.6.15",
|
||||
"@vite-pwa/sveltekit": "^1.0.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-svelte": "^3.13.0",
|
||||
"patch-package": "^8.0.1",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"svelte": "^5.45.6",
|
||||
"svelte-check": "^4.3.3",
|
||||
"tslib": "^2.7.0",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.47.0",
|
||||
"vite": "^7.2.6"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.1",
|
||||
"@capacitor-community/safe-area": "^7.0.0-alpha.1",
|
||||
"@capacitor/android": "^7.4.4",
|
||||
"@capacitor/app": "^7.1.0",
|
||||
"@capacitor/browser": "^7.0.0",
|
||||
"@capacitor/clipboard": "^7.0.0",
|
||||
"@capacitor/core": "^7.4.4",
|
||||
"@capacitor/preferences": "^7.0.2",
|
||||
"@capacitor/screen-orientation": "^7.0.0",
|
||||
"@capacitor/share": "^7.0.2",
|
||||
"@macfja/serializer": "^1.1.4",
|
||||
"@macfja/svelte-persistent-store": "^2.4.2",
|
||||
"beercss": "^3.13.1",
|
||||
"bgutils-js": "^3.2.0",
|
||||
"capacitor-music-controls-plugin": "^6.1.0",
|
||||
"capacitor-nodejs": "https://github.com/hampoelz/capacitor-nodejs/releases/download/v1.0.0-beta.9/capacitor-nodejs.tgz",
|
||||
"dayjs": "^1.11.19",
|
||||
"dexie": "^4.2.1",
|
||||
"fuse.js": "^7.0.0",
|
||||
"googlevideo": "^4.0.4",
|
||||
"he": "^1.2.0",
|
||||
"human-number": "^2.0.8",
|
||||
"i18next": "^25.7.2",
|
||||
"iso-3166": "^4.4.0",
|
||||
"iso-639-1": "^3.1.5",
|
||||
"material-dynamic-colors": "^1.1.1",
|
||||
"media-captions": "^1.0.4",
|
||||
"mousetrap": "^1.6.5",
|
||||
"peerjs": "^1.5.5",
|
||||
"shaka-player": "^4.16.11",
|
||||
"sponsorblock-api": "^0.2.4",
|
||||
"svelte-infinite-loading": "^1.4.0",
|
||||
"youtubei.js": "^16.0.1"
|
||||
}
|
||||
"name": "materialious",
|
||||
"version": "1.12.9",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "npm run patch:github && vite dev",
|
||||
"build": "npm run patch:github && vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"eslint": "eslint .",
|
||||
"format": "prettier --write .",
|
||||
"patch:shaka": "node ./scripts/patchShaka.mjs",
|
||||
"patch:github": "node ./scripts/githubContributors.mjs",
|
||||
"postinstall": "npm run patch:shaka"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capacitor/assets": "^3.0.5",
|
||||
"@capacitor/cli": "^8.0.0",
|
||||
"@sveltejs/adapter-auto": "^6.0.1",
|
||||
"@sveltejs/adapter-static": "^3.0.10",
|
||||
"@sveltejs/kit": "^2.49.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
||||
"@types/event-source-polyfill": "^1.0.5",
|
||||
"@types/he": "^1.2.3",
|
||||
"@types/human-number": "^1.0.2",
|
||||
"@types/mousetrap": "^1.6.15",
|
||||
"@vite-pwa/sveltekit": "^1.0.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-svelte": "^3.13.0",
|
||||
"patch-package": "^8.0.1",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"svelte": "^5.45.6",
|
||||
"svelte-check": "^4.3.3",
|
||||
"tslib": "^2.7.0",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.47.0",
|
||||
"vite": "^7.2.6"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.1",
|
||||
"@capacitor-community/safe-area": "^7.0.0-alpha.1",
|
||||
"@capacitor/android": "^8.0.0",
|
||||
"@capacitor/app": "^8.0.0",
|
||||
"@capacitor/browser": "^8.0.0",
|
||||
"@capacitor/clipboard": "^8.0.0",
|
||||
"@capacitor/core": "^8.0.0",
|
||||
"@capacitor/preferences": "^8.0.0",
|
||||
"@capacitor/screen-orientation": "^8.0.0",
|
||||
"@capacitor/share": "^8.0.0",
|
||||
"@macfja/serializer": "^1.1.4",
|
||||
"@macfja/svelte-persistent-store": "^2.4.2",
|
||||
"beercss": "^3.13.1",
|
||||
"bgutils-js": "^3.2.0",
|
||||
"capacitor-music-controls-plugin": "^6.1.0",
|
||||
"capacitor-nodejs": "https://github.com/hampoelz/capacitor-nodejs/releases/download/v1.0.0-beta.9/capacitor-nodejs.tgz",
|
||||
"dayjs": "^1.11.19",
|
||||
"dexie": "^4.2.1",
|
||||
"fuse.js": "^7.0.0",
|
||||
"googlevideo": "^4.0.4",
|
||||
"he": "^1.2.0",
|
||||
"human-number": "^2.0.8",
|
||||
"i18next": "^25.7.2",
|
||||
"iso-3166": "^4.4.0",
|
||||
"iso-639-1": "^3.1.5",
|
||||
"material-dynamic-colors": "^1.1.1",
|
||||
"media-captions": "^1.0.4",
|
||||
"mousetrap": "^1.6.5",
|
||||
"peerjs": "^1.5.5",
|
||||
"shaka-player": "^4.16.11",
|
||||
"sponsorblock-api": "^0.2.4",
|
||||
"svelte-infinite-loading": "^1.4.0",
|
||||
"youtubei.js": "^16.0.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import fetch from 'node-fetch';
|
||||
import * as url from 'node:url';
|
||||
|
||||
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
||||
|
||||
const apiUrl = 'https://api.github.com/repos/Materialious/Materialious/contributors';
|
||||
const outputDir = path.join(__dirname, '../static/localApi');
|
||||
const outputFile = 'ghContributors.json';
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const response = await fetch(apiUrl);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Ensure the output directory exists
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Write the data to a JSON file
|
||||
fs.writeFileSync(path.join(outputDir, outputFile), JSON.stringify(data));
|
||||
console.log('Github contributors fetched and written to', path.join(outputDir, outputFile));
|
||||
} catch (error) {
|
||||
console.error('Error fetching data:', error);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -3,7 +3,7 @@
|
||||
import { getBestThumbnail } from '$lib/images';
|
||||
import { padTime, videoLength } from '$lib/numbers';
|
||||
import { type PhasedDescription } from '$lib/timestamps';
|
||||
import { SafeArea } from '@capacitor-community/safe-area';
|
||||
import { SafeArea, SystemBarsStyle, SystemBarsType } from '@capacitor-community/safe-area';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { ScreenOrientation, type ScreenOrientationResult } from '@capacitor/screen-orientation';
|
||||
import { error, type Page } from '@sveltejs/kit';
|
||||
@@ -43,7 +43,12 @@
|
||||
} from '../store';
|
||||
import { setStatusBarColor } from '../theme';
|
||||
import { patchYoutubeJs } from '$lib/patches/youtubejs';
|
||||
import { goToNextVideo, goToPreviousVideo, playbackRates } from '$lib/player';
|
||||
import {
|
||||
goToNextVideo,
|
||||
goToPreviousVideo,
|
||||
playbackRates,
|
||||
playerDoubleTapSeek
|
||||
} from '$lib/player';
|
||||
import { dashManifestDomainInclusion } from '$lib/android/youtube/dash';
|
||||
import { injectSabr } from '$lib/sabr';
|
||||
import type { SabrStreamingAdapter } from 'googlevideo/sabr-streaming-adapter';
|
||||
@@ -68,16 +73,17 @@
|
||||
let snackBarAlert = $state('');
|
||||
let originalOrigination: ScreenOrientationResult | undefined;
|
||||
// eslint-disable-next-line no-undef
|
||||
let watchProgressTimeout: NodeJS.Timeout;
|
||||
let watchProgressInterval: NodeJS.Timeout;
|
||||
let showVideoRetry = $state(false);
|
||||
|
||||
let player: shaka.Player;
|
||||
let sabrAdapter: SabrStreamingAdapter | null;
|
||||
let playerContainer: HTMLElement;
|
||||
let bufferBar: HTMLElement | undefined = $state();
|
||||
|
||||
let playerCurrentPlaybackState = $state(false);
|
||||
let playerCurrentTime = $state(0);
|
||||
let playerMaxKnownTime = $state(0);
|
||||
let playerMaxKnownTime = $state(data.video.lengthSeconds);
|
||||
let playerIsBuffering = $state(false);
|
||||
let playerVolume = $state(0);
|
||||
let playerSettings: 'quality' | 'speed' | 'language' | 'root' = $state('root');
|
||||
@@ -89,6 +95,13 @@
|
||||
let playerTimelineTimeHover: number = $state(0);
|
||||
let playerTimelineMouseX: number = $state(0);
|
||||
let playerTimelineLastUpdate: number = 0;
|
||||
let playerVideoEndTimePretty: string = $state('');
|
||||
|
||||
let clickCount = $state(0);
|
||||
// eslint-disable-next-line no-undef
|
||||
let clickCounterTimeout: NodeJS.Timeout;
|
||||
|
||||
let seekDirection: 'forwards' | 'backwards' = $state('forwards');
|
||||
|
||||
const STORAGE_KEY_VOLUME = 'shaka-preferred-volume';
|
||||
|
||||
@@ -192,14 +205,14 @@
|
||||
|
||||
if (isFullScreen) {
|
||||
// Ensure bar color is black while in fullscreen
|
||||
await SafeArea.enable({
|
||||
config: {
|
||||
customColorsForSystemBars: true,
|
||||
statusBarColor: '#00000000',
|
||||
statusBarContent: 'light',
|
||||
navigationBarColor: '#00000000',
|
||||
navigationBarContent: 'light'
|
||||
}
|
||||
await SafeArea.setSystemBarsStyle({
|
||||
style: SystemBarsStyle.Dark
|
||||
});
|
||||
await SafeArea.hideSystemBars({
|
||||
type: SystemBarsType.NavigationBar
|
||||
});
|
||||
await SafeArea.hideSystemBars({
|
||||
type: SystemBarsType.StatusBar
|
||||
});
|
||||
} else {
|
||||
await setStatusBarColor();
|
||||
@@ -340,6 +353,14 @@
|
||||
if (playerElement) playerElement.currentTime = playerCurrentTime;
|
||||
}
|
||||
|
||||
function toggleFullscreen() {
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
} else {
|
||||
playerContainer.requestFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
async function loadVideo() {
|
||||
showVideoRetry = false;
|
||||
|
||||
@@ -357,11 +378,11 @@
|
||||
});
|
||||
|
||||
if (!data.video.liveNow) {
|
||||
if (watchProgressTimeout) {
|
||||
clearInterval(watchProgressTimeout);
|
||||
if (watchProgressInterval) {
|
||||
clearInterval(watchProgressInterval);
|
||||
}
|
||||
// Auto save watch progress every minute.
|
||||
watchProgressTimeout = setInterval(() => savePlayerPos(), 60000);
|
||||
watchProgressInterval = setInterval(() => savePlayerPos(), 60000);
|
||||
setupSponsorSkip();
|
||||
|
||||
let dashUrl: string;
|
||||
@@ -692,14 +713,14 @@
|
||||
if (!$isAndroidTvStore) {
|
||||
Mousetrap.bind('right', () => {
|
||||
if (!playerElement) return;
|
||||
playerElement.currentTime = playerElement.currentTime + 10;
|
||||
playerElement.currentTime = playerElement.currentTime + playerDoubleTapSeek;
|
||||
return false;
|
||||
});
|
||||
|
||||
Mousetrap.bind('left', () => {
|
||||
if (!playerElement) return;
|
||||
|
||||
playerElement.currentTime = playerElement.currentTime - 10;
|
||||
playerElement.currentTime = playerElement.currentTime - playerDoubleTapSeek;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
@@ -710,11 +731,7 @@
|
||||
});
|
||||
|
||||
Mousetrap.bind('f', () => {
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
} else {
|
||||
playerContainer.requestFullscreen();
|
||||
}
|
||||
toggleFullscreen();
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -788,7 +805,33 @@
|
||||
playerCurrentTime = playerElement.currentTime ?? 0;
|
||||
|
||||
if (playerMaxKnownTime === 0 || playerCurrentTime > playerMaxKnownTime) {
|
||||
playerMaxKnownTime = Number(playerElement?.currentTime);
|
||||
playerMaxKnownTime = Number(playerElement.currentTime);
|
||||
}
|
||||
|
||||
const remainingTime = playerMaxKnownTime - playerElement.currentTime;
|
||||
const videoEnds = new Date(Date.now() + remainingTime * 1000);
|
||||
|
||||
playerVideoEndTimePretty = videoEnds.toLocaleTimeString([], {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: true
|
||||
});
|
||||
|
||||
const buffered = playerElement.buffered;
|
||||
|
||||
if (buffered.length > 0 && bufferBar) {
|
||||
const bufferedEnd = buffered.end(0); // Amount shaka has buffered
|
||||
const startBuffer = Math.max(playerElement.currentTime, 0);
|
||||
|
||||
// Calculate the buffered width as a percentage starting from the current time
|
||||
const bufferedWidth =
|
||||
((bufferedEnd - startBuffer) / (playerMaxKnownTime - startBuffer)) * 100;
|
||||
|
||||
const currentSliderPercentage = (playerCurrentTime / playerMaxKnownTime) * 100;
|
||||
|
||||
const effectiveWidth = Math.min(Math.max(bufferedWidth, 0), currentSliderPercentage);
|
||||
bufferBar.style.width = effectiveWidth + '%';
|
||||
bufferBar.style.left = Math.min(currentSliderPercentage, 100) + '%';
|
||||
}
|
||||
});
|
||||
|
||||
@@ -898,26 +941,40 @@
|
||||
if (
|
||||
event.target &&
|
||||
event.target instanceof HTMLElement &&
|
||||
event.target.id === 'player-center' &&
|
||||
event.target.id === 'player-tap-controls-area' &&
|
||||
parseFloat(getComputedStyle(event.target).opacity) > 0 &&
|
||||
playerElement
|
||||
) {
|
||||
clickCount++;
|
||||
|
||||
const container = event.currentTarget;
|
||||
|
||||
const rect = container.getBoundingClientRect();
|
||||
const clickX = event.clientX - rect.left;
|
||||
const width = rect.width;
|
||||
|
||||
if (clickCounterTimeout) clearTimeout(clickCounterTimeout);
|
||||
|
||||
clickCounterTimeout = setTimeout(() => {
|
||||
if (clickCount == 1) {
|
||||
toggleVideoPlaybackStatus();
|
||||
}
|
||||
|
||||
clickCount = 0;
|
||||
}, 300);
|
||||
|
||||
if (clickCount < 2) return;
|
||||
|
||||
if (clickX < width / 3) {
|
||||
// Left third, back 10s
|
||||
playerElement.currentTime = Math.max(0, playerElement.currentTime - 10);
|
||||
seekDirection = 'backwards';
|
||||
playerElement.currentTime = Math.max(0, playerElement.currentTime - playerDoubleTapSeek);
|
||||
} else if (clickX < (2 * width) / 3) {
|
||||
// Middle third, toggle play/pause
|
||||
toggleVideoPlaybackStatus();
|
||||
toggleFullscreen();
|
||||
} else {
|
||||
// Right third, forward 10s
|
||||
seekDirection = 'forwards';
|
||||
playerElement.currentTime = Math.min(
|
||||
playerElement.duration,
|
||||
playerElement.currentTime + 10
|
||||
playerElement.currentTime + playerDoubleTapSeek
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -935,6 +992,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
await setStatusBarColor();
|
||||
|
||||
await CapacitorMusicControls.destroy();
|
||||
}
|
||||
|
||||
@@ -948,10 +1007,12 @@
|
||||
|
||||
Mousetrap.unbind(['left', 'right', 'space', 'c', 'f', 'shift+left', 'shift+right']);
|
||||
|
||||
if (watchProgressTimeout) clearTimeout(watchProgressTimeout);
|
||||
if (watchProgressInterval) clearTimeout(watchProgressInterval);
|
||||
|
||||
if (sabrAdapter) sabrAdapter.dispose();
|
||||
|
||||
if (clickCounterTimeout) clearTimeout(clickCounterTimeout);
|
||||
|
||||
if (player) {
|
||||
player.unload();
|
||||
player.destroy();
|
||||
@@ -979,42 +1040,75 @@
|
||||
</div>
|
||||
{/if}
|
||||
{#if !hideControls}
|
||||
<p id="mobile-time" class="chip secondary s">
|
||||
{#if data.video.liveNow}
|
||||
{$_('thumbnail.live')}
|
||||
{:else}
|
||||
{videoLength(playerCurrentTime)} / {videoLength(data.video.lengthSeconds)}
|
||||
{/if}
|
||||
</p>
|
||||
<div id="mobile-time">
|
||||
<p class="chip inverse-primary s">
|
||||
{#if data.video.liveNow}
|
||||
{$_('thumbnail.live')}
|
||||
{:else}
|
||||
{videoLength(playerCurrentTime)} / {videoLength(playerMaxKnownTime)}
|
||||
{/if}
|
||||
</p>
|
||||
<p class="chip inverse-primary">
|
||||
{playerVideoEndTimePretty}
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
<div id="player-center">
|
||||
{#if playerIsBuffering}
|
||||
<progress class="circle large indeterminate" value="50" max="100"></progress>
|
||||
{:else if !playerCurrentPlaybackState}
|
||||
<button class="extra secondary" onclick={toggleVideoPlaybackStatus}>
|
||||
<i>play_arrow</i>
|
||||
</button>
|
||||
{/if}
|
||||
<div class="grid">
|
||||
<div class="s4 m4 l4" id="player-tap-controls-area">
|
||||
{#if clickCount > 1 && seekDirection === 'backwards'}
|
||||
<div
|
||||
class="seek-double-click"
|
||||
class:buffer-left={seekDirection === 'backwards'}
|
||||
id="player-tap-controls-area"
|
||||
>
|
||||
<h4 id="player-tap-controls-area">-{(clickCount - 1) * playerDoubleTapSeek}</h4>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="s4 m4 l4">
|
||||
<div class="player-status" id="player-tap-controls-area">
|
||||
{#if playerIsBuffering}
|
||||
<progress class="circle large indeterminate" value="50" max="100"></progress>
|
||||
{:else if !playerCurrentPlaybackState}
|
||||
<button class="extra inverse-primary" onclick={toggleVideoPlaybackStatus}>
|
||||
<i>play_arrow</i>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="s4 m4 l4" id="player-tap-controls-area">
|
||||
{#if clickCount > 1 && seekDirection === 'forwards'}
|
||||
<div
|
||||
class="seek-double-click"
|
||||
class:buffer-right={seekDirection === 'forwards'}
|
||||
id="player-tap-controls-area"
|
||||
>
|
||||
<h4 id="player-tap-controls-area">+{(clickCount - 1) * playerDoubleTapSeek}</h4>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{#if !hideControls}
|
||||
<div id="player-controls">
|
||||
<article class="round" style="width: 100%;padding: 0;height: 10px;">
|
||||
<label id="progress-slider" class="slider max">
|
||||
{#key playerCurrentTime}
|
||||
<input
|
||||
oninput={handleTimeChange}
|
||||
type="range"
|
||||
min={0}
|
||||
step={0.1}
|
||||
bind:value={playerCurrentTime}
|
||||
max={data.video.liveNow ? playerMaxKnownTime : data.video.lengthSeconds}
|
||||
onmousemove={handleMouseMove}
|
||||
onmouseleave={handleMouseLeave}
|
||||
/>
|
||||
{/key}
|
||||
<span></span>
|
||||
</label>
|
||||
</article>
|
||||
<label class="slider" id="progress-slider">
|
||||
{#key playerCurrentTime}
|
||||
<input
|
||||
style="width: 100%;"
|
||||
type="range"
|
||||
oninput={handleTimeChange}
|
||||
min={0}
|
||||
step={0.1}
|
||||
bind:value={playerCurrentTime}
|
||||
max={playerMaxKnownTime}
|
||||
onmousemove={handleMouseMove}
|
||||
onmouseleave={handleMouseLeave}
|
||||
/>
|
||||
{/key}
|
||||
<span></span>
|
||||
<div bind:this={bufferBar} class="buffered-bar"></div>
|
||||
</label>
|
||||
|
||||
{#if playerTimelineTooltipVisible}
|
||||
<div class="tooltip" style="position: absolute; left: {playerTimelineMouseX}px;">
|
||||
@@ -1024,7 +1118,7 @@
|
||||
|
||||
<nav>
|
||||
<nav class="no-wrap">
|
||||
<button class="secondary" onclick={toggleVideoPlaybackStatus}>
|
||||
<button class="inverse-primary" onclick={toggleVideoPlaybackStatus}>
|
||||
<i>
|
||||
{#if playerCurrentPlaybackState}
|
||||
pause
|
||||
@@ -1034,35 +1128,28 @@
|
||||
</i>
|
||||
</button>
|
||||
{#if Capacitor.getPlatform() !== 'android'}
|
||||
<article
|
||||
id="volume-slider"
|
||||
class="round m l"
|
||||
style="padding: 0;height: 10px;width: 150px;"
|
||||
>
|
||||
<label class="slider max">
|
||||
{#key playerVolume}
|
||||
<input
|
||||
oninput={() => {
|
||||
if (!playerElement) return;
|
||||
<label class="slider round m l" id="volume-slider">
|
||||
{#key playerVolume}
|
||||
<input
|
||||
oninput={() => {
|
||||
if (!playerElement) return;
|
||||
|
||||
playerElement.volume = playerVolume;
|
||||
}}
|
||||
bind:value={playerVolume}
|
||||
type="range"
|
||||
step="0.1"
|
||||
max="1"
|
||||
/>
|
||||
{/key}
|
||||
<span></span>
|
||||
</label>
|
||||
</article>
|
||||
playerElement.volume = playerVolume;
|
||||
}}
|
||||
bind:value={playerVolume}
|
||||
type="range"
|
||||
step="0.1"
|
||||
max="1"
|
||||
/>
|
||||
{/key} <span></span>
|
||||
</label>
|
||||
{/if}
|
||||
</nav>
|
||||
|
||||
<div class="max"></div>
|
||||
|
||||
<nav class="no-wrap">
|
||||
<p class="chip secondary m l" style="border: none;">
|
||||
<p class="chip m l" style="height: 100%;">
|
||||
{#if data.video.liveNow}
|
||||
{$_('thumbnail.live')}
|
||||
{:else}
|
||||
@@ -1070,7 +1157,7 @@
|
||||
{/if}
|
||||
</p>
|
||||
{#if playerTextTracks && playerTextTracks.length > 0 && !data.video.liveNow}
|
||||
<button class="secondary">
|
||||
<button class="inverse-primary">
|
||||
<i>closed_caption</i>
|
||||
<menu class="no-wrap mobile" id="cc-menu" data-ui="#cc-menu">
|
||||
<li
|
||||
@@ -1095,7 +1182,7 @@
|
||||
</menu>
|
||||
</button>
|
||||
{/if}
|
||||
<button class="secondary">
|
||||
<button class="inverse-primary">
|
||||
<i>settings</i>
|
||||
<menu class="no-wrap mobile" id="settings-menu">
|
||||
{#if playerSettings !== 'root'}
|
||||
@@ -1231,7 +1318,7 @@
|
||||
</button>
|
||||
{#if document.pictureInPictureEnabled}
|
||||
<button
|
||||
class="secondary"
|
||||
class="inverse-primary"
|
||||
onclick={() => {
|
||||
(playerElement as HTMLVideoElement).requestPictureInPicture();
|
||||
}}
|
||||
@@ -1240,7 +1327,7 @@
|
||||
</button>
|
||||
{/if}
|
||||
<button
|
||||
class="secondary"
|
||||
class="inverse-primary"
|
||||
onclick={() => {
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
@@ -1305,13 +1392,21 @@
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#player-controls span {
|
||||
clip-path: none;
|
||||
}
|
||||
|
||||
#player-center {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.player-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: var(--video-player-height);
|
||||
}
|
||||
|
||||
#mobile-time {
|
||||
@@ -1319,15 +1414,24 @@
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
opacity: 0;
|
||||
transition: opacity 2s ease;
|
||||
}
|
||||
|
||||
#mobile-time .chip {
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#progress-slider > span {
|
||||
transition: 0.25s;
|
||||
}
|
||||
|
||||
#progress-slider {
|
||||
block-size: 1.5em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#player-container:focus-within #player-controls,
|
||||
#player-container:active #player-controls,
|
||||
#player-container:hover #player-controls {
|
||||
@@ -1342,6 +1446,42 @@
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.seek-double-click {
|
||||
background-color: var(--secondary-container);
|
||||
height: var(--video-player-height);
|
||||
color: var(--secondary);
|
||||
width: 100%;
|
||||
opacity: 0.8;
|
||||
padding: 1em;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.seek-double-click.buffer-right {
|
||||
border-top-left-radius: 2rem;
|
||||
border-bottom-left-radius: 2rem;
|
||||
}
|
||||
|
||||
.seek-double-click.buffer-left {
|
||||
border-top-right-radius: 2rem;
|
||||
border-bottom-right-radius: 2rem;
|
||||
}
|
||||
|
||||
.buffered-bar {
|
||||
position: absolute;
|
||||
height: 1rem;
|
||||
background: var(--secondary);
|
||||
top: 50%;
|
||||
left: 0;
|
||||
transform: translateY(-50%);
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
border-top-right-radius: 2rem;
|
||||
border-bottom-right-radius: 2rem;
|
||||
}
|
||||
|
||||
menu.mobile {
|
||||
transform: scale(1) translateY(-40%) translateX(0);
|
||||
width: 300px;
|
||||
@@ -1389,4 +1529,25 @@
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chip {
|
||||
background-color: var(--inverse-primary);
|
||||
color: var(--primary);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.slider > span {
|
||||
background-color: var(--inverse-primary);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.slider > input::-webkit-slider-thumb {
|
||||
background-color: var(--inverse-primary);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.slider > input::-moz-range-thumb {
|
||||
background-color: var(--inverse-primary);
|
||||
color: var(--primary);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
let ghContributors: { login: string; avatar_url: string; type: 'Bot' | 'User' }[] = $state([]);
|
||||
onMount(() => {
|
||||
fetch('https://api.github.com/repos/Materialious/Materialious/contributors', {
|
||||
fetch(`${document.location.origin}/localApi/ghContributors.json`, {
|
||||
priority: 'low'
|
||||
}).then(async (resp) => {
|
||||
if (!resp.ok) {
|
||||
|
||||
@@ -172,7 +172,15 @@
|
||||
</dialog>
|
||||
|
||||
<style>
|
||||
.tabbed {
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
.tabbed > a {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
#dialog-settings {
|
||||
width: fit-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -41,23 +41,14 @@ button,
|
||||
}
|
||||
|
||||
nav.top {
|
||||
padding-top: calc(var(--safe-area-inset-top) + 1rem) !important;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
nav.bottom {
|
||||
padding-bottom: var(--safe-area-inset-bottom) !important;
|
||||
}
|
||||
|
||||
main.root {
|
||||
max-height: 100vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
dialog {
|
||||
padding-top: calc(var(--safe-area-inset-top) + 1rem) !important;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 1em !important;
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
"defaultPage": "Alapértelmezett oldal",
|
||||
"player": {
|
||||
"youtubeJsFallBack": "Helyi videó visszatérés van használatban",
|
||||
"preferredQuality": "Előnyben részesített minőség",
|
||||
"preferredQuality": "Előnyben részesített felbontás",
|
||||
"share": {
|
||||
"includeTimestamp": "Időbélyeggel ellátott",
|
||||
"title": "Megosztás",
|
||||
@@ -150,7 +150,17 @@
|
||||
"enableYoutubejsPerm": "Mindig engedélyezze a helyi videó visszatérést",
|
||||
"retryText": "A videó betöltése siketelen, hogyan szeretné folytatni?",
|
||||
"youtubeJsLoading": "A videó betöltése sikertelen, újraprobálkozás a helyi videó visszatéréssel.",
|
||||
"premiere": "A videó elérhető lesz ekkor"
|
||||
"premiere": "A videó elérhető lesz ekkor",
|
||||
"controls": {
|
||||
"back": "Vissza",
|
||||
"quality": "Felbontás",
|
||||
"auto": "Automatikus",
|
||||
"playbackSpeed": "Lejátszási sebesség",
|
||||
"loop": "Folyamatos lejátszás",
|
||||
"on": "Be",
|
||||
"off": "Ki",
|
||||
"language": "Nyelv"
|
||||
}
|
||||
},
|
||||
"title": "Cím",
|
||||
"subscriptions": {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"cancel": "İptal",
|
||||
"create": "Oluştur",
|
||||
"title": "Başlık",
|
||||
"searchPlaceholder": "Ara...",
|
||||
"searchPlaceholder": "Ara",
|
||||
"delete": "Sil",
|
||||
"deleteAllHistory": "Tüm geçmişi sil",
|
||||
"skipping": "Atla",
|
||||
@@ -44,7 +44,9 @@
|
||||
"private": "Gizli",
|
||||
"playVideos": "Videoları oynat",
|
||||
"shuffleVideos": "Videoları karışık oynat",
|
||||
"loopPlaylist": "Çalma listesini tekrarla"
|
||||
"loopPlaylist": "Çalma listesini tekrarla",
|
||||
"next": "Sıradaki",
|
||||
"previous": "Önceki"
|
||||
},
|
||||
"thumbnail": {
|
||||
"live": "CANLI",
|
||||
@@ -67,7 +69,8 @@
|
||||
"title": "Paylaş",
|
||||
"materialiousLink": "Bağlantıyı Materialious a kopyala",
|
||||
"invidiousRedirect": "Invidious yönlendirme bağlantısını kopyala",
|
||||
"youtubeLink": "Youtube bağlantısını kopyala"
|
||||
"youtubeLink": "Youtube bağlantısını kopyala",
|
||||
"copiedSuccess": "Panoya kopyalandı"
|
||||
},
|
||||
"download": "İndir",
|
||||
"downloadSteps": {
|
||||
@@ -82,7 +85,19 @@
|
||||
},
|
||||
"noPlaylists": "Oynatma listesi yok",
|
||||
"unableToLoadComments": "Yorumlar yüklenemiyor",
|
||||
"addToPlaylist": "Oynatma listesine ekle"
|
||||
"addToPlaylist": "Oynatma listesine ekle",
|
||||
"pauseTimer": "Zamanlayıcıyı durdur",
|
||||
"preferredQuality": "Tercih edilen kalite",
|
||||
"chapters": "Bölümler",
|
||||
"defaultLanguage": "Varsayılan Dil",
|
||||
"retryText": "Video yüklenemedi, nasıl devam etmek istersiniz?",
|
||||
"controls": {
|
||||
"quality": "Kalite",
|
||||
"auto": "Otomatik",
|
||||
"playbackSpeed": "Oynatma hızı",
|
||||
"loop": "Döngü",
|
||||
"language": "Dil"
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
"interface": "Arayüz",
|
||||
@@ -101,7 +116,8 @@
|
||||
"theme": "Tema",
|
||||
"darkMode": "Koyu mod",
|
||||
"lightMode": "Açık Mod",
|
||||
"color": "Renk"
|
||||
"color": "Renk",
|
||||
"AmoledTheme": "Amoled tema"
|
||||
},
|
||||
"searchSuggestions": "Önerileri ara",
|
||||
"previewVideoOnHover": "Fareyle üzerine gelindiğinde videoyu ön izleyin",
|
||||
@@ -141,7 +157,11 @@
|
||||
"thumbnailInstanceUrl": "Küçük resim görünüm URL'si",
|
||||
"titleOnly": "Sadece başlık"
|
||||
},
|
||||
"allowInsecureRequests": "Güvenli olmayan isteklere izin ver"
|
||||
"allowInsecureRequests": "Güvenli olmayan isteklere izin ver",
|
||||
"about": "Hakkında",
|
||||
"lowBandwidthMode": "Düşük bant genişliği modu",
|
||||
"searchHistory": "Arama geçmişi",
|
||||
"disableAutoUpdate": "Otomatik güncellemeleri devre dışı bırak"
|
||||
},
|
||||
"subscribe": "Abone Ol",
|
||||
"premium": "Premium YouTube içeriği Materialious ile izlenemez.",
|
||||
@@ -157,5 +177,18 @@
|
||||
"comments": "yorumlar",
|
||||
"reply": "cevapla",
|
||||
"login": "Giriş",
|
||||
"invidiousLogin": "Lütfen Invidious hesabınız ile giriş yapınız"
|
||||
"invidiousLogin": "Lütfen Invidious hesabınız ile giriş yapınız",
|
||||
"popularPageDisabled": "Popüler sayfası Yöneticiler tarafından devre dışı bırakıldı",
|
||||
"filters": {
|
||||
"filters": "Filtreler",
|
||||
"type": "Tür",
|
||||
"uploadDate": "Yüklenme tarihi",
|
||||
"duration": "Uzunluk",
|
||||
"features": "Özellikler"
|
||||
},
|
||||
"contributors": "Katkıda bulunanlar",
|
||||
"version": "Sürüm",
|
||||
"newest": "En yeni",
|
||||
"oldest": "En eski",
|
||||
"popular": "Popüler"
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ export interface PlayerEvents {
|
||||
}
|
||||
|
||||
export const playbackRates = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3];
|
||||
export const playerDoubleTapSeek = 10.0;
|
||||
|
||||
export function goToPreviousVideo(playlistId: string | null) {
|
||||
const previousVideos = get(playerPlaylistHistory);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Capacitor } from '@capacitor/core';
|
||||
import ui from 'beercss';
|
||||
import { tick } from 'svelte';
|
||||
import { get } from 'svelte/store';
|
||||
import { SafeArea } from '@capacitor-community/safe-area';
|
||||
import { SafeArea, SystemBarsStyle, SystemBarsType } from '@capacitor-community/safe-area';
|
||||
import { darkModeStore, interfaceAmoledTheme } from './store';
|
||||
|
||||
export async function getDynamicTheme(mode?: string): Promise<Record<string, string>> {
|
||||
@@ -23,20 +23,15 @@ export async function setStatusBarColor() {
|
||||
|
||||
await tick();
|
||||
|
||||
const surfaceColor = get(interfaceAmoledTheme)
|
||||
? '#000000'
|
||||
: (await getDynamicTheme())['--surface-container'];
|
||||
await SafeArea.setSystemBarsStyle({
|
||||
style: get(darkModeStore) ? SystemBarsStyle.Dark : SystemBarsStyle.Light
|
||||
});
|
||||
|
||||
const contentColor = !get(darkModeStore) ? 'dark' : 'light';
|
||||
|
||||
await SafeArea.enable({
|
||||
config: {
|
||||
customColorsForSystemBars: true,
|
||||
statusBarColor: surfaceColor,
|
||||
statusBarContent: contentColor,
|
||||
navigationBarColor: surfaceColor,
|
||||
navigationBarContent: contentColor
|
||||
}
|
||||
await SafeArea.showSystemBars({
|
||||
type: SystemBarsType.NavigationBar
|
||||
});
|
||||
await SafeArea.showSystemBars({
|
||||
type: SystemBarsType.StatusBar
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -525,11 +525,6 @@
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.pip > .pip-info > nav {
|
||||
align-items: start;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
.pip > .pip-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -12,6 +12,13 @@
|
||||
box-shadow: none !important;
|
||||
}
|
||||
</style>
|
||||
{:else}
|
||||
<style>
|
||||
:focus {
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
</style>
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"sourceLanguageTag": "en",
|
||||
"languageTags": [
|
||||
"en",
|
||||
"de",
|
||||
"es",
|
||||
"nl",
|
||||
"pt-BR",
|
||||
"ru",
|
||||
"sh",
|
||||
"tr"
|
||||
],
|
||||
"modules": [
|
||||
"https://cdn.jsdelivr.net/npm/@inlang/plugin-i18next@latest/dist/index.js"
|
||||
],
|
||||
"plugin.inlang.i18next": {
|
||||
"pathPattern": "./materialious/src/lib/i18n/locales/{languageTag}.json",
|
||||
"variableReferencePattern": [
|
||||
"{{",
|
||||
"}}"
|
||||
]
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3,7 +3,7 @@ import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
LATEST_VERSION = "1.12.8"
|
||||
LATEST_VERSION = "1.12.9"
|
||||
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