mirror of
https://github.com/Myxelium/Bridge-Multi.git
synced 2026-07-07 18:45:09 +00:00
Download video backgrounds setting; improved settings loading
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
<div style="display: flex; flex-direction: column; height: 100%;">
|
<div *ngIf="settingsLoaded" style="display: flex; flex-direction: column; height: 100%;">
|
||||||
<app-toolbar></app-toolbar>
|
<app-toolbar></app-toolbar>
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</div>
|
</div>
|
||||||
@@ -8,5 +8,10 @@ import { SettingsService } from './core/services/settings.service'
|
|||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
|
|
||||||
constructor(private settingsService: SettingsService) { }
|
settingsLoaded = false
|
||||||
|
|
||||||
|
constructor(private settingsService: SettingsService) {
|
||||||
|
// Ensure settings are loaded before rendering the application
|
||||||
|
settingsService.loadSettings().then(() => this.settingsLoaded = true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,12 @@
|
|||||||
|
|
||||||
<h3 class="ui header">Downloads</h3>
|
<h3 class="ui header">Downloads</h3>
|
||||||
<div class="ui form">
|
<div class="ui form">
|
||||||
|
<div class="field">
|
||||||
|
<div appCheckbox #videoCheckbox class="ui checkbox" (checked)="downloadVideos($event)">
|
||||||
|
<input type="checkbox">
|
||||||
|
<label>Download video backgrounds</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div *ngIf="loginAvailable" class="field">
|
<div *ngIf="loginAvailable" class="field">
|
||||||
<label>Google rate limit delay</label>
|
<label>Google rate limit delay</label>
|
||||||
<div id="rateLimitInput" class="ui right labeled input">
|
<div id="rateLimitInput" class="ui right labeled input">
|
||||||
@@ -28,7 +34,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- TODO: Uncomment this when switching to the OAuth2 Login system -->
|
|
||||||
<div *ngIf="loginAvailable" class="field">
|
<div *ngIf="loginAvailable" class="field">
|
||||||
<div class="ui button" data-tooltip="Removes rate limit delay" data-position="right center" (click)="googleLogin()">
|
<div class="ui button" data-tooltip="Removes rate limit delay" data-position="right center" (click)="googleLogin()">
|
||||||
<i class="google icon"></i>Sign in with Google
|
<i class="google icon"></i>Sign in with Google
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Component, OnInit, AfterViewInit, ChangeDetectorRef, ViewChild, ElementRef } from '@angular/core'
|
import { Component, OnInit, AfterViewInit, ChangeDetectorRef, ViewChild, ElementRef } from '@angular/core'
|
||||||
|
import { CheckboxDirective } from 'src/app/core/directives/checkbox.directive'
|
||||||
import { ElectronService } from 'src/app/core/services/electron.service'
|
import { ElectronService } from 'src/app/core/services/electron.service'
|
||||||
import { SettingsService } from 'src/app/core/services/settings.service'
|
import { SettingsService } from 'src/app/core/services/settings.service'
|
||||||
|
|
||||||
@@ -9,6 +10,7 @@ import { SettingsService } from 'src/app/core/services/settings.service'
|
|||||||
})
|
})
|
||||||
export class SettingsComponent implements OnInit, AfterViewInit {
|
export class SettingsComponent implements OnInit, AfterViewInit {
|
||||||
@ViewChild('themeDropdown', { static: true }) themeDropdown: ElementRef
|
@ViewChild('themeDropdown', { static: true }) themeDropdown: ElementRef
|
||||||
|
@ViewChild(CheckboxDirective, { static: true }) videoCheckbox: CheckboxDirective
|
||||||
|
|
||||||
cacheSize = 'Calculating...'
|
cacheSize = 'Calculating...'
|
||||||
updateAvailable = false
|
updateAvailable = false
|
||||||
@@ -21,7 +23,11 @@ export class SettingsComponent implements OnInit, AfterViewInit {
|
|||||||
updateRetrying = false
|
updateRetrying = false
|
||||||
currentVersion = ''
|
currentVersion = ''
|
||||||
|
|
||||||
constructor(public settingsService: SettingsService, private electronService: ElectronService, private ref: ChangeDetectorRef) { }
|
constructor(
|
||||||
|
public settingsService: SettingsService,
|
||||||
|
private electronService: ElectronService,
|
||||||
|
private ref: ChangeDetectorRef
|
||||||
|
) { }
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.electronService.receiveIPC('update-available', (result) => {
|
this.electronService.receiveIPC('update-available', (result) => {
|
||||||
@@ -61,6 +67,8 @@ export class SettingsComponent implements OnInit, AfterViewInit {
|
|||||||
this.settingsService.theme = text
|
this.settingsService.theme = text
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.videoCheckbox.check(this.settingsService.downloadVideos)
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearCache() {
|
async clearCache() {
|
||||||
@@ -69,6 +77,10 @@ export class SettingsComponent implements OnInit, AfterViewInit {
|
|||||||
this.cacheSize = 'Cleared!'
|
this.cacheSize = 'Cleared!'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async downloadVideos(isChecked: boolean) {
|
||||||
|
this.settingsService.downloadVideos = isChecked
|
||||||
|
}
|
||||||
|
|
||||||
async getLibraryDirectory() {
|
async getLibraryDirectory() {
|
||||||
const result = await this.electronService.showOpenDialog({
|
const result = await this.electronService.showOpenDialog({
|
||||||
title: 'Choose library folder',
|
title: 'Choose library folder',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { ElectronService } from './electron.service'
|
import { ElectronService } from './electron.service'
|
||||||
import { Settings, defaultSettings } from 'src/electron/shared/Settings'
|
import { Settings } from 'src/electron/shared/Settings'
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -11,26 +11,18 @@ export class SettingsService {
|
|||||||
private settings: Settings
|
private settings: Settings
|
||||||
private currentThemeLink: HTMLLinkElement
|
private currentThemeLink: HTMLLinkElement
|
||||||
|
|
||||||
constructor(private electronService: ElectronService) {
|
constructor(private electronService: ElectronService) { }
|
||||||
this.getSettings().then(() => {
|
|
||||||
|
async loadSettings() {
|
||||||
|
this.settings = await this.electronService.invoke('get-settings', undefined)
|
||||||
if (this.settings.theme != this.builtinThemes[0]) {
|
if (this.settings.theme != this.builtinThemes[0]) {
|
||||||
this.changeTheme(this.settings.theme)
|
this.changeTheme(this.settings.theme)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async getSettings() {
|
|
||||||
if (this.settings == undefined) {
|
|
||||||
this.settings = await this.electronService.invoke('get-settings', undefined)
|
|
||||||
}
|
|
||||||
return this.settings
|
|
||||||
}
|
}
|
||||||
|
|
||||||
saveSettings() {
|
saveSettings() {
|
||||||
if (this.settings != undefined) {
|
|
||||||
this.electronService.sendIPC('set-settings', this.settings)
|
this.electronService.sendIPC('set-settings', this.settings)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
changeTheme(theme: string) {
|
changeTheme(theme: string) {
|
||||||
if (this.currentThemeLink != undefined) this.currentThemeLink.remove()
|
if (this.currentThemeLink != undefined) this.currentThemeLink.remove()
|
||||||
@@ -55,15 +47,23 @@ export class SettingsService {
|
|||||||
|
|
||||||
// Individual getters/setters
|
// Individual getters/setters
|
||||||
get libraryDirectory() {
|
get libraryDirectory() {
|
||||||
return this.settings == undefined ? defaultSettings.libraryPath : this.settings.libraryPath
|
return this.settings.libraryPath
|
||||||
}
|
}
|
||||||
set libraryDirectory(newValue: string) {
|
set libraryDirectory(newValue: string) {
|
||||||
this.settings.libraryPath = newValue
|
this.settings.libraryPath = newValue
|
||||||
this.saveSettings()
|
this.saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get downloadVideos() {
|
||||||
|
return this.settings.downloadVideos
|
||||||
|
}
|
||||||
|
set downloadVideos(isChecked) {
|
||||||
|
this.settings.downloadVideos = isChecked
|
||||||
|
this.saveSettings()
|
||||||
|
}
|
||||||
|
|
||||||
get theme() {
|
get theme() {
|
||||||
return this.settings == undefined ? defaultSettings.theme : this.settings.theme
|
return this.settings.theme
|
||||||
}
|
}
|
||||||
set theme(newValue: string) {
|
set theme(newValue: string) {
|
||||||
this.settings.theme = newValue
|
this.settings.theme = newValue
|
||||||
@@ -72,7 +72,7 @@ export class SettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get rateLimitDelay() {
|
get rateLimitDelay() {
|
||||||
return this.settings == undefined ? defaultSettings.rateLimitDelay : this.settings.rateLimitDelay
|
return this.settings.rateLimitDelay
|
||||||
}
|
}
|
||||||
set rateLimitDelay(delay: number) {
|
set rateLimitDelay(delay: number) {
|
||||||
this.settings.rateLimitDelay = delay
|
this.settings.rateLimitDelay = delay
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ class GetSettingsHandler implements IPCInvokeHandler<'get-settings'> {
|
|||||||
// Read/create settings
|
// Read/create settings
|
||||||
if (await exists(settingsPath)) {
|
if (await exists(settingsPath)) {
|
||||||
settings = JSON.parse(await readFile(settingsPath, 'utf8'))
|
settings = JSON.parse(await readFile(settingsPath, 'utf8'))
|
||||||
|
settings = Object.assign(JSON.parse(JSON.stringify(defaultSettings)), settings)
|
||||||
} else {
|
} else {
|
||||||
await SetSettingsHandler.saveSettings(defaultSettings)
|
await SetSettingsHandler.saveSettings(defaultSettings)
|
||||||
settings = defaultSettings
|
settings = defaultSettings
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import { DriveFile } from 'src/electron/shared/interfaces/songDetails.interface'
|
|||||||
import { FileTransfer } from './FileTransfer'
|
import { FileTransfer } from './FileTransfer'
|
||||||
import * as _rimraf from 'rimraf'
|
import * as _rimraf from 'rimraf'
|
||||||
import { FilesystemChecker } from './FilesystemChecker'
|
import { FilesystemChecker } from './FilesystemChecker'
|
||||||
|
import { getSettings } from '../SettingsHandler.ipc'
|
||||||
|
import { hasVideoExtension } from '../../shared/ElectronUtilFunctions'
|
||||||
|
|
||||||
const rimraf = promisify(_rimraf)
|
const rimraf = promisify(_rimraf)
|
||||||
|
|
||||||
@@ -45,7 +47,7 @@ export class ChartDownload {
|
|||||||
|
|
||||||
constructor(public versionID: number, private data: NewDownload) {
|
constructor(public versionID: number, private data: NewDownload) {
|
||||||
this.updateGUI('', 'Waiting for other downloads to finish...', 'good')
|
this.updateGUI('', 'Waiting for other downloads to finish...', 'good')
|
||||||
this.files = data.driveData.files
|
this.files = this.filterDownloadFiles(data.driveData.files)
|
||||||
this.individualFileProgressPortion = 80 / this.files.length
|
this.individualFileProgressPortion = 80 / this.files.length
|
||||||
if (data.driveData.inChartPack) {
|
if (data.driveData.inChartPack) {
|
||||||
this.destinationFolderName = sanitizeFilename(parse(data.driveData.files[0].name).name)
|
this.destinationFolderName = sanitizeFilename(parse(data.driveData.files[0].name).name)
|
||||||
@@ -61,6 +63,12 @@ export class ChartDownload {
|
|||||||
this.callbacks[event] = callback
|
this.callbacks[event] = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filterDownloadFiles(files: DriveFile[]) {
|
||||||
|
return files.filter(file => {
|
||||||
|
return (file.name != 'ch.dat') && (getSettings().downloadVideos || !hasVideoExtension(file.name))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retries the last failed step if it is running.
|
* Retries the last failed step if it is running.
|
||||||
*/
|
*/
|
||||||
@@ -135,7 +143,6 @@ export class ChartDownload {
|
|||||||
|
|
||||||
// DOWNLOAD FILES
|
// DOWNLOAD FILES
|
||||||
for (let i = 0; i < this.files.length; i++) {
|
for (let i = 0; i < this.files.length; i++) {
|
||||||
if (this.files[i].name == 'ch.dat') { continue }
|
|
||||||
let wasCanceled = false
|
let wasCanceled = false
|
||||||
this.cancelFn = () => { wasCanceled = true }
|
this.cancelFn = () => { wasCanceled = true }
|
||||||
const downloader = await getDownloader(this.files[i].webContentLink, join(this.tempPath, this.files[i].name))
|
const downloader = await getDownloader(this.files[i].webContentLink, join(this.tempPath, this.files[i].name))
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { basename } from 'path'
|
import { basename, parse } from 'path'
|
||||||
import { getSettingsHandler } from '../ipc/SettingsHandler.ipc'
|
import { getSettingsHandler } from '../ipc/SettingsHandler.ipc'
|
||||||
import { emitIPCEvent } from '../main'
|
import { emitIPCEvent } from '../main'
|
||||||
|
import { lower } from './UtilFunctions'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns The relative filepath from the library folder to `absoluteFilepath`.
|
* @returns The relative filepath from the library folder to `absoluteFilepath`.
|
||||||
@@ -10,6 +11,13 @@ export function getRelativeFilepath(absoluteFilepath: string) {
|
|||||||
return basename(settings.libraryPath) + absoluteFilepath.substring(settings.libraryPath.length)
|
return basename(settings.libraryPath) + absoluteFilepath.substring(settings.libraryPath.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns `true` if `name` has a valid video file extension.
|
||||||
|
*/
|
||||||
|
export function hasVideoExtension(name: string) {
|
||||||
|
return (['.mp4', '.avi', '.webm', '.ogv', '.mpeg'].includes(parse(lower(name)).ext))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log a message in the main BrowserWindow's console.
|
* Log a message in the main BrowserWindow's console.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
export interface Settings {
|
export interface Settings {
|
||||||
rateLimitDelay: number // Number of seconds to wait between each file download from Google servers
|
rateLimitDelay: number // Number of seconds to wait between each file download from Google servers
|
||||||
|
downloadVideos: boolean // If background videos should be downloaded
|
||||||
theme: string // The name of the currently enabled UI theme
|
theme: string // The name of the currently enabled UI theme
|
||||||
libraryPath: string // The path to the user's library
|
libraryPath: string // The path to the user's library
|
||||||
}
|
}
|
||||||
@@ -12,6 +13,7 @@ export interface Settings {
|
|||||||
*/
|
*/
|
||||||
export const defaultSettings: Settings = {
|
export const defaultSettings: Settings = {
|
||||||
rateLimitDelay: 31,
|
rateLimitDelay: 31,
|
||||||
|
downloadVideos: true,
|
||||||
theme: 'Default',
|
theme: 'Default',
|
||||||
libraryPath: undefined
|
libraryPath: undefined
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,13 @@ export function sanitizeFilename(filename: string): string {
|
|||||||
return (newFilename == '' ? randomBytes(5).toString('hex') : newFilename)
|
return (newFilename == '' ? randomBytes(5).toString('hex') : newFilename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns `text` converted to lower case.
|
||||||
|
*/
|
||||||
|
export function lower(text: string) {
|
||||||
|
return text.toLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts `val` from the range (`fromStart`, `fromEnd`) to the range (`toStart`, `toEnd`).
|
* Converts `val` from the range (`fromStart`, `fromEnd`) to the range (`toStart`, `toEnd`).
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user