@@ -7,8 +7,8 @@ android {
|
||||
applicationId "us.materialio.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 138
|
||||
versionName "1.9.21"
|
||||
versionCode 139
|
||||
versionName "1.9.22"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
@@ -55,7 +55,11 @@
|
||||
<content_attribute id="social-contacts">intense</content_attribute>
|
||||
</content_rating>
|
||||
<releases>
|
||||
<release version="1.9.21" date="2025-7-21">
|
||||
|
||||
<release version="1.9.22" date="2025-7-26">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.9.22</url>
|
||||
</release>
|
||||
<release version="1.9.21" date="2025-7-21">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.9.21</url>
|
||||
</release>
|
||||
<release version="1.9.20" date="2025-7-09">
|
||||
|
||||
Generated
+10
-9
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.9.21",
|
||||
"version": "1.9.22",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "Materialious",
|
||||
"version": "1.9.21",
|
||||
"version": "1.9.22",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.0",
|
||||
@@ -22,7 +22,7 @@
|
||||
"jsonfile": "^6.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^37.2.1",
|
||||
"electron": "^37.2.3",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-rebuild": "^3.2.9",
|
||||
"typescript": "^5.7.3"
|
||||
@@ -2495,9 +2495,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "37.2.1",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-37.2.1.tgz",
|
||||
"integrity": "sha512-ae2EbzRNqIAHlftfCHtbbt6EgJUW8+zxWLONqNnn2iSrLF0O/pbxbff3xcpZYPpmFBs4uqjoi+s4QS7DQ+zZ/w==",
|
||||
"version": "37.2.3",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-37.2.3.tgz",
|
||||
"integrity": "sha512-JRKKn8cRDXDfkC+oWISbYs+c+L6RA776JM0NiB9bn2yV8H/LnBUlVPzKKfsXgrUIokN4YcbCw694vfAdEJwtGw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
@@ -3093,15 +3093,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
||||
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.9.21",
|
||||
"version": "1.9.22",
|
||||
"description": "Modern material design for Invidious.",
|
||||
"author": {
|
||||
"name": "Ward Pearce",
|
||||
@@ -35,7 +35,7 @@
|
||||
"jsonfile": "^6.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^37.2.1",
|
||||
"electron": "^37.2.3",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-rebuild": "^3.2.9",
|
||||
"typescript": "^5.7.3"
|
||||
@@ -44,4 +44,4 @@
|
||||
"capacitor",
|
||||
"electron"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,7 @@ import {
|
||||
getCapacitorElectronConfig,
|
||||
setupElectronDeepLinking
|
||||
} from '@capacitor-community/electron';
|
||||
import type { MenuItemConstructorOptions } from 'electron';
|
||||
import { app, ipcMain, MenuItem, session } from 'electron';
|
||||
import { app, ipcMain, session } from 'electron';
|
||||
import electronIsDev from 'electron-is-dev';
|
||||
import unhandled from 'electron-unhandled';
|
||||
import { autoUpdater } from 'electron-updater';
|
||||
@@ -16,25 +15,12 @@ import { ElectronCapacitorApp, setupContentSecurityPolicy, setupReloadWatcher }
|
||||
// Graceful handling of unhandled errors.
|
||||
unhandled();
|
||||
|
||||
// Define our menu templates (these are optional)
|
||||
const trayMenuTemplate: (MenuItemConstructorOptions | MenuItem)[] = [
|
||||
new MenuItem({ label: 'Quit App', role: 'quit' })
|
||||
];
|
||||
const appMenuBarMenuTemplate: (MenuItemConstructorOptions | MenuItem)[] = [
|
||||
{ role: process.platform === 'darwin' ? 'appMenu' : 'fileMenu' },
|
||||
{ role: 'viewMenu' }
|
||||
];
|
||||
|
||||
// Get Config options from capacitor.config
|
||||
const capacitorFileConfig: CapacitorElectronConfig = getCapacitorElectronConfig();
|
||||
|
||||
// Initialize our app. You can pass menu templates into the app here.
|
||||
// const myCapacitorApp = new ElectronCapacitorApp(capacitorFileConfig);
|
||||
const myCapacitorApp = new ElectronCapacitorApp(
|
||||
capacitorFileConfig,
|
||||
trayMenuTemplate,
|
||||
appMenuBarMenuTemplate
|
||||
);
|
||||
const myCapacitorApp = new ElectronCapacitorApp(capacitorFileConfig);
|
||||
|
||||
// If deeplinking is enabled then we will set it up here.
|
||||
if (capacitorFileConfig.electron?.deepLinkingEnabled) {
|
||||
|
||||
+217
-193
@@ -1,13 +1,23 @@
|
||||
import type { CapacitorElectronConfig } from '@capacitor-community/electron';
|
||||
import {
|
||||
CapacitorSplashScreen,
|
||||
CapElectronEventEmitter,
|
||||
setupCapacitorElectronPlugins,
|
||||
CapacitorSplashScreen,
|
||||
CapElectronEventEmitter,
|
||||
setupCapacitorElectronPlugins
|
||||
} from '@capacitor-community/electron';
|
||||
import { USER_AGENT } from 'bgutils-js';
|
||||
import chokidar from 'chokidar';
|
||||
import type { MenuItemConstructorOptions } from 'electron';
|
||||
import { app, BrowserWindow, Menu, MenuItem, nativeImage, session, shell, Tray } from 'electron';
|
||||
import {
|
||||
app,
|
||||
BrowserWindow,
|
||||
Menu,
|
||||
MenuItem,
|
||||
nativeImage,
|
||||
session,
|
||||
shell,
|
||||
Tray,
|
||||
globalShortcut
|
||||
} from 'electron';
|
||||
import electronIsDev from 'electron-is-dev';
|
||||
import electronServe from 'electron-serve';
|
||||
import windowStateKeeper from 'electron-window-state';
|
||||
@@ -15,222 +25,236 @@ import { join } from 'path';
|
||||
|
||||
// Define components for a watcher to detect when the webapp is changed so we can reload in Dev mode.
|
||||
const reloadWatcher = {
|
||||
debouncer: null,
|
||||
ready: false,
|
||||
watcher: null,
|
||||
debouncer: null,
|
||||
ready: false,
|
||||
watcher: null
|
||||
};
|
||||
export function setupReloadWatcher(electronCapacitorApp: ElectronCapacitorApp): void {
|
||||
reloadWatcher.watcher = chokidar
|
||||
.watch(join(app.getAppPath(), 'app'), {
|
||||
ignored: /[/\\]\./,
|
||||
persistent: true,
|
||||
})
|
||||
.on('ready', () => {
|
||||
reloadWatcher.ready = true;
|
||||
})
|
||||
.on('all', (_event, _path) => {
|
||||
if (reloadWatcher.ready) {
|
||||
clearTimeout(reloadWatcher.debouncer);
|
||||
reloadWatcher.debouncer = setTimeout(async () => {
|
||||
electronCapacitorApp.getMainWindow().webContents.reload();
|
||||
reloadWatcher.ready = false;
|
||||
clearTimeout(reloadWatcher.debouncer);
|
||||
reloadWatcher.debouncer = null;
|
||||
reloadWatcher.watcher = null;
|
||||
setupReloadWatcher(electronCapacitorApp);
|
||||
}, 1500);
|
||||
}
|
||||
});
|
||||
reloadWatcher.watcher = chokidar
|
||||
.watch(join(app.getAppPath(), 'app'), {
|
||||
ignored: /[/\\]\./,
|
||||
persistent: true
|
||||
})
|
||||
.on('ready', () => {
|
||||
reloadWatcher.ready = true;
|
||||
})
|
||||
.on('all', (_event, _path) => {
|
||||
if (reloadWatcher.ready) {
|
||||
clearTimeout(reloadWatcher.debouncer);
|
||||
reloadWatcher.debouncer = setTimeout(async () => {
|
||||
electronCapacitorApp.getMainWindow().webContents.reload();
|
||||
reloadWatcher.ready = false;
|
||||
clearTimeout(reloadWatcher.debouncer);
|
||||
reloadWatcher.debouncer = null;
|
||||
reloadWatcher.watcher = null;
|
||||
setupReloadWatcher(electronCapacitorApp);
|
||||
}, 1500);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Define our class to manage our app.
|
||||
export class ElectronCapacitorApp {
|
||||
private MainWindow: BrowserWindow | null = null;
|
||||
private SplashScreen: CapacitorSplashScreen | null = null;
|
||||
private TrayIcon: Tray | null = null;
|
||||
private CapacitorFileConfig: CapacitorElectronConfig;
|
||||
private TrayMenuTemplate: (MenuItem | MenuItemConstructorOptions)[] = [
|
||||
new MenuItem({ label: 'Quit App', role: 'quit' }),
|
||||
];
|
||||
private AppMenuBarMenuTemplate: (MenuItem | MenuItemConstructorOptions)[] = [
|
||||
{ role: process.platform === 'darwin' ? 'appMenu' : 'fileMenu' },
|
||||
{ role: 'viewMenu' },
|
||||
];
|
||||
private mainWindowState;
|
||||
private loadWebApp;
|
||||
private customScheme: string;
|
||||
private MainWindow: BrowserWindow | null = null;
|
||||
private SplashScreen: CapacitorSplashScreen | null = null;
|
||||
private TrayIcon: Tray | null = null;
|
||||
private CapacitorFileConfig: CapacitorElectronConfig;
|
||||
private TrayMenuTemplate: (MenuItem | MenuItemConstructorOptions)[] = [
|
||||
new MenuItem({ label: 'Quit App', role: 'quit' })
|
||||
];
|
||||
private mainWindowState;
|
||||
private loadWebApp;
|
||||
private customScheme: string;
|
||||
|
||||
constructor(
|
||||
capacitorFileConfig: CapacitorElectronConfig,
|
||||
trayMenuTemplate?: (MenuItemConstructorOptions | MenuItem)[],
|
||||
appMenuBarMenuTemplate?: (MenuItemConstructorOptions | MenuItem)[]
|
||||
) {
|
||||
this.CapacitorFileConfig = capacitorFileConfig;
|
||||
constructor(
|
||||
capacitorFileConfig: CapacitorElectronConfig,
|
||||
trayMenuTemplate?: (MenuItemConstructorOptions | MenuItem)[]
|
||||
) {
|
||||
this.CapacitorFileConfig = capacitorFileConfig;
|
||||
|
||||
this.customScheme = this.CapacitorFileConfig.electron?.customUrlScheme ?? 'capacitor-electron';
|
||||
this.customScheme = this.CapacitorFileConfig.electron?.customUrlScheme ?? 'capacitor-electron';
|
||||
|
||||
if (trayMenuTemplate) {
|
||||
this.TrayMenuTemplate = trayMenuTemplate;
|
||||
}
|
||||
if (trayMenuTemplate) {
|
||||
this.TrayMenuTemplate = trayMenuTemplate;
|
||||
}
|
||||
|
||||
if (appMenuBarMenuTemplate) {
|
||||
this.AppMenuBarMenuTemplate = appMenuBarMenuTemplate;
|
||||
}
|
||||
// Setup our web app loader, this lets us load apps like react, vue, and angular without changing their build chains.
|
||||
this.loadWebApp = electronServe({
|
||||
directory: join(app.getAppPath(), 'app'),
|
||||
scheme: this.customScheme
|
||||
});
|
||||
}
|
||||
|
||||
// Setup our web app loader, this lets us load apps like react, vue, and angular without changing their build chains.
|
||||
this.loadWebApp = electronServe({
|
||||
directory: join(app.getAppPath(), 'app'),
|
||||
scheme: this.customScheme,
|
||||
});
|
||||
}
|
||||
// Helper function to load in the app.
|
||||
private async loadMainWindow(thisRef: any) {
|
||||
await thisRef.loadWebApp(thisRef.MainWindow);
|
||||
}
|
||||
|
||||
// Helper function to load in the app.
|
||||
private async loadMainWindow(thisRef: any) {
|
||||
await thisRef.loadWebApp(thisRef.MainWindow);
|
||||
}
|
||||
// Expose the mainWindow ref for use outside of the class.
|
||||
getMainWindow(): BrowserWindow {
|
||||
return this.MainWindow;
|
||||
}
|
||||
|
||||
// Expose the mainWindow ref for use outside of the class.
|
||||
getMainWindow(): BrowserWindow {
|
||||
return this.MainWindow;
|
||||
}
|
||||
getCustomURLScheme(): string {
|
||||
return this.customScheme;
|
||||
}
|
||||
|
||||
getCustomURLScheme(): string {
|
||||
return this.customScheme;
|
||||
}
|
||||
async init(): Promise<void> {
|
||||
const icon = nativeImage.createFromPath(
|
||||
join(app.getAppPath(), 'assets', process.platform === 'win32' ? 'appIcon.ico' : 'appIcon.png')
|
||||
);
|
||||
this.mainWindowState = windowStateKeeper({
|
||||
defaultWidth: 1000,
|
||||
defaultHeight: 800
|
||||
});
|
||||
// Setup preload script path and construct our main window.
|
||||
const preloadPath = join(app.getAppPath(), 'build', 'src', 'preload.js');
|
||||
this.MainWindow = new BrowserWindow({
|
||||
icon,
|
||||
show: false,
|
||||
x: this.mainWindowState.x,
|
||||
y: this.mainWindowState.y,
|
||||
width: this.mainWindowState.width,
|
||||
height: this.mainWindowState.height,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: true,
|
||||
webSecurity: false,
|
||||
// Use preload to inject the electron varriant overrides for capacitor plugins.
|
||||
// preload: join(app.getAppPath(), "node_modules", "@capacitor-community", "electron", "dist", "runtime", "electron-rt.js"),
|
||||
preload: preloadPath
|
||||
}
|
||||
});
|
||||
this.mainWindowState.manage(this.MainWindow);
|
||||
|
||||
async init(): Promise<void> {
|
||||
const icon = nativeImage.createFromPath(
|
||||
join(app.getAppPath(), 'assets', process.platform === 'win32' ? 'appIcon.ico' : 'appIcon.png')
|
||||
);
|
||||
this.mainWindowState = windowStateKeeper({
|
||||
defaultWidth: 1000,
|
||||
defaultHeight: 800,
|
||||
});
|
||||
// Setup preload script path and construct our main window.
|
||||
const preloadPath = join(app.getAppPath(), 'build', 'src', 'preload.js');
|
||||
this.MainWindow = new BrowserWindow({
|
||||
icon,
|
||||
show: false,
|
||||
x: this.mainWindowState.x,
|
||||
y: this.mainWindowState.y,
|
||||
width: this.mainWindowState.width,
|
||||
height: this.mainWindowState.height,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: true,
|
||||
webSecurity: false,
|
||||
// Use preload to inject the electron varriant overrides for capacitor plugins.
|
||||
// preload: join(app.getAppPath(), "node_modules", "@capacitor-community", "electron", "dist", "runtime", "electron-rt.js"),
|
||||
preload: preloadPath,
|
||||
},
|
||||
});
|
||||
this.mainWindowState.manage(this.MainWindow);
|
||||
if (this.CapacitorFileConfig.backgroundColor) {
|
||||
this.MainWindow.setBackgroundColor(this.CapacitorFileConfig.electron.backgroundColor);
|
||||
}
|
||||
|
||||
if (this.CapacitorFileConfig.backgroundColor) {
|
||||
this.MainWindow.setBackgroundColor(this.CapacitorFileConfig.electron.backgroundColor);
|
||||
}
|
||||
// If we close the main window with the splashscreen enabled we need to destory the ref.
|
||||
this.MainWindow.on('closed', () => {
|
||||
if (
|
||||
this.SplashScreen?.getSplashWindow() &&
|
||||
!this.SplashScreen.getSplashWindow().isDestroyed()
|
||||
) {
|
||||
this.SplashScreen.getSplashWindow().close();
|
||||
}
|
||||
});
|
||||
|
||||
// If we close the main window with the splashscreen enabled we need to destory the ref.
|
||||
this.MainWindow.on('closed', () => {
|
||||
if (this.SplashScreen?.getSplashWindow() && !this.SplashScreen.getSplashWindow().isDestroyed()) {
|
||||
this.SplashScreen.getSplashWindow().close();
|
||||
}
|
||||
});
|
||||
// When the tray icon is enabled, setup the options.
|
||||
if (this.CapacitorFileConfig.electron?.trayIconAndMenuEnabled) {
|
||||
this.TrayIcon = new Tray(icon);
|
||||
this.TrayIcon.on('double-click', () => {
|
||||
if (this.MainWindow) {
|
||||
if (this.MainWindow.isVisible()) {
|
||||
this.MainWindow.hide();
|
||||
} else {
|
||||
this.MainWindow.show();
|
||||
this.MainWindow.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.TrayIcon.on('click', () => {
|
||||
if (this.MainWindow) {
|
||||
if (this.MainWindow.isVisible()) {
|
||||
this.MainWindow.hide();
|
||||
} else {
|
||||
this.MainWindow.show();
|
||||
this.MainWindow.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.TrayIcon.setToolTip(app.getName());
|
||||
this.TrayIcon.setContextMenu(Menu.buildFromTemplate(this.TrayMenuTemplate));
|
||||
}
|
||||
|
||||
// When the tray icon is enabled, setup the options.
|
||||
if (this.CapacitorFileConfig.electron?.trayIconAndMenuEnabled) {
|
||||
this.TrayIcon = new Tray(icon);
|
||||
this.TrayIcon.on('double-click', () => {
|
||||
if (this.MainWindow) {
|
||||
if (this.MainWindow.isVisible()) {
|
||||
this.MainWindow.hide();
|
||||
} else {
|
||||
this.MainWindow.show();
|
||||
this.MainWindow.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.TrayIcon.on('click', () => {
|
||||
if (this.MainWindow) {
|
||||
if (this.MainWindow.isVisible()) {
|
||||
this.MainWindow.hide();
|
||||
} else {
|
||||
this.MainWindow.show();
|
||||
this.MainWindow.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.TrayIcon.setToolTip(app.getName());
|
||||
this.TrayIcon.setContextMenu(Menu.buildFromTemplate(this.TrayMenuTemplate));
|
||||
}
|
||||
// Disable Menu Bar at the top.
|
||||
Menu.setApplicationMenu(null);
|
||||
|
||||
// Setup the main manu bar at the top of our window.
|
||||
Menu.setApplicationMenu(Menu.buildFromTemplate(this.AppMenuBarMenuTemplate));
|
||||
// If the splashscreen is enabled, show it first while the main window loads then switch it out for the main window, or just load the main window from the start.
|
||||
if (this.CapacitorFileConfig.electron?.splashScreenEnabled) {
|
||||
this.SplashScreen = new CapacitorSplashScreen({
|
||||
imageFilePath: join(
|
||||
app.getAppPath(),
|
||||
'assets',
|
||||
this.CapacitorFileConfig.electron?.splashScreenImageName ?? 'splash.png'
|
||||
),
|
||||
windowWidth: 400,
|
||||
windowHeight: 400
|
||||
});
|
||||
this.SplashScreen.init(this.loadMainWindow, this);
|
||||
} else {
|
||||
this.loadMainWindow(this);
|
||||
}
|
||||
|
||||
// If the splashscreen is enabled, show it first while the main window loads then switch it out for the main window, or just load the main window from the start.
|
||||
if (this.CapacitorFileConfig.electron?.splashScreenEnabled) {
|
||||
this.SplashScreen = new CapacitorSplashScreen({
|
||||
imageFilePath: join(
|
||||
app.getAppPath(),
|
||||
'assets',
|
||||
this.CapacitorFileConfig.electron?.splashScreenImageName ?? 'splash.png'
|
||||
),
|
||||
windowWidth: 400,
|
||||
windowHeight: 400,
|
||||
});
|
||||
this.SplashScreen.init(this.loadMainWindow, this);
|
||||
} else {
|
||||
this.loadMainWindow(this);
|
||||
}
|
||||
globalShortcut.register('Control+Shift+I', () => {
|
||||
this.MainWindow.webContents.toggleDevTools();
|
||||
});
|
||||
|
||||
// Security
|
||||
this.MainWindow.webContents.setWindowOpenHandler((details) => {
|
||||
shell.openExternal(details.url);
|
||||
return { action: 'deny' };
|
||||
});
|
||||
this.MainWindow.webContents.on('will-navigate', (event, _newURL) => {
|
||||
if (!this.MainWindow.webContents.getURL().includes(this.customScheme)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
// Link electron plugins into the system.
|
||||
setupCapacitorElectronPlugins();
|
||||
let zoomFactor = 1.0;
|
||||
globalShortcut.register('Control+Plus', () => {
|
||||
zoomFactor += 0.1;
|
||||
this.MainWindow.webContents.setZoomFactor(zoomFactor);
|
||||
});
|
||||
|
||||
// When the web app is loaded we hide the splashscreen if needed and show the mainwindow.
|
||||
this.MainWindow.webContents.on('dom-ready', () => {
|
||||
if (this.CapacitorFileConfig.electron?.splashScreenEnabled) {
|
||||
this.SplashScreen.getSplashWindow().hide();
|
||||
}
|
||||
if (!this.CapacitorFileConfig.electron?.hideMainWindowOnLaunch) {
|
||||
this.MainWindow.show();
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (electronIsDev) {
|
||||
this.MainWindow.webContents.openDevTools();
|
||||
}
|
||||
CapElectronEventEmitter.emit('CAPELECTRON_DeeplinkListenerInitialized', '');
|
||||
}, 400);
|
||||
});
|
||||
}
|
||||
globalShortcut.register('Control+Minus', () => {
|
||||
zoomFactor = Math.max(0.2, zoomFactor - 0.1);
|
||||
this.MainWindow.webContents.setZoomFactor(zoomFactor);
|
||||
});
|
||||
|
||||
globalShortcut.register('Control+0', () => {
|
||||
zoomFactor = 1.0;
|
||||
this.MainWindow.webContents.setZoomFactor(zoomFactor);
|
||||
});
|
||||
|
||||
// Security
|
||||
this.MainWindow.webContents.setWindowOpenHandler((details) => {
|
||||
shell.openExternal(details.url);
|
||||
return { action: 'deny' };
|
||||
});
|
||||
this.MainWindow.webContents.on('will-navigate', (event, _newURL) => {
|
||||
if (!this.MainWindow.webContents.getURL().includes(this.customScheme)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
// Link electron plugins into the system.
|
||||
setupCapacitorElectronPlugins();
|
||||
|
||||
// When the web app is loaded we hide the splashscreen if needed and show the mainwindow.
|
||||
this.MainWindow.webContents.on('dom-ready', () => {
|
||||
if (this.CapacitorFileConfig.electron?.splashScreenEnabled) {
|
||||
this.SplashScreen.getSplashWindow().hide();
|
||||
}
|
||||
if (!this.CapacitorFileConfig.electron?.hideMainWindowOnLaunch) {
|
||||
this.MainWindow.show();
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (electronIsDev) {
|
||||
this.MainWindow.webContents.openDevTools();
|
||||
}
|
||||
CapElectronEventEmitter.emit('CAPELECTRON_DeeplinkListenerInitialized', '');
|
||||
}, 400);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Set a CSP up for our application based on the custom scheme
|
||||
export function setupContentSecurityPolicy(customScheme: string): void {
|
||||
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
||||
callback({
|
||||
responseHeaders: {
|
||||
...details.responseHeaders,
|
||||
},
|
||||
});
|
||||
});
|
||||
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
||||
callback({
|
||||
responseHeaders: {
|
||||
...details.responseHeaders
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
|
||||
const uri = new URL(details.url);
|
||||
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
|
||||
const uri = new URL(details.url);
|
||||
|
||||
details.requestHeaders['User-Agent'] = USER_AGENT;
|
||||
details.requestHeaders['origin'] = uri.origin;
|
||||
details.requestHeaders['host'] = uri.host;
|
||||
details.requestHeaders['User-Agent'] = USER_AGENT;
|
||||
details.requestHeaders['origin'] = uri.origin;
|
||||
details.requestHeaders['host'] = uri.host;
|
||||
|
||||
callback({ requestHeaders: details.requestHeaders });
|
||||
});
|
||||
callback({ requestHeaders: details.requestHeaders });
|
||||
});
|
||||
}
|
||||
|
||||
Generated
+117
-61
@@ -55,7 +55,7 @@
|
||||
"@vite-pwa/sveltekit": "^0.6.6",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.45.1",
|
||||
"eslint-plugin-svelte": "^3.11.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-svelte": "^3.2.7",
|
||||
@@ -3598,9 +3598,9 @@
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
@@ -5699,22 +5699,6 @@
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-compat-utils": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz",
|
||||
"integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-config-prettier": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
|
||||
@@ -5729,32 +5713,31 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-svelte": {
|
||||
"version": "2.46.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.46.1.tgz",
|
||||
"integrity": "sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==",
|
||||
"version": "3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.11.0.tgz",
|
||||
"integrity": "sha512-KliWlkieHyEa65aQIkRwUFfHzT5Cn4u3BQQsu3KlkJOs7c1u7ryn84EWaOjEzilbKgttT4OfBURA8Uc4JBSQIw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15",
|
||||
"eslint-compat-utils": "^0.5.1",
|
||||
"@eslint-community/eslint-utils": "^4.6.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0",
|
||||
"esutils": "^2.0.3",
|
||||
"known-css-properties": "^0.35.0",
|
||||
"postcss": "^8.4.38",
|
||||
"globals": "^16.0.0",
|
||||
"known-css-properties": "^0.37.0",
|
||||
"postcss": "^8.4.49",
|
||||
"postcss-load-config": "^3.1.4",
|
||||
"postcss-safe-parser": "^6.0.0",
|
||||
"postcss-selector-parser": "^6.1.0",
|
||||
"semver": "^7.6.2",
|
||||
"svelte-eslint-parser": "^0.43.0"
|
||||
"postcss-safe-parser": "^7.0.0",
|
||||
"semver": "^7.6.3",
|
||||
"svelte-eslint-parser": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.17.0 || >=16.0.0"
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ota-meshi"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0",
|
||||
"eslint": "^8.57.1 || ^9.0.0",
|
||||
"svelte": "^3.37.0 || ^4.0.0 || ^5.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
@@ -5763,6 +5746,19 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-svelte/node_modules/globals": {
|
||||
"version": "16.3.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz",
|
||||
"integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-scope": {
|
||||
"version": "7.2.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
|
||||
@@ -6225,14 +6221,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
||||
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
@@ -7966,9 +7963,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/known-css-properties": {
|
||||
"version": "0.35.0",
|
||||
"resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz",
|
||||
"integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==",
|
||||
"version": "0.37.0",
|
||||
"resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz",
|
||||
"integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -9438,20 +9435,30 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-safe-parser": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz",
|
||||
"integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==",
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz",
|
||||
"integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/postcss-safe-parser"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
"node": ">=18.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"postcss": "^8.3.3"
|
||||
"postcss": "^8.4.31"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-scss": {
|
||||
@@ -9482,9 +9489,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-selector-parser": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
|
||||
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz",
|
||||
"integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -11469,20 +11476,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-eslint-parser": {
|
||||
"version": "0.43.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz",
|
||||
"integrity": "sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.3.0.tgz",
|
||||
"integrity": "sha512-VCgMHKV7UtOGcGLGNFSbmdm6kEKjtzo5nnpGU/mnx4OsFY6bZ7QwRF5DUx+Hokw5Lvdyo8dpk8B1m8mliomrNg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eslint-scope": "^7.2.2",
|
||||
"eslint-visitor-keys": "^3.4.3",
|
||||
"espree": "^9.6.1",
|
||||
"postcss": "^8.4.39",
|
||||
"postcss-scss": "^4.0.9"
|
||||
"eslint-scope": "^8.2.0",
|
||||
"eslint-visitor-keys": "^4.0.0",
|
||||
"espree": "^10.0.0",
|
||||
"postcss": "^8.4.49",
|
||||
"postcss-scss": "^4.0.9",
|
||||
"postcss-selector-parser": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ota-meshi"
|
||||
@@ -11496,6 +11504,54 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-eslint-parser/node_modules/eslint-scope": {
|
||||
"version": "8.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
|
||||
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^5.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-eslint-parser/node_modules/eslint-visitor-keys": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
|
||||
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-eslint-parser/node_modules/espree": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
|
||||
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"acorn": "^8.15.0",
|
||||
"acorn-jsx": "^5.3.2",
|
||||
"eslint-visitor-keys": "^4.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-infinite-loading": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-infinite-loading/-/svelte-infinite-loading-1.4.0.tgz",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "materialious",
|
||||
"version": "1.9.21",
|
||||
"version": "1.9.22",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
@@ -28,7 +28,7 @@
|
||||
"@vite-pwa/sveltekit": "^0.6.6",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.45.1",
|
||||
"eslint-plugin-svelte": "^3.11.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-svelte": "^3.2.7",
|
||||
@@ -70,4 +70,4 @@
|
||||
"svelte-persisted-store": "^0.12.0",
|
||||
"youtubei.js": "^15.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@ export interface VideoPlay extends Video {
|
||||
genre: string;
|
||||
genreUrl: string;
|
||||
hlsUrl?: string;
|
||||
dashUrl: string;
|
||||
dashUrl?: string;
|
||||
adaptiveFormats: AdaptiveFormats[];
|
||||
formatStreams: FormatStreams[];
|
||||
recommendedVideos: VideoBase[];
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
</script>
|
||||
|
||||
<div class="space"></div>
|
||||
|
||||
<div
|
||||
style="display: flex;align-items: center;flex-direction: column;text-align: center;padding: 90px;"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="200" viewBox="0 -960 960 960" width="200"
|
||||
><path
|
||||
d="M480-420q-68 0-123.5 38.5T276-280h408q-25-63-80.5-101.5T480-420Zm-168-60 44-42 42 42 42-42-42-42 42-44-42-42-42 42-44-42-42 42 42 44-42 42 42 42Zm250 0 42-42 44 42 42-42-42-42 42-44-42-42-44 42-42-42-42 42 42 44-42 42 42 42ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-400Zm0 320q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Z"
|
||||
/></svg
|
||||
>
|
||||
|
||||
{#if page.error}
|
||||
<article>
|
||||
<code style="white-space: pre-line;word-wrap: break-word;">{page.error.message}</code>
|
||||
</article>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -8,7 +8,7 @@
|
||||
import { ScreenOrientation, type ScreenOrientationResult } from '@capacitor/screen-orientation';
|
||||
import { StatusBar, Style } from '@capacitor/status-bar';
|
||||
import { NavigationBar } from '@hugotomazi/capacitor-navigation-bar';
|
||||
import { type Page } from '@sveltejs/kit';
|
||||
import { error, type Page } from '@sveltejs/kit';
|
||||
import { HttpFetchPlugin } from '$lib/sabr/shakaHttpPlugin';
|
||||
import ui from 'beercss';
|
||||
import ISO6391 from 'iso-639-1';
|
||||
@@ -385,7 +385,7 @@
|
||||
watchProgressTimeout = setInterval(() => savePlayerPos(), 60000);
|
||||
setupSponsorSkip();
|
||||
|
||||
let dashUrl: string = '';
|
||||
let dashUrl: string;
|
||||
|
||||
// Due to CORs issues with redirects, hosted instances of Materialious
|
||||
// dirctly provide the companion instance
|
||||
@@ -393,6 +393,10 @@
|
||||
if (import.meta.env.VITE_DEFAULT_COMPANION_INSTANCE && Capacitor.getPlatform() === 'web') {
|
||||
dashUrl = `${import.meta.env.VITE_DEFAULT_COMPANION_INSTANCE}/api/manifest/dash/id/${data.video.videoId}`;
|
||||
} else {
|
||||
if (!data.video.dashUrl) {
|
||||
error(500, 'No dash manifest found');
|
||||
return;
|
||||
}
|
||||
dashUrl = data.video.dashUrl;
|
||||
}
|
||||
|
||||
@@ -403,6 +407,10 @@
|
||||
await player.load(dashUrl, await getLastPlayPos());
|
||||
} else {
|
||||
if (data.video.fallbackPatch === 'youtubejs') {
|
||||
if (!data.video.dashUrl) {
|
||||
error(500, 'No dash manifest found');
|
||||
return;
|
||||
}
|
||||
await player.load(data.video.dashUrl);
|
||||
} else {
|
||||
await player.load(data.video.hlsUrl + '?local=true');
|
||||
@@ -590,22 +598,22 @@
|
||||
playerElement.playbackRate = playerElement.playbackRate + 0.25;
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
Mousetrap.bind(',', () => {
|
||||
if (!playerElement) return
|
||||
|
||||
const currentTrack = player.getVariantTracks().find(track => track.active)
|
||||
const frameTime = 1/(currentTrack?.frameRate || 30)
|
||||
playerElement.currentTime -= frameTime
|
||||
})
|
||||
if (!playerElement) return;
|
||||
|
||||
const currentTrack = player.getVariantTracks().find((track) => track.active);
|
||||
const frameTime = 1 / (currentTrack?.frameRate || 30);
|
||||
playerElement.currentTime -= frameTime;
|
||||
});
|
||||
|
||||
Mousetrap.bind('.', () => {
|
||||
if (!playerElement) return
|
||||
|
||||
const currentTrack = player.getVariantTracks().find(track => track.active)
|
||||
const frameTime = 1/(currentTrack?.frameRate || 30)
|
||||
playerElement.currentTime += frameTime
|
||||
})
|
||||
if (!playerElement) return;
|
||||
|
||||
const currentTrack = player.getVariantTracks().find((track) => track.active);
|
||||
const frameTime = 1 / (currentTrack?.frameRate || 30);
|
||||
playerElement.currentTime += frameTime;
|
||||
});
|
||||
|
||||
playerElement.addEventListener('pause', async () => {
|
||||
savePlayerPos();
|
||||
|
||||
@@ -270,6 +270,7 @@
|
||||
.video-title {
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.thumbnail-details {
|
||||
|
||||
@@ -7,6 +7,7 @@ export const locale: Writable<string> = writable(defaultLocale);
|
||||
export const _: Writable<(key: string, options?: any) => string> = writable(() => '');
|
||||
|
||||
const resources: Record<string, () => Promise<Record<string, any>>> = {
|
||||
ar: () => import('./locales/ar.json'),
|
||||
en: () => import('./locales/en.json'),
|
||||
ru: () => import('./locales/ru.json'),
|
||||
'zh-CN': () => import('./locales/zh-CN.json'),
|
||||
@@ -14,6 +15,7 @@ const resources: Record<string, () => Promise<Record<string, any>>> = {
|
||||
nl: () => import('./locales/nl.json'),
|
||||
de: () => import('./locales/de.json'),
|
||||
es: () => import('./locales/es.json'),
|
||||
gsw: () => import('./locales/gsw.json'),
|
||||
sh: () => import('./locales/sh.json'),
|
||||
'pt-BR': () => import('./locales/pt-BR.json'),
|
||||
lv: () => import('./locales/lv.json'),
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
"previewVideoOnHover": "Video-Vorschau beim Hovern",
|
||||
"expandDescription": "Beschreibung standardmäßig erweitern",
|
||||
"expandComments": "Kommentare standardmäßig erweitern",
|
||||
"disableAutoUpdate": "Automatische Installation von Updates deaktivieren",
|
||||
"disableAutoUpdate": "Automatische Updates deaktivieren",
|
||||
"dataPreferences": {
|
||||
"content": "Du möchtest Abonnements importieren/exportieren, dein Passwort ändern oder dein Konto löschen? Klicke hier und scrolle bis zum Ende der Seite.",
|
||||
"dataPreferences": "Dateneinstellungen"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"premium": "Premium YouTube content can't be watched on Materialious.",
|
||||
"isUpcoming": "Video is not in a watchable state yet.",
|
||||
"copyUrl": "Copy URL",
|
||||
"loadMore": "Load more",
|
||||
"views": "views",
|
||||
|
||||
@@ -85,7 +85,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"
|
||||
"expandDescription": "Beschriibig standardmässig erwiitere",
|
||||
"disableAutoUpdate": "Automatischi Updates deaktiviere"
|
||||
},
|
||||
"videos": "Videos",
|
||||
"cancel": "Abbreche",
|
||||
|
||||
@@ -7,7 +7,6 @@ import type {
|
||||
VideoBase,
|
||||
VideoPlay
|
||||
} from '$lib/api/model';
|
||||
import { numberWithCommas } from '$lib/numbers';
|
||||
import { fromFormat } from '$lib/sabr/formatKeyUtils';
|
||||
import { interfaceRegionStore, poTokenCacheStore } from '$lib/store';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
@@ -77,8 +76,6 @@ export async function patchYoutubeJs(videoId: string): Promise<VideoPlay> {
|
||||
throw new Error('Unable to pull video info from youtube.js');
|
||||
}
|
||||
|
||||
console.log(video);
|
||||
|
||||
let dashUri: string | undefined;
|
||||
|
||||
if (video.streaming_data) {
|
||||
@@ -103,8 +100,6 @@ export async function patchYoutubeJs(videoId: string): Promise<VideoPlay> {
|
||||
}
|
||||
}
|
||||
|
||||
if (!dashUri) throw Error('Unable to find suitable dash manifest');
|
||||
|
||||
const descString = video.secondary_info.description?.toString() || '';
|
||||
|
||||
let authorThumbnails: Image[];
|
||||
@@ -206,9 +201,10 @@ export async function patchYoutubeJs(videoId: string): Promise<VideoPlay> {
|
||||
premiereTimestamp: 0,
|
||||
hlsUrl: video.streaming_data?.hls_manifest_url || undefined,
|
||||
liveNow: video.basic_info.is_live || false,
|
||||
premium: false,
|
||||
// @ts-expect-error Type does have offer_id
|
||||
premium: video?.playability_status?.error_screen?.offer_id === 'sponsors_only_video',
|
||||
storyboards: storyboard,
|
||||
isUpcoming: false,
|
||||
isUpcoming: video?.playability_status?.status !== 'OK',
|
||||
videoId: videoId,
|
||||
videoThumbnails: video.basic_info.thumbnail as Thumbnail[],
|
||||
author: video.basic_info.author || 'Unknown',
|
||||
|
||||
@@ -67,7 +67,7 @@ export const returnYTDislikesInstanceStore: Writable<string | null | undefined>
|
||||
)
|
||||
);
|
||||
|
||||
export const synciousStore = persisted('syncious', true);
|
||||
export const synciousStore = persisted('syncious', false);
|
||||
export const synciousInstanceStore: Writable<string | null | undefined> = persisted(
|
||||
'synciousInstance',
|
||||
platformDependentDefault(
|
||||
@@ -92,7 +92,7 @@ export const interfaceDisplayThumbnailAvatars = persisted('disableThumbnailAvata
|
||||
export const interfaceDefaultPage = persisted('defaultPage', '/');
|
||||
export const interfaceSearchHistoryEnabled = persisted('searchHistoryEnabled', false);
|
||||
export const interfaceAllowInsecureRequests = persisted('allowInsecureRequests', false);
|
||||
export const interfaceDisableAutoUpdate = persisted('disableAutoUpdate', false)
|
||||
export const interfaceDisableAutoUpdate = persisted('disableAutoUpdate', false);
|
||||
|
||||
export const sponsorBlockStore = persisted('sponsorBlock', true);
|
||||
export const sponsorBlockUrlStore: Writable<string | null | undefined> = persisted(
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
import { phaseDescription } from '$lib/timestamps';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { get } from 'svelte/store';
|
||||
import { _ } from './i18n';
|
||||
|
||||
export async function getWatchDetails(videoId: string, url: URL) {
|
||||
let video;
|
||||
@@ -25,6 +26,14 @@ export async function getWatchDetails(videoId: string, url: URL) {
|
||||
error(500, errorMessage);
|
||||
}
|
||||
|
||||
if (video.premium) {
|
||||
error(400, get(_)('premium'));
|
||||
}
|
||||
|
||||
if (video.isUpcoming) {
|
||||
error(400, get(_)('isUpcoming'));
|
||||
}
|
||||
|
||||
let personalPlaylists;
|
||||
if (get(authStore)) {
|
||||
postHistory(video.videoId);
|
||||
|
||||
@@ -1,29 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import ErrorMsg from '$lib/components/ErrorMsg.svelte';
|
||||
</script>
|
||||
|
||||
<div class="space"></div>
|
||||
|
||||
<div
|
||||
style="display: flex;align-items: center;flex-direction: column;text-align: center;padding: 90px;"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="200" viewBox="0 -960 960 960" width="200"
|
||||
><path
|
||||
d="M480-420q-68 0-123.5 38.5T276-280h408q-25-63-80.5-101.5T480-420Zm-168-60 44-42 42 42 42-42-42-42 42-44-42-42-42 42-44-42-42 42 42 44-42 42 42 42Zm250 0 42-42 44 42 42-42-42-42 42-44-42-42-44 42-42-42-42 42 42 44-42 42 42 42ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-400Zm0 320q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Z"
|
||||
/></svg
|
||||
>
|
||||
<h2>Oh no! You've encountered an error.</h2>
|
||||
|
||||
<a
|
||||
href="https://github.com/WardPearce/Materialious/issues/new"
|
||||
class="link"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"><h3>Report it here</h3></a
|
||||
>
|
||||
|
||||
{#if $page.error}
|
||||
<article>
|
||||
<code style="white-space: pre-line;word-wrap: break-word;">{$page.error.message}</code>
|
||||
</article>
|
||||
{/if}
|
||||
</div>
|
||||
<ErrorMsg />
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<script lang="ts">
|
||||
import ErrorMsg from '$lib/components/ErrorMsg.svelte';
|
||||
</script>
|
||||
|
||||
<ErrorMsg />
|
||||
@@ -0,0 +1,5 @@
|
||||
<script lang="ts">
|
||||
import ErrorMsg from '$lib/components/ErrorMsg.svelte';
|
||||
</script>
|
||||
|
||||
<ErrorMsg />
|
||||
+1
-1
@@ -3,7 +3,7 @@ import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
LATEST_VERSION = "1.9.21"
|
||||
LATEST_VERSION = "1.9.22"
|
||||
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