From 9f9d944e7da5905cdc6e1ab0bc5c110e50a21cda Mon Sep 17 00:00:00 2001
From: cbartondock <cbartondock@gmail.com>
Date: Fri, 12 Nov 2021 20:26:53 -0500
Subject: [PATCH] Working select and deselect all

---
 src/lang/english/markdown/steam-parser.md     |  3 ++
 src/lib/parsers/steam.parser.ts               |  1 -
 .../components/nav-expand.component.ts        | 54 ++++++++++---------
 src/renderer/components/nav.component.ts      | 42 +++++++--------
 .../components/user-exceptions.component.ts   |  3 --
 src/renderer/services/parsers.service.ts      | 18 +++++--
 src/renderer/styles/nav-expand.component.scss |  3 +-
 src/renderer/styles/nav-link.component.scss   |  4 +-
 src/renderer/styles/nav.component.scss        | 48 ++++++++++++-----
 src/renderer/templates/nav.component.html     | 43 ++++++---------
 10 files changed, 122 insertions(+), 97 deletions(-)

diff --git a/src/lang/english/markdown/steam-parser.md b/src/lang/english/markdown/steam-parser.md
index 8a53c395ab..9ecd1c430c 100644
--- a/src/lang/english/markdown/steam-parser.md
+++ b/src/lang/english/markdown/steam-parser.md
@@ -2,6 +2,9 @@
 
 This parser imports steam games into SRM. It does not add shortcuts, but it allows you to set the artwork for your steam games. By default the parser will get games from all user accounts in the steam directory specified &mdash; if you would prefer to only get the games for a subset of the accounts then specify them in the `User accounts` field.
 
+## Limitations
+Unfortunately for the time being this parser only works for steam games **that are in at least one category**. The reason for this is that Steam only stores your full list of games locally if they are categorized. Sometimes, for unknown reasons, games will be stored locally regardless and the parser will work, but to be safe the easiest thing to do is just **create a Steam Category** that has all of your Steam games in it.
+
 ## User accounts (Optional)
 
 Can be used to limit configuration to specific user accounts. In order to set user accounts, the following syntax must be used:
diff --git a/src/lib/parsers/steam.parser.ts b/src/lib/parsers/steam.parser.ts
index dab1529b68..c784c541ed 100644
--- a/src/lib/parsers/steam.parser.ts
+++ b/src/lib/parsers/steam.parser.ts
@@ -57,7 +57,6 @@ export class SteamParser implements GenericParser {
               return Promise.resolve({title: (appinfo[infoIndex].entries.common||{}).name, appid: appId});
             } else {
               return appid(parseInt(appId)).then((x: any)=>{
-                console.log(x);
                 return {title: (x||{}).name, appid: appId}
               });
             }
diff --git a/src/renderer/components/nav-expand.component.ts b/src/renderer/components/nav-expand.component.ts
index 2607a46d80..184397a1fc 100644
--- a/src/renderer/components/nav-expand.component.ts
+++ b/src/renderer/components/nav-expand.component.ts
@@ -2,33 +2,35 @@ import { Component, ContentChildren, QueryList, ElementRef, OnDestroy, ViewEncap
 import { NavLinkComponent } from './nav-link.component';
 
 @Component({
-    selector: 'nav-expand',
-    template: `
-        <ng-content select=".title"></ng-content>
-        <div class="items"><ng-content select=".item"></ng-content></div>
-    `,
-    styleUrls: ['../styles/nav-expand.component.scss'],
-    host: { '[class.empty]': 'itemCount === 0' },
-    encapsulation: ViewEncapsulation.None
+  selector: 'nav-expand',
+  template: `
+  <ng-content select=".title"></ng-content>
+  <div class="items"><ng-content select=".item"></ng-content></div>
+  `,
+  styleUrls: ['../styles/nav-expand.component.scss'],
+  encapsulation: ViewEncapsulation.None
 })
+
+//Redid essentially all of the child element tracking functionality using a simple ngIf
 export class NavExpandComponent implements OnDestroy {
-    private itemCount: number = 0;
-    private keepAlive: boolean = true;
-    @ContentChildren(NavLinkComponent, { read: ElementRef }) children: QueryList<ElementRef>;
+  // private itemCount: number = 0;
+  // private keepAlive: boolean = true;
+  // @ContentChildren(NavLinkComponent, { read: ElementRef }) children: QueryList<ElementRef>;
 
-    ngAfterContentInit() {
-        this.children.changes.takeWhile(() => this.keepAlive).subscribe((data: QueryList<ElementRef>) => {
-            if (data) {
-                this.itemCount = data.toArray().filter((dataItem) => {
-                    return (<HTMLElement>dataItem.nativeElement).parentElement.classList.contains('items');
-                }).length;
-            }
-            else
-                this.itemCount = 0;
-        });
-    }
+  ngAfterContentInit() {
+    // this.children.changes.takeWhile(() => this.keepAlive).subscribe((data: QueryList<ElementRef>) => {
+    //   if (data) {
+    //     this.itemCount = data.toArray().filter((dataItem) => {
+    //       return (<HTMLElement>dataItem.nativeElement).parentElement.classList.contains('items');
+    //     }).length;
+    //   }
+    //   else {
+    //     this.itemCount = 0;
+    //   }
+    // });
+  }
 
-    ngOnDestroy() {
-        this.keepAlive = false;
-    }
-}
\ No newline at end of file
+  ngOnDestroy() {
+    //this.keepAlive = false;
+  }
+}
diff --git a/src/renderer/components/nav.component.ts b/src/renderer/components/nav.component.ts
index e84947d5ec..b25989b435 100644
--- a/src/renderer/components/nav.component.ts
+++ b/src/renderer/components/nav.component.ts
@@ -1,4 +1,4 @@
-import { Component, ChangeDetectionStrategy, ChangeDetectorRef, ApplicationRef, OnDestroy } from '@angular/core';
+import { Component, ChangeDetectionStrategy, ChangeDetectorRef, OnDestroy } from '@angular/core';
 import { FormBuilder, FormArray, FormGroup, FormControl } from '@angular/forms';
 import { ParsersService, LanguageService, UserExceptionsService } from '../services';
 import { UserConfiguration } from '../../models';
