Carousel improvements, ability to customize number of visible zones and offset.

merge-notes
isark 2 years ago
parent 70cdb6b3b0
commit d010d6dde7

@ -1,6 +1,6 @@
import { animate, keyframes, state, style, transition, trigger } from '@angular/animations'; import { animate, keyframes, state, style, transition, trigger } from '@angular/animations';
import { NgStyle } from '@angular/common'; import { NgStyle } from '@angular/common';
import { AfterViewInit, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, Input, OnInit, Output, QueryList, TemplateRef, ViewChild, ViewChildren } from '@angular/core'; import { AfterViewInit, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { AngularResizeEventModule, ResizedEvent } from 'angular-resize-event'; import { AngularResizeEventModule, ResizedEvent } from 'angular-resize-event';
import { Subject, debounceTime } from 'rxjs'; import { Subject, debounceTime } from 'rxjs';
@ -33,10 +33,9 @@ import { Subject, debounceTime } from 'rxjs';
]) ])
] ]
}) })
export class CarouselComponent<T> implements OnInit, AfterViewInit { export class CarouselComponent<T> implements OnInit, AfterViewInit, OnChanges {
@Output() afterInitSelf: EventEmitter<CarouselComponent<T>> = new EventEmitter<CarouselComponent<T>>(); @Output() afterInitSelf: EventEmitter<CarouselComponent<T>> = new EventEmitter<CarouselComponent<T>>();
@Output() changedIndex: EventEmitter<number> = new EventEmitter<number>();
@Input() slides?: T[]; @Input() slides?: T[];
@ContentChild(TemplateRef) template?: TemplateRef<any>; @ContentChild(TemplateRef) template?: TemplateRef<any>;
@ViewChild('carouselWindow') window!: ElementRef; @ViewChild('carouselWindow') window!: ElementRef;
@ -45,6 +44,7 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
@Input() initIndex?: number; @Input() initIndex?: number;
current: number = 0; current: number = 0;
intersectionObserver?: IntersectionObserver; intersectionObserver?: IntersectionObserver;
visibleSlides?: IntersectingSlide[]; visibleSlides?: IntersectingSlide[];
increasing: boolean = true; increasing: boolean = true;
@ -53,12 +53,10 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
animation: string = 'vertical'; animation: string = 'vertical';
directionTime: number = 0; directionTime: number = 0;
@Input() numVisible: number = 1; @Input() numVisible: number = 1;
@Input() offset: number = 0;
containerDirectionLength: number = 0; containerDirectionLength: number = 0;
private debouncedOnchange: Subject<void> = new Subject<void>(); private debouncedOnchange: Subject<void> = new Subject<void>();
constructor(private cdr: ChangeDetectorRef) { constructor(private cdr: ChangeDetectorRef) {
this.visibleSlides = []; this.visibleSlides = [];
this.debouncedOnchange.pipe(debounceTime(500)).subscribe(() => this.realOnChange()); this.debouncedOnchange.pipe(debounceTime(500)).subscribe(() => this.realOnChange());
@ -67,9 +65,9 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
} }
} }
ngOnInit(): void { ngOnInit(): void {
this.afterInitSelf.next(this); this.afterInitSelf.next(this);
this.intersectionObserver = new IntersectionObserver((entries, observer) => { this.intersectionObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => { entries.forEach(entry => {
const runIntersectionHandling = () => { const runIntersectionHandling = () => {
@ -77,38 +75,35 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
if (!entryIndex && entryIndex != 0) { if (!entryIndex && entryIndex != 0) {
return; return;
} }
const entryIntersectingSlide = this.visibleSlides?.find((s) => {
return s.index == entryIndex; const entryIntersectingSlide = this.visibleSlides?.find(s => s.index == entryIndex);
});
if (!entryIntersectingSlide) { if (!entryIntersectingSlide) {
return; return;
} }
entryIntersectingSlide.currentlyIntersecting = entry.isIntersecting; entryIntersectingSlide.currentlyIntersecting = entry.isIntersecting;
if (entryIntersectingSlide.hasBeenVisible && !entry.isIntersecting) {
this.visibleSlides = this.visibleSlides?.filter(e => e.index != entryIndex);
this.intersectionObserver?.unobserve(entry.target);
}
}; };
runIntersectionHandling(); runIntersectionHandling();
this.onChange(); this.onChange();
}) })
}) })
} }
numExtraNext() { numExtraNext() {
return Math.floor((this.numVisible - 1) / 2); return this.numVisible + this.offset - 1;
} }
numExtraPrev() { numExtraPrev() {
return Math.ceil((this.numVisible - 1) / 2); return 0 + this.offset;
} }
ngAfterViewInit(): void { ngOnChanges(changes: SimpleChanges): void {
if(changes['numVisible'] || changes['offset']) {
this.reinitializeVisibleSlides();
}
}
ngAfterViewInit(): void {
this.slideElements.changes.subscribe((comps: QueryList<ElementRef>) => { this.slideElements.changes.subscribe((comps: QueryList<ElementRef>) => {
comps.forEach((comp) => this.handleNewDomSlide(comp)) comps.forEach((comp) => this.handleNewDomSlide(comp))
}); });
@ -123,7 +118,6 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
for (let i = 0; i <= this.numExtraNext() && i < this.slides!.length; i++) { for (let i = 0; i <= this.numExtraNext() && i < this.slides!.length; i++) {
this.visibleSlides?.push({ this.visibleSlides?.push({
index: i, index: i,
hasBeenVisible: false,
currentlyIntersecting: false, currentlyIntersecting: false,
}) })
} }
@ -135,20 +129,19 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
setIndex(slideIndex: number) { setIndex(slideIndex: number) {
this.current = slideIndex; this.current = slideIndex;
console.log("setIndex", slideIndex); this.reinitializeVisibleSlides();
this.visibleSlides!.length = 0; this.onChange();
console.log("length", this.slides!.length); }
for (let i = -this.numExtraPrev(); i <= this.numExtraNext(); i++) { reinitializeVisibleSlides() {
console.log("i, ", i); this.visibleSlides!.length = 0;
if (this.current + i >= 0 && this.current + i < this.slides!.length) { const start = Math.max(0, this.current - this.numExtraPrev());
console.log("pushing", this.current + i); const end = Math.min(this.current + this.numExtraNext(), this.slides!.length - 1);
for (let i = start; i <= end; i++) {
this.visibleSlides?.push({ this.visibleSlides?.push({
index: this.current + i, index: i,
hasBeenVisible: false,
currentlyIntersecting: false, currentlyIntersecting: false,
}); });
}
} }
this.onChange(); this.onChange();
@ -158,12 +151,10 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
this.increasing = true; this.increasing = true;
if (this.slides && this.current + 1 < this.slides?.length) { if (this.slides && this.current + 1 < this.slides?.length) {
this.current += 1; this.current += 1;
this.changedIndex.emit(this.current);
if (this.current + this.numExtraNext() < this.slides.length) { if (this.current + this.numExtraNext() < this.slides.length) {
if (!this.visibleSlides?.find(e => e.index == this.current + this.numExtraNext())) { if (!this.visibleSlides?.find(e => e.index == this.current + this.numExtraNext())) {
this.visibleSlides?.push({ this.visibleSlides?.push({
index: this.current + this.numExtraNext(), index: this.current + this.numExtraNext(),
hasBeenVisible: false,
currentlyIntersecting: false, currentlyIntersecting: false,
}); });
} }
@ -176,13 +167,10 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
this.increasing = false; this.increasing = false;
if (this.current - 1 >= 0) { if (this.current - 1 >= 0) {
this.current -= 1; this.current -= 1;
this.changedIndex.emit(this.current);
if (this.current - this.numExtraPrev() >= 0) { if (this.current - this.numExtraPrev() >= 0) {
if (!this.visibleSlides?.find(e => e.index == this.current - this.numExtraPrev())) { if (!this.visibleSlides?.find(e => e.index == this.current - this.numExtraPrev())) {
this.visibleSlides?.push({ this.visibleSlides?.push({
index: this.current - this.numExtraPrev(), index: this.current - this.numExtraPrev(),
hasBeenVisible: false,
currentlyIntersecting: false, currentlyIntersecting: false,
}); });
} }
@ -196,47 +184,36 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
} }
realOnChange() { realOnChange() {
const safetyFactor = this.numVisible == 1 ? 1 : 2; const safetyFactor = (this.numVisible == 1 ? 1 : 2);
{ const intersecting = this.visibleSlides?.filter(e => e.currentlyIntersecting).sort((e1, e2) => e1.index - e2.index);
const intersecting = this.visibleSlides?.filter(e => e.currentlyIntersecting).sort((e1, e2) => e1.index - e2.index); if (intersecting && intersecting.length > 0) {
if (intersecting && intersecting.length > 0) { const lowestIntersecting = intersecting![0];
const lowestIntersecting = intersecting![0]; const highestIntersecting = intersecting![intersecting!.length - 1];
this.visibleSlides = this.visibleSlides?.filter(e => e.index + safetyFactor >= lowestIntersecting!.index && e.index >= this.current - this.numExtraPrev());
}
}
{
const intersecting = this.visibleSlides?.filter(e => e.currentlyIntersecting).sort((e1, e2) => e1.index - e2.index).reverse(); const min = Math.min(lowestIntersecting.index - safetyFactor, this.current - this.numExtraPrev());
if (intersecting && intersecting.length > 0) { const max = Math.max(highestIntersecting.index + safetyFactor, this.current + this.numExtraNext());
const highestIntersecting = intersecting![0]
this.visibleSlides = this.visibleSlides?.filter(e => e.index - safetyFactor <= highestIntersecting!.index && e.index <= this.current + this.numExtraNext()); this.visibleSlides = this.visibleSlides?.filter(e => e.index >= min && e.index <= max);
}
} }
} }
translation() { translation() {
let num = (this.current - this.numExtraNext() - (this.numVisible % 2 == 0 ? 1 : 0)) * (-1 / this.numVisible) * 100;
const step = this.containerDirectionLength / this.numVisible; const step = this.containerDirectionLength / this.numVisible;
const pos = (this.current - this.numExtraNext() - (this.numVisible % 2 == 0 ? 1 : 0)); const translation = -((this.current - this.offset) * step);
const offset = pos * -step;
if (this.vertical) { if (this.vertical) {
return `0 ${offset}px` return `0 ${translation}px`
} else { } else {
return `${offset}px 0` return `${translation}px 0`
} }
} }
templateValue() { templateValue() {
const len = this.slides?.length; const len = this.slides?.length;
return `repeat(${len}, ${this.containerDirectionLength / this.numVisible}px)`; return `repeat(${len}, ${this.containerDirectionLength / this.numVisible}px)`;
} }
style() { style() {
let style: any = { let style: any = {};
};
if (this.vertical) { if (this.vertical) {
style['grid-template-rows'] = this.templateValue(); style['grid-template-rows'] = this.templateValue();
@ -281,11 +258,9 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
this.containerDirectionLength = event.newRect.width; this.containerDirectionLength = event.newRect.width;
} }
} }
} }
interface IntersectingSlide { interface IntersectingSlide {
index: number; index: number;
hasBeenVisible: boolean;
currentlyIntersecting: boolean; currentlyIntersecting: boolean;
} }

@ -1,13 +1,15 @@
<ng-container *ngIf="init"> <ng-container *ngIf="init">
<div #globalTopLeft style="position: fixed; top: 0; left: 0; z-index: -1;"></div> <div #globalTopLeft style="position: fixed; top: 0; left: 0; z-index: -1;"></div>
<ng-container *ngIf="rect && planService.currentPlan"> <ng-container *ngIf="rect && planService.currentPlan">
<div class="target waypoint trial" [style.background-color]="backgroundColor ? backgroundColor : 'rgba(0, 0, 0, 0.1)'" <div class="target waypoint trial"
[style.background-color]="backgroundColor ? backgroundColor : 'rgba(0, 0, 0, 0.1)'"
[style.transform]="transform()" [style.width]="rect.width + 'px'" [style.height]="rect.height + 'px'" [style.transform]="transform()" [style.width]="rect.width + 'px'" [style.height]="rect.height + 'px'"
[class]="specialClasses()" (wheel)="onScroll($event)" #targetRef> [class]="specialClasses()" (wheel)="onScroll($event)" #targetRef>
<ng-container *ngIf="planService.currentPlan"> <ng-container *ngIf="planService.currentPlan">
<span hidden>{{planService.currentPlan.current}}</span> <span hidden>{{planService.currentPlan.current}}</span>
<carousel [initIndex]="planService.currentPlan.current" [numVisible]="3" <carousel [initIndex]="planService.currentPlan.current" [numVisible]="configService.config.numVisible"
[slides]="planService.currentPlan.plan" (afterInitSelf)="registerZoneSlides($event)"> [offset]="clampedOffset()" [slides]="planService.currentPlan.plan"
(afterInitSelf)="registerZoneSlides($event)">
<ng-template let-slide let-index="index"> <ng-template let-slide let-index="index">
<div class="zone-slide" [style.color]="configService.config.noteDefaultFg" <div class="zone-slide" [style.color]="configService.config.noteDefaultFg"
[style.border]="index == planService.currentPlan.current ? '1px white solid' : 'none'"> [style.border]="index == planService.currentPlan.current ? '1px white solid' : 'none'">
@ -35,6 +37,10 @@
<button mat-icon-button *ngIf="overlayService.interactable" class="settings-button" <button mat-icon-button *ngIf="overlayService.interactable" class="settings-button"
(click)="settingsClick($event)" (mousedown)="$event.stopPropagation()"><img (click)="settingsClick($event)" (mousedown)="$event.stopPropagation()"><img
src="assets/material-settings.svg"></button> src="assets/material-settings.svg"></button>
<!-- <div *ngIf="overlayService.interactable" #tooltip="matTooltip" matTooltip="(T) = Trial in zone<br> (W) = Waypoint in zone. <br> Border around plan window will light up in the same color"
[matTooltipPosition]="'below'" matTooltipHideDelay="1000" class="help-button">
<img src="assets/material-help.svg">
</div> -->
</div> </div>
<ngx-moveable #moveable [target]="targetRef" [draggable]="draggable && overlayService.interactable" <ngx-moveable #moveable [target]="targetRef" [draggable]="draggable && overlayService.interactable"

@ -115,7 +115,12 @@ notes {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
}
.help-button {
position: absolute;
top: 0;
left: 0;
} }

@ -1,21 +1,17 @@
import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, Input, NgZone, OnInit, ViewChild } from '@angular/core'; import { AfterViewInit, ChangeDetectorRef, Component, Input, NgZone, OnInit, ViewChild } from '@angular/core';
import { NgxMoveableComponent, OnDragEnd, OnResize, OnResizeEnd } from 'ngx-moveable'; import { NgxMoveableComponent, OnDragEnd, OnResize, OnResizeEnd } from 'ngx-moveable';
import { OnDrag } from 'ngx-moveable'; import { OnDrag } from 'ngx-moveable';
import { ConfigService } from '../_services/config.service'; import { ConfigService } from '../_services/config.service';
import { Rect } from '../_models/generated/Rect'; import { Rect } from '../_models/generated/Rect';
import { Color } from '../color-picker/color-picker.component';
import { ShortcutService } from '../_services/shortcut.service'; import { ShortcutService } from '../_services/shortcut.service';
import { CarouselComponent } from '../carousel/carousel.component'; import { CarouselComponent } from '../carousel/carousel.component';
import { PlanService } from '../_services/plan.service'; import { PlanService } from '../_services/plan.service';
import { Plan, PlanElement } from '../_models/plan'; import { Plan, PlanElement } from '../_models/plan';
import { WorldAreaService } from '../_services/world-area.service'; import { WorldAreaService } from '../_services/world-area.service';
import { WorldArea } from '../_models/world-area'; import { WorldArea } from '../_models/world-area';
import { NotesComponent } from '../editor/notes/notes.component';
import { ResizedEvent } from 'angular-resize-event';
import { from } from 'rxjs'; import { from } from 'rxjs';
import { open } from '@tauri-apps/api/dialog'; import { open } from '@tauri-apps/api/dialog';
import { OverlayRef } from '@angular/cdk/overlay'; import { OverlayService } from '../_services/overlay.service';
import { OverlayService, StateEvent } from '../_services/overlay.service';
import { appWindow } from '@tauri-apps/api/window'; import { appWindow } from '@tauri-apps/api/window';
import { EventsService } from '../_services/events.service'; import { EventsService } from '../_services/events.service';
@ -25,23 +21,12 @@ import { EventsService } from '../_services/events.service';
styleUrls: ['./plan-display.component.scss'] styleUrls: ['./plan-display.component.scss']
}) })
export class PlanDisplayComponent implements AfterViewInit, OnInit { export class PlanDisplayComponent implements AfterViewInit, OnInit {
specialClasses() {
const waypoint = this.hasWaypoint() ? 'active' : '';
const trial = this.hasTrial() ? 'trial-active' : '';
return `${waypoint} ${trial}`;
}
@Input() backgroundColor?: String; @Input() backgroundColor?: String;
draggable: boolean = true; draggable: boolean = true;
rect?: Rect; rect?: Rect;
bounds: any = { "left": 0, "top": 0, "right": 0, "bottom": 0, "position": "css" }; bounds: any = { "left": 0, "top": 0, "right": 0, "bottom": 0, "position": "css" };
@ViewChild("moveable") moveable?: NgxMoveableComponent; @ViewChild("moveable") moveable?: NgxMoveableComponent;
// slides: PlanElement[] = [];
slideIndex: number = 0; slideIndex: number = 0;
zoneSlides?: CarouselComponent<PlanElement>; zoneSlides?: CarouselComponent<PlanElement>;
currentSlides?: CarouselComponent<PlanElement>; currentSlides?: CarouselComponent<PlanElement>;
@ -57,16 +42,6 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
}) })
}); });
// const test = this.events.listen<StateEvent>("OverlayStateChange").subscribe(event => {
// if (!this.hasAttachedOnce) {
// this.hasAttachedOnce = true;
// test.unsubscribe();
// if (!event.payload.Hidden)
// overlayService.setInteractable();
// }
// });
appWindow.listen("entered", (entered) => { appWindow.listen("entered", (entered) => {
if (this.planService.currentPlan) { if (this.planService.currentPlan) {
const current = this.planService.currentPlan.current; const current = this.planService.currentPlan.current;
@ -175,6 +150,7 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
this.zoneSlides = carousel; this.zoneSlides = carousel;
this.zoneSlides.setIndex(this.slideIndex); this.zoneSlides.setIndex(this.slideIndex);
} }
registerCurrentSlides(carousel: CarouselComponent<PlanElement>) { registerCurrentSlides(carousel: CarouselComponent<PlanElement>) {
this.currentSlides = carousel; this.currentSlides = carousel;
this.currentSlides.setIndex(this.slideIndex); this.currentSlides.setIndex(this.slideIndex);
@ -201,11 +177,9 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
this.slideIndex = index; this.slideIndex = index;
if (this.currentSlides) { if (this.currentSlides) {
this.currentSlides.setIndex(index); this.currentSlides.setIndex(index);
} }
if (this.zoneSlides) { if (this.zoneSlides) {
this.zoneSlides.setIndex(index); this.zoneSlides.setIndex(index);
} }
} }
@ -215,31 +189,6 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
}); });
} }
onResizeNote(noteSlide: NotesComponent) {
if (!noteSlide.ref) { return; }
let bounds = noteSlide.ref.nativeElement.getBoundingClientRect();
const children = noteSlide.ref.nativeElement.children;
let sumWidth = 0;
let sumHeight = 0;
for (let child of children) {
const c = child.getBoundingClientRect();
sumWidth += c.width;
sumHeight += c.height;
}
const scale = Math.min(
sumWidth / bounds.width,
sumHeight / bounds.height,
)
for (let child of children) {
child.style.transform = `scale(1, ${scale})`;
}
}
settingsClick(event: any) { settingsClick(event: any) {
this.settingsOpen = !this.settingsOpen; this.settingsOpen = !this.settingsOpen;
event.stopPropagation(); event.stopPropagation();
@ -277,10 +226,6 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
}) })
} }
enumeratedPlans() {
}
onScroll(event: WheelEvent) { onScroll(event: WheelEvent) {
if (event.deltaY < 0) { if (event.deltaY < 0) {
this.prev(); this.prev();
@ -288,4 +233,14 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
this.next(); this.next();
} }
} }
specialClasses() {
const waypoint = this.hasWaypoint() ? 'active' : '';
const trial = this.hasTrial() ? 'trial-active' : '';
return `${waypoint} ${trial}`;
}
clampedOffset(): number {
return Math.min(this.configService.config.numVisible - 1, this.configService.config.offset);
}
} }

