diff --git a/src/renderer/components/view.component.ts b/src/renderer/components/view.component.ts index 12ba551812..16ad341a3c 100644 --- a/src/renderer/components/view.component.ts +++ b/src/renderer/components/view.component.ts @@ -1,29 +1,20 @@ import { Component, ChangeDetectionStrategy, ChangeDetectorRef, OnDestroy, ElementRef, Renderer2, RendererStyleFlags2 } from '@angular/core'; import { clipboard } from 'electron'; -import { ActivatedRoute, Router, RouterLinkActive } from '@angular/router'; -import { FormBuilder, FormArray, FormGroup, FormControl } from '@angular/forms'; -import { PreviewService, LoggerService, ParsersService } from '../services'; -import { Subscription } from "rxjs"; -import { APP } from '../../variables'; +import { ActivatedRoute, Router } from '@angular/router'; +import { LoggerService } from '../services'; import { - VDF_Manager, - VDF_Error, - CategoryManager, ControllerManager, - Acceptable_Error } from "../../lib"; -import { controllerNames, controllerTypes, enableDisplayNames } from '../../lib/controller-manager'; -import {artworkTypes, artworkIdDict, artworkDimsDict, artworkSingDict} from '../../lib/artwork-types'; -import { UserData, VDF_ListItem, VDF_ListData, VDF_ShortcutsItem, SteamInputEnabled } from "../../models"; +import { controllerTypes, enableDisplayNames } from '../../lib/controller-manager'; +import {artworkTypes, artworkIdDict, artworkSingDict} from '../../lib/artwork-types'; +import { VDF_ShortcutsItem, SteamInputEnabled } from "../../models"; import { generateShortAppId } from '../../lib/helpers/steam'; import path from "path"; -import fs from "fs-extra"; import _ from "lodash"; import * as url from '../../lib/helpers/url'; import { glob } from 'glob'; import { exec } from "child_process"; -import { steam } from '../../systems-logos'; -import { title } from 'process'; +import { ViewService } from '../services/view.service'; @Component({ @@ -33,11 +24,8 @@ import { title } from 'process'; changeDetection: ChangeDetectionStrategy.OnPush }) -export class ViewComponent implements OnDestroy { - private subscriptions: Subscription = new Subscription(); - private vdfData: VDF_ListData; - private controllerData: UserData; - private categoryData: UserData; +export class ViewComponent { + private currentShortcut: VDF_ShortcutsItem; private currentCats: string; private currentLaunch: string; @@ -50,49 +38,23 @@ export class ViewComponent implements OnDestroy { private router: Router, private activatedRoute: ActivatedRoute, private loggerService: LoggerService, - private parsersService: ParsersService, + private viewService: ViewService, private renderer: Renderer2, private elementRef: ElementRef, private changeDetectionRef: ChangeDetectorRef ) { - - } - private get lang() { - // return APP.lang.view.component; - return {}; + this.refreshGames(false); } - async refreshGames() { - this.loggerService.info('Reading Shortcuts, Categories, and Controllers', {invokeAlert: true, alertTimeout: 3000}) - this.currentShortcut = null; - this.renderer.setStyle(this.elementRef.nativeElement, '--view-details-width', '0%', RendererStyleFlags2.DashCase); - let knownSteamDirectories = this.parsersService.getKnownSteamDirectories(); - const vdfManager = new VDF_Manager(); - await vdfManager.prepare(knownSteamDirectories); - await vdfManager.read({ addedItems: false }); - const vdfData = vdfManager.vdfData; - const categoryManager = new CategoryManager(); - let categoryData: {[steamDirectory:string]: {[userId:string]: any}} = {}; - const controllerManager = new ControllerManager(); - let controllerData: {[steamDirectory: string]: {[userId: string]: any}} = {}; - for(const steamDirectory in vdfData) { - categoryData[steamDirectory] = {}; - controllerData[steamDirectory] = {}; - for(const userId in vdfData[steamDirectory]) { - try { - categoryData[steamDirectory][userId] = await categoryManager.readCategories(steamDirectory, userId); - } catch (e) {} - const configsetDir = ControllerManager.configsetDir(steamDirectory, userId); - const localConfigPath = ControllerManager.localConfigPath(steamDirectory, userId); - controllerData[steamDirectory][userId] = { - configsets: controllerManager.readControllers(configsetDir), - localConfig: controllerManager.readLocalConfig(localConfigPath), - } - } + async refreshGames(force?: boolean) { + if(force) { + this.loggerService.info('Reading Shortcuts, Categories, and Controllers', {invokeAlert: true, alertTimeout: 3000}) + } + if(!this.viewService.vdfData || force) { + this.renderer.setStyle(this.elementRef.nativeElement, '--view-details-width', '0%', RendererStyleFlags2.DashCase); + this.currentShortcut = null; + await this.viewService.refreshGames(); } - this.vdfData = vdfData; - this.controllerData = controllerData; - this.categoryData = categoryData; this.changeDetectionRef.detectChanges(); } @@ -103,22 +65,21 @@ export class ViewComponent implements OnDestroy { private async setCurrentShortcut(steamDir: string, steamUser: string, shortcut: VDF_ShortcutsItem) { this.currentShortcut = shortcut; this.renderer.setStyle(this.elementRef.nativeElement, '--view-details-width', '50%', RendererStyleFlags2.DashCase); - const gridDir = this.vdfData[steamDir][steamUser].screenshots.gridDir; + const gridDir = this.viewService.vdfData[steamDir][steamUser].screenshots.gridDir; const shortAppId = generateShortAppId(shortcut.exe, shortcut.appname); for(let artworkType of artworkTypes) { const files = await glob(`${shortAppId}${artworkIdDict[artworkType]}.*`, { dot: true, cwd: gridDir, absolute: true }); this.currentArtwork[artworkType] = files.length ? url.encodeFile(files[0]) : require('../../assets/images/no-images.svg'); } - this.currentArtwork = _.clone(this.currentArtwork) this.currentCats = this.currentShortcut.tags.join(" ") this.currentLaunch = this.currentShortcut.LaunchOptions ? `${this.currentShortcut.exe} ${this.currentShortcut.LaunchOptions}` : this.currentShortcut.exe; this.currentControllers = {}; for(let controllerType of controllerTypes) { - const configset = this.controllerData[steamDir][steamUser].configsets[controllerType] + const configset = this.viewService.controllerData[steamDir][steamUser].configsets[controllerType] if(configset) { const appController = configset.controller_config[ControllerManager.transformTitle(this.currentShortcut.appname)]; if(appController && (appController.template || appController.workshop)) { - const templates = await ControllerManager.readTemplates(steamDir, controllerType); + const templates = this.viewService.controllerTemplateData[steamDir][controllerType]; const mappingId = appController.template || appController.workshop; const appTemplates = Object.values(templates).filter(x=>x.mappingId==mappingId); if(appTemplates.length && appTemplates[0].title) { @@ -130,7 +91,7 @@ export class ViewComponent implements OnDestroy { } } } - let enabled: SteamInputEnabled = (this.controllerData[steamDir][steamUser].localConfig.UserLocalConfigStore.apps[this.currentShortcut.appid]||{}).UseSteamControllerConfig||"1"; + let enabled: SteamInputEnabled = (this.viewService.controllerData[steamDir][steamUser].localConfig.UserLocalConfigStore.apps[this.currentShortcut.appid]||{}).UseSteamControllerConfig||"1"; this.currentControllerEnabled = enableDisplayNames[enabled]; this.changeDetectionRef.detectChanges() } @@ -143,12 +104,4 @@ export class ViewComponent implements OnDestroy { private launchTitle() { exec(this.currentLaunch, {cwd: this.currentShortcut.StartDir}) } - - ngAfterViewInit() { - this.refreshGames(); - } - - ngOnDestroy () { - this.subscriptions.unsubscribe() - } } diff --git a/src/renderer/services/index.ts b/src/renderer/services/index.ts index 611fa47f02..4ec43ddfe4 100644 --- a/src/renderer/services/index.ts +++ b/src/renderer/services/index.ts @@ -11,3 +11,4 @@ export * from './config-presets.service'; export * from './shell-scripts.service'; export * from './user-exceptions.service'; export * from './ipc.service'; +export * from './view.service'; \ No newline at end of file diff --git a/src/renderer/services/view.service.ts b/src/renderer/services/view.service.ts new file mode 100644 index 0000000000..c6e5787da7 --- /dev/null +++ b/src/renderer/services/view.service.ts @@ -0,0 +1,68 @@ +import { Injectable } from '@angular/core'; +import { LoggerService, ParsersService } from '../services'; +import { VDF_ListData, UserData, ControllerTemplates } from '../../models'; +import * as _ from "lodash"; +import { + VDF_Manager, + CategoryManager, + ControllerManager, +} from "../../lib"; +import { controllerTypes } from '../../lib/controller-manager'; +import { BehaviorSubject } from 'rxjs'; + + +@Injectable() +export class ViewService { + vdfData: VDF_ListData; + controllerData: UserData; + categoryData: UserData; + controllerTemplateData: ControllerTemplates; + status: {[k: string]: BehaviorSubject} = { + refreshingShortcuts: new BehaviorSubject(false), + refreshingDetails: new BehaviorSubject(false) + } + constructor( + private parsersService: ParsersService) { + } + + private clearData() { + this.vdfData = null; + this.categoryData = {}; + this.controllerData = {}; + this.controllerTemplateData = {}; + } + + async refreshGames(force?: boolean) { + this.clearData(); + this.status.refreshingShortcuts.next(true); + this.status.refreshingDetails.next(true); + let knownSteamDirectories = this.parsersService.getKnownSteamDirectories(); + const vdfManager = new VDF_Manager(); + const categoryManager = new CategoryManager(); + const controllerManager = new ControllerManager(); + await vdfManager.prepare(knownSteamDirectories); + await vdfManager.read({ addedItems: false }); + this.vdfData = vdfManager.vdfData; + this.status.refreshingShortcuts.next(false); + for(const steamDirectory in this.vdfData) { + this.categoryData[steamDirectory] = {}; + this.controllerData[steamDirectory] = {}; + this.controllerTemplateData[steamDirectory] = {}; + for(const userId in this.vdfData[steamDirectory]) { + try { + this.categoryData[steamDirectory][userId] = await categoryManager.readCategories(steamDirectory, userId); + } catch (e) {} + const configsetDir = ControllerManager.configsetDir(steamDirectory, userId); + const localConfigPath = ControllerManager.localConfigPath(steamDirectory, userId); + this.controllerData[steamDirectory][userId] = { + configsets: controllerManager.readControllers(configsetDir), + localConfig: controllerManager.readLocalConfig(localConfigPath), + } + } + for(const controllerType of controllerTypes) { + this.controllerTemplateData[steamDirectory][controllerType] = await ControllerManager.readTemplates(steamDirectory, controllerType) + } + } + this.status.refreshingDetails.next(false); + } +} diff --git a/src/renderer/styles/preview.component.scss b/src/renderer/styles/preview.component.scss index 8aaa5bed63..b1b73c6dde 100644 --- a/src/renderer/styles/preview.component.scss +++ b/src/renderer/styles/preview.component.scss @@ -51,6 +51,11 @@ border-radius: 50%; } } + @keyframes loadingSpinner { + to { + transform: rotate(360deg); + } + } .preview-description { height: 100%; grid-area: entries; @@ -234,11 +239,7 @@ "detailsList"; grid-template-rows: auto 1fr; overflow-y: auto; - @keyframes loadingSpinner { - to { - transform: rotate(360deg); - } - } + .detailsOptions { padding: 1em 1em 0.5em 1em; grid-area: detailsOptions; diff --git a/src/renderer/styles/view.component.scss b/src/renderer/styles/view.component.scss index 713353b39b..d2e6b2c7d1 100644 --- a/src/renderer/styles/view.component.scss +++ b/src/renderer/styles/view.component.scss @@ -14,7 +14,29 @@ grid-template-columns: auto var(--view-details-width); grid-template-rows: auto 1fr auto; - + .loadingSpinner { + &:before { + display: block; + justify-content: center; + width: 5em; + height: 5em; + margin-top: 40vh; + margin-left: calc(0.45 * (100vw - var(--nav-width))); + + content: ""; + animation: loadingSpinner 0.6s linear infinite; + + border-top: 0.325em solid transparent; + border-top-color: var(--color-app-loading-spinner); + border-right: 0.325em solid transparent; + border-radius: 50%; + } + } + @keyframes loadingSpinner { + to { + transform: rotate(360deg); + } + } .upperMenu { grid-area: upperMenu; @@ -132,6 +154,11 @@ background-color: var(--color-nested-form-background); color: var(--color-settings-text); overflow: auto; + .loadingSpinner { + &:before { + margin-left: calc(0.2 * (100vw - var(--nav-width))); + } + } .launch { @include button(); @include clickButtonColor(click-button); diff --git a/src/renderer/templates/view.component.html b/src/renderer/templates/view.component.html index 07a3f353ac..5556f7c550 100644 --- a/src/renderer/templates/view.component.html +++ b/src/renderer/templates/view.component.html @@ -3,21 +3,22 @@ -
- +
+
+
{{steamDir}}
- +
{{steamUser}}
- +
@@ -31,78 +32,80 @@
- -
-
LAUNCH TITLE
-
- -
-
-
- FULL SHORTCUT +
+ +
+
LAUNCH TITLE
+
+
-
- {{currentLaunch}} +
+
+ FULL SHORTCUT +
+
+ {{currentLaunch}} +
-
-
-
- START DIRECTORY +
+
+ START DIRECTORY +
+
+ {{currentShortcut.StartDir}} +
-
- {{currentShortcut.StartDir}} +
+
+ CATEGORIES +
+
+ {{currentCats}} +
-
-
- CATEGORIES -
-
- {{currentCats}} -
+
+
-
-
- -
-
- -
-
- {{artworkSingDict[artworkType].toUpperCase()}} +
+ +
+
+ {{artworkSingDict[artworkType].toUpperCase()}} +
+
- -
- -
-
- -
-
-
-
- ENABLE STEAM INPUT -
-
- {{currentControllerEnabled}} -
+
-
-
- {{controllerType.toUpperCase()}} -
-
- {{currentControllers[controllerType].title}} +
+ +
+
+
+
+ ENABLE STEAM INPUT +
+
+ {{currentControllerEnabled}} +
-
- {{currentControllers[controllerType].templatePath}} +
+
+ {{controllerType.toUpperCase()}} +
+
+ {{currentControllers[controllerType].title}} +
+
+ {{currentControllers[controllerType].templatePath}} +
-
+