@@ -28,33 +28,33 @@ export class NavComponent implements OnDestroy {
     private languageService: LanguageService,
     private exceptionsService: UserExceptionsService,
     private changeRef: ChangeDetectorRef,
-    private appRef: ApplicationRef,
     private formBuilder: FormBuilder,
   ) {}
 
   ngOnInit() {
     this.subscriptions.add(this.parsersService.getUserConfigurations().subscribe((userConfigurations) => {
-      //if(userConfigurations.length != this.numConfigurations) {
-        this.navForm = this.formBuilder.group({
-          parserStatuses: this.formBuilder.array(userConfigurations.map((config: {saved: UserConfiguration, current: UserConfiguration}) => {
-            let singleton={};
-            singleton[config.saved.parserId] = ! config.saved.disabled;
-            return this.formBuilder.group(singleton);
-          }))
-        });
-        (this.navForm.get("parserStatuses") as FormArray).controls.forEach((control: FormControl)=>{
-          control.valueChanges.subscribe((val: {[parserId: string]: boolean}) => {
-            console.log("Little Change: ", val)
-            this.parsersService.changeEnabledStatus(Object.keys(val)[0], Object.values(val)[0])
-          })
+      this.numConfigurations = userConfigurations.length;
+      this.userConfigurations = userConfigurations;
+      let someOn = userConfigurations.length ? userConfigurations.map(config=>!config.saved.disabled).reduce((x,y)=>x||y) : false;
+      this.navForm = this.formBuilder.group({
+        selectAll: someOn,
+        parserStatuses: this.formBuilder.array(userConfigurations.map((config: {saved: UserConfiguration, current: UserConfiguration}) => {
+          let singleton={};
+          singleton[config.saved.parserId] = ! config.saved.disabled;
+          return this.formBuilder.group(singleton);
+        }))
+      });
+      this.navForm.get("selectAll").valueChanges.subscribe((val)=>{
+        if(!val || this.userConfigurations.map(config=>config.saved.disabled).reduce((x,y)=>x&&y)) {
+          this.parsersService.changeEnabledStatusAll(val);
+        }
+      });
+      (this.navForm.get("parserStatuses") as FormArray).controls.forEach((control: FormControl)=>{
+        control.valueChanges.subscribe((val: {[parserId: string]: boolean}) => {
+          this.parsersService.changeEnabledStatus(Object.keys(val)[0], Object.values(val)[0])
         })
-        this.numConfigurations = userConfigurations.length;
-        this.userConfigurations = userConfigurations;
-      //}
-
-      this.appRef.tick()
+      })
       this.changeRef.detectChanges();
-      this.refreshActiveRoute();
     }));
     this.subscriptions.add(this.exceptionsService.isUnsavedObservable.subscribe((val:boolean)=>{
       this.isExceptionsUnsaved = val;
diff --git a/src/renderer/components/user-exceptions.component.ts b/src/renderer/components/user-exceptions.component.ts
index 6238600118..90ca302b46 100644
--- a/src/renderer/components/user-exceptions.component.ts
+++ b/src/renderer/components/user-exceptions.component.ts
@@ -90,9 +90,6 @@ export class ExceptionsComponent implements OnDestroy {
       this.userExceptions = data.current ? data.current : data.saved;
       if(!this.exceptionsService.isUnsaved) {
         this.setForm();
-        console.log("how many times we doin that.");
-        console.log("numexceps: ", this.userExceptions.length);
-        console.log(this.exceptionsForm);
       }
       if(data.current) {
         this.exceptionsService.setIsUnsaved(true);
diff --git a/src/renderer/services/parsers.service.ts b/src/renderer/services/parsers.service.ts
index b6ca6f2b98..3737c6974b 100644
--- a/src/renderer/services/parsers.service.ts
+++ b/src/renderer/services/parsers.service.ts
@@ -97,16 +97,24 @@ export class ParsersService {
     let temp = userConfigurations[currentIndex];
     userConfigurations[currentIndex] = userConfigurations[newIndex];
     userConfigurations[newIndex] = temp;
-
     this.userConfigurations.next(userConfigurations);
     this.saveUserConfigurations();
   }
 
   changeEnabledStatus(parserId: string, enabled: boolean) {
-    let updateIndex = this.userConfigurations.getValue().map(e=>e.saved.parserId).indexOf(parserId);
-    let config = _.cloneDeep(this.userConfigurations.getValue()[updateIndex].saved);
-    config.disabled = !enabled;
-    this.updateConfiguration(updateIndex, config);
+    let userConfigurations = this.userConfigurations.getValue();
+    let updateIndex = userConfigurations.map(e=>e.saved.parserId).indexOf(parserId);
+    userConfigurations[updateIndex].saved.disabled = !enabled;
+    this.userConfigurations.next(userConfigurations);
+    this.saveUserConfigurations();
+  }
+  changeEnabledStatusAll(enabled: boolean) {
+    let userConfigurations = this.userConfigurations.getValue();
+    for(let i=0; i < userConfigurations.length; i++) {
+      userConfigurations[i].saved.disabled = !enabled;
+    }
+    this.userConfigurations.next(userConfigurations);
+    this.saveUserConfigurations();
   }
 
   updateConfiguration(index: number, config?: UserConfiguration) {
diff --git a/src/renderer/styles/nav-expand.component.scss b/src/renderer/styles/nav-expand.component.scss
index 0f1e956e20..033b03b555 100644
--- a/src/renderer/styles/nav-expand.component.scss
+++ b/src/renderer/styles/nav-expand.component.scss
@@ -18,9 +18,10 @@ nav-expand {
     & >.title {
         display: flex;
         overflow-y: auto;
+        overflow-x: hidden;
         flex-direction: column;
 
         margin: 0;
         padding: 0;
     }
-}
\ No newline at end of file
+}
diff --git a/src/renderer/styles/nav-link.component.scss b/src/renderer/styles/nav-link.component.scss
index a787b1ba1b..cd5f8a9773 100644
--- a/src/renderer/styles/nav-link.component.scss
+++ b/src/renderer/styles/nav-link.component.scss
@@ -14,9 +14,9 @@ nav-link {
         text-overflow: ellipsis;
     }
 
-    &.title {
+    &.titlelink {
         >.content {
             display: flex;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/renderer/styles/nav.component.scss b/src/renderer/styles/nav.component.scss
index bd15e9397c..c8d75a1d30 100644
--- a/src/renderer/styles/nav.component.scss
+++ b/src/renderer/styles/nav.component.scss
@@ -15,7 +15,35 @@
 	--link-vPadding: 0.5em;
 	grid-area: nav;
 	@include webkitScrollbar(nav-scrollbar, 0.375em);
-
+  .parsers {
+    .parserlink {
+      width: 64%;
+    }
+    .titlelink {
+      width: 64%;
+    }
+    .inputContainer {
+      display: flex;
+      flex-direction: column;
+
+      margin: 0.1em 0 .1em 0;
+      padding-left: 0em;
+
+      .inlineGroup {
+        display: flex;
+        margin: 0.1em 0.1em 0.1em 0;
+        justify-content: space-between;
+        align-items: center;
+      }
+      .ngToggleButton {
+        font-size: 1em;
+
+        margin: 0.1em 0 0.1em 0;
+
+        @include ngToggleButtonColor(ng-toggle-button);
+      }
+    }
+  }
 	nav-link {
 		height: var(--link-height);
 		padding: var(--link-vPadding) 1em;
@@ -26,7 +54,8 @@
 		svg {
 			height: var(--link-height);
 			width: 1em;
-
+      margin-bottom:-4px;
+      margin-left: -5px;
 			polyline {
 				stroke: var(--color-nav-link-text);
 			}
@@ -66,8 +95,11 @@
 		}
 	}
 
-	> nav-expand {
-		nav-link:not(.title) {
+	nav-expand {
+    nav-link.titlelink {
+      padding: var(--link-vPadding) 2em var(--link-vPadding) 1em;
+    }
+		nav-link:not(.titlelink) {
 			padding: var(--link-vPadding) 1em var(--link-vPadding) 2em;
 
 			position: relative;
@@ -150,13 +182,5 @@
 				}
 			}
 		}
-
-		&.empty {
-			nav-link.title {
-				svg {
-					display: none;
-				}
-			}
-		}
 	}
 }
diff --git a/src/renderer/templates/nav.component.html b/src/renderer/templates/nav.component.html
index 4181ac64a0..d325c375bc 100644
--- a/src/renderer/templates/nav.component.html
+++ b/src/renderer/templates/nav.component.html
@@ -7,40 +7,31 @@
   </nav-link>
 </nav-expand>
 <nav-link routerLink="/about" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">{{lang.about}}</nav-link>
-<div [formGroup]="navForm" *ngIf="!!navForm">
+<div class="parsers" [formGroup]="navForm" *ngIf="!!navForm">
   <nav-expand routerLinkActive="active">
-    <nav-link class="title" [routerLink]="['/parsers', -1]" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">
-      <span>{{lang.parsers}}</span>
-      <span>&nbsp;&nbsp;</span>
-      <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 300 300">
-        <polyline points="30,110 150,210 270,110" style="stroke-width:30;fill:none;" />
-      </svg>
-    </nav-link>
+    <div class="title">
+      <div class="inputContainer">
+        <div class="inlineGroup">
+          <nav-link class="titlelink" [routerLink]="['/parsers', -1]" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">
+            <span>{{lang.parsers}}</span>
+            <span>&nbsp;&nbsp;</span>
+            <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 300 300" *ngIf="userConfigurations.length">
+              <polyline points="30,110 150,210 270,110" style="stroke-width:30;fill:none;" />
+            </svg>
+          </nav-link>
+          <ng-toggle-button class="ngToggleButton" [formControl]="navForm.get('selectAll')"></ng-toggle-button>
+        </div>
+      </div>
+    </div>
     <div class="item" formArrayName="parserStatuses" *ngFor="let item of navForm.get('parserStatuses').controls;let i=index">
-      <div [formGroupName]=i>
+      <div class="inputContainer" [formGroupName]=i>
         <div class="inlineGroup">
-          <nav-link class="item" [ngClass]="{unsaved: userConfigurations[i].current != null, disabled: userConfigurations[i].saved.disabled}" [routerLink]="['/parsers', i]" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true, dummy: dummy }">
+          <nav-link class="parserlink" [ngClass]="{unsaved: userConfigurations[i].current != null, disabled: userConfigurations[i].saved.disabled}" [routerLink]="['/parsers', i]" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true, dummy: dummy }">
             {{userConfigurations[i].saved.configTitle || lang.noTitle}}
           </nav-link>
           <ng-toggle-button class="ngToggleButton" [formControl]="item.controls[userConfigurations[i].saved.parserId]"></ng-toggle-button>
         </div>
       </div>
     </div>
-    <!-- <nav-link class="item" [ngClass]="{unsaved: config.current != null, disabled: config.saved.disabled}" *ngFor="let config of userConfigurations; index as i" [routerLink]="['/parsers', i]" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true, dummy: dummy }"> -->
-    <!--   {{config.saved.configTitle || lang.noTitle}} -->
-    <!-- </nav-link> -->
   </nav-expand>
 </div>
-<!-- <div class="item" [formGroup]="navForm" *ngIf="!!navForm"> -->
-<!--   <div formArrayName="parserStatuses" -->
-<!--        *ngFor="let item of navForm.get('parserStatuses').controls;let i=index;"> -->
-<!--     <div [formGroupName]=i> -->
-<!--       <div class="inlineGroup"> -->
-<!--         <nav-link class="item" [ngClass]="{unsaved: userConfigurations[i].current != null, disabled: userConfigurations[i].saved.disabled}" [routerLink]="['/parsers', i]" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true, dummy: dummy }"> -->
-<!--           {{userConfigurations[i].saved.configTitle || lang.noTitle}} -->
-<!--         </nav-link> -->
-<!--         <ng-toggle-button class="ngToggleButton" [formControl]="item.controls[userConfigurations[i].saved.parserId]"></ng-toggle-button> -->
-<!--       </div> -->
-<!--     </div> -->
-<!--   </div> -->
-<!-- </div> -->