@ -12,6 +12,7 @@ import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatListModule } from '@angular/material/list'; import { MatListModule } from '@angular/material/list';
import { ScalableComponent } from '../Scalable/scalable.component'; import { ScalableComponent } from '../Scalable/scalable.component';
import {MatTooltipModule} from '@angular/material/tooltip';
@NgModule({ @NgModule({
declarations: [ declarations: [
PlanDisplayComponent PlanDisplayComponent
@ -29,7 +30,8 @@ import { ScalableComponent } from '../Scalable/scalable.component';
MatButtonModule, MatButtonModule,
MatIconModule, MatIconModule,
MatListModule, MatListModule,
ScalableComponent ScalableComponent,
MatTooltipModule
], ],
exports: [ exports: [
PlanDisplayComponent PlanDisplayComponent

@ -6,17 +6,22 @@
</h1> </h1>
</div> </div>
<div class="row"> <div class="row">
<color-picker [placement]="{color: 'bottom'}" [setColor]="configService.config.planBg" (color)="onPlanColorChange($event)">Plan window <color-picker [placement]="{color: 'bottom'}" [setColor]="configService.config.planBg"
background</color-picker> (color)="onPlanColorChange($event)">
Plan window background
</color-picker>
</div> </div>
<div class="row"> <div class="row">
<color-picker [placement]="{color: 'bottom'}" [setColor]="configService.config.backdropBg" (color)="onBackdropColorChange($event)">Overlay <color-picker [placement]="{color: 'bottom'}" [setColor]="configService.config.backdropBg"
backdrop color</color-picker> (color)="onBackdropColorChange($event)">
Overlay backdrop color
</color-picker>
</div> </div>
<div class="row"> <div class="row">
<color-picker [placement]="{color: 'bottom'}" [setColor]="configService.config.noteDefaultFg" (color)="onNoteColorChange($event)">Overlay <color-picker [placement]="{color: 'bottom'}" [setColor]="configService.config.noteDefaultFg"
default (color)="onNoteColorChange($event)">
font color</color-picker> Overlay default font color
</color-picker>
</div> </div>
<div class="d-flex flex-row justify-content-between"> <div class="d-flex flex-row justify-content-between">
@ -25,15 +30,26 @@
[(ngModel)]="configService.config.hideOnUnfocus"></mat-slide-toggle> [(ngModel)]="configService.config.hideOnUnfocus"></mat-slide-toggle>
</div> </div>
<div class="row"> <div class="row">
<button mat-raised-button color="primary" (click)="rebindOverlayToggle()">Overlay toggle shortcut: <button mat-raised-button color="primary" (click)="rebindOverlayToggle()">
{{configService.config.toggleOverlay}}</button> Overlay toggle shortcut: {{configService.config.toggleOverlay}}
</button>
</div> </div>
<div class="row"> <div class="row">
<button mat-raised-button color="primary" (click)="rebindPreviousZone()">Previous zone shortcut: <button mat-raised-button color="primary" (click)="rebindPreviousZone()">
{{configService.config.prev}}</button> Previous zone shortcut: {{configService.config.prev}}
</button>
</div> </div>
<div class="row"> <div class="row">
<button mat-raised-button color="primary" (click)="rebindNextZone()">Next zone shortcut: <button mat-raised-button color="primary" (click)="rebindNextZone()">
{{configService.config.next}}</button> Next zone shortcut: {{configService.config.next}}
</button>
</div>
<!-- TODO: Better visuals :D -->
<div class="row">
<input type="number" [(ngModel)]="configService.config.numVisible" min="1" max="10" step="1">
</div>
<div class="row">
<input type="number" [(ngModel)]="configService.config.offset" min="0" [max]="configService.config.numVisible - 1" step="1">
</div> </div>
</div> </div>

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#FFFFFF"><path d="M0 0h24v24H0z" fill="none"/><path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z"/></svg>

After

Width:  |  Height:  |  Size: 400 B

Loading…
Cancel
Save