+ [style]="{'width': '100%','max-width': mediaEntity.new_state?.attributes?.media_image_url ? (300*scale)+'px' : (800*scale)+'px'}">
+
-
+
@@ -102,8 +100,9 @@
(click)="mediaAction(mediaEntity, 'media_player.volume_up')"
icon="icon icon-plus" size="small" pTooltip="Volume +" [rounded]="true" [outlined]="true" class="uc-button"/>
+ [textValue]="'Volume '+Helper.getNumber(mediaEntity.new_state!.attributes!.volume!)+'%'+
+ (Helper.isMuted(mediaEntity) ? ' (muted)' : '')"
+ [editable]="checkFeature(mediaEntity, 'volume')" [secondaryState]="Helper.isMuted(mediaEntity)"/>
diff --git a/src/app/active-entities/media-entity/media-entity.component.ts b/src/app/active-entities/media-entity/media-entity.component.ts
index af321c6..f7cd777 100644
--- a/src/app/active-entities/media-entity/media-entity.component.ts
+++ b/src/app/active-entities/media-entity/media-entity.component.ts
@@ -8,7 +8,7 @@ import {
TemplateRef,
ViewEncapsulation
} from '@angular/core';
-import {MediaEntityState, RemoteWebsocketService} from "../../remote-widget/remote-websocket.service";
+import {MediaEntityState, RemoteWebsocketService} from "../../remote-websocket.service";
import {Remote} from "../../interfaces";
import {ServerService} from "../../server.service";
import {Button} from "primeng/button";
@@ -18,6 +18,7 @@ import {ScrollingTextComponent} from "../../controls/scrolling-text/scrolling-te
import {SliderComponent} from "../../controls/slider/slider.component";
import {TagModule} from "primeng/tag";
import {TooltipModule} from "primeng/tooltip";
+import {Helper} from "../../helper";
@Component({
selector: 'app-media-entity',
@@ -204,8 +205,5 @@ export class MediaEntityComponent implements OnInit, AfterViewInit {
cmd_id}).subscribe();
}
- getNumber(number: number) {
- if (isNaN(number)) return 0;
- return Math.round(number);
- }
+ protected readonly Helper = Helper;
}
diff --git a/src/app/activity-player/activity-player.component.html b/src/app/activity-player/activity-player.component.html
index 1fb6ee6..eb2a365 100644
--- a/src/app/activity-player/activity-player.component.html
+++ b/src/app/activity-player/activity-player.component.html
@@ -34,11 +34,19 @@
{{Helper.getEntityName(activity)}}
(onSelectButton)="handleMessage($event)"/>
+ [selectionMode]="false" [currentPage]="currentPage" [runMode]="true" (onSelectButton)="handleCommand($event)"/>
+
diff --git a/src/app/activity-player/activity-player.component.ts b/src/app/activity-player/activity-player.component.ts
index 681edd6..7da5548 100644
--- a/src/app/activity-player/activity-player.component.ts
+++ b/src/app/activity-player/activity-player.component.ts
@@ -11,14 +11,14 @@ import {DialogModule} from "primeng/dialog";
import {Message, MessageService, PrimeTemplate} from "primeng/api";
import {ActivityViewerComponent} from "../activity-viewer/activity-viewer.component";
import {ServerService} from "../server.service";
-import {RemoteWebsocketService} from "../remote-widget/remote-websocket.service";
-import {Activity, ButtonMapping, EntityCommand, Remote, UIPage} from "../interfaces";
+import {MediaEntityState, RemoteWebsocketService} from "../remote-websocket.service";
+import {Activity, ButtonMapping, Command, Entity, EntityCommand, Remote, UIPage} from "../interfaces";
import {Helper} from "../helper";
import {Button} from "primeng/button";
import {TooltipModule} from "primeng/tooltip";
import {ActivityButtonsComponent, ButtonMode} from "../activity-viewer/activity-buttons/activity-buttons.component";
import {NgIf} from "@angular/common";
-import {catchError, delay, forkJoin, from, map, mergeMap, of} from "rxjs";
+import {catchError, delay, forkJoin, from, map, mergeMap, Observable, of} from "rxjs";
import {ActivityGridComponent} from "../activity-viewer/activity-grid/activity-grid.component";
import {ToastModule} from "primeng/toast";
import {HttpErrorResponse} from "@angular/common/http";
@@ -26,6 +26,7 @@ import {ProgressBarModule} from "primeng/progressbar";
import {PaginationComponent} from "../controls/pagination/pagination.component";
import {RouterLink} from "@angular/router";
import {IconComponent} from "../controls/icon/icon.component";
+import {SliderComponent} from "../controls/slider/slider.component";
@Component({
selector: 'app-activity-player',
@@ -43,7 +44,8 @@ import {IconComponent} from "../controls/icon/icon.component";
ProgressBarModule,
PaginationComponent,
RouterLink,
- IconComponent
+ IconComponent,
+ SliderComponent
],
templateUrl: './activity-player.component.html',
styleUrl: './activity-player.component.css',
@@ -56,16 +58,20 @@ export class ActivityPlayerComponent {
configEntityCommands: EntityCommand[] | undefined;
@Input('remote') set _remote(value: Remote | undefined) {
this.remote = value;
- if (this.remote)
+ if (this.remote) {
this.server.getConfigEntityCommands(this.remote).subscribe(entityCommands => {
this.configEntityCommands = entityCommands;
this.cdr.detectChanges();
- })
+ });
+ this.update();
+ }
}
activity: Activity | undefined;
@Input("activity") set _activity (activity: Activity | undefined) {
this.activity = activity;
+ console.log("Play activity", this.activity);
this.currentPage = activity?.options?.user_interface?.pages?.[0];
+ this.update();
this.cdr.detectChanges();
}
@Input() visible = false;
@@ -76,9 +82,29 @@ export class ActivityPlayerComponent {
currentPage: UIPage | undefined;
progress = 0;
progressDetail: string | undefined;
+ volumeEntity: MediaEntityState | undefined;
constructor(private server:ServerService, protected remoteWebsocketService: RemoteWebsocketService,
- private cdr:ChangeDetectorRef, private messageService: MessageService) { }
+ private cdr:ChangeDetectorRef, private messageService: MessageService) {
+ this.remoteWebsocketService.onMediaStateChange().subscribe(mediaStates => {
+ if (!this.volumeEntity) return;
+ const state = mediaStates.find(item => item.entity_id === this.volumeEntity!.entity_id!);
+ if (state) {
+ this.volumeEntity = state;
+ this.cdr.detectChanges();
+ }
+ })
+ }
+
+ update() {
+ if (!this.remote || !this.activity) return;
+ this.getVolumeEntity().subscribe(mediaState => {
+ if (!mediaState) return;
+ console.log("Volume entity", mediaState);
+ this.volumeEntity = mediaState;
+ this.cdr.detectChanges();
+ })
+ }
protected readonly Helper = Helper;
@@ -159,13 +185,65 @@ export class ActivityPlayerComponent {
this.cdr.detectChanges();
}
+ handleCommand($event: {command: Command, mode: ButtonMode, severity: "success" | "error", error?: string}) {
+ let message = "Short press ";
+ if ($event.mode === ButtonMode.ShortPress) message = `Short press `;
+ else if ($event.mode === ButtonMode.LongPress) message = `Long press `;
+ else if ($event.mode === ButtonMode.DoublePress) message = `Double press `;
+ let entityName = Helper.getEntityName(this.activity?.options?.included_entities?.find(item => item.entity_id === $event.command.entity_id));
+ if (!entityName ||entityName === "") entityName = $event.command.entity_id;
+ const commandName = Helper.getCommandName($event.command, this.configEntityCommands);
+ message += `${entityName} ${commandName}`;
+ if ($event.error)
+ message = `${message} : ${$event.error}`;
+ this.onMessage.emit({severity: $event.severity, detail: message});
+ }
+
handleMessage($event: {button: ButtonMapping, mode: ButtonMode, severity: "success" | "error", error?: string}) {
let message = "Short press";
- if ($event.mode === ButtonMode.ShortPress) message = `Short press ${$event.button.short_press?.entity_id} ${$event.button.short_press?.cmd_id}`;
- else if ($event.mode === ButtonMode.LongPress) message = `Long press ${$event.button.long_press?.entity_id} ${$event.button.long_press?.cmd_id}`;
- else if ($event.mode === ButtonMode.DoublePress) message = `Double press ${$event.button.double_press?.entity_id} ${$event.button.double_press?.cmd_id}`;
+ const command = $event.mode == ButtonMode.ShortPress ? $event.button.short_press :
+ ($event.mode == ButtonMode.LongPress ? $event.button.long_press : $event.button.double_press);
+ if (!command) return;
+ let entityName = Helper.getEntityName(this.activity?.options?.included_entities?.find(item => item.entity_id === command.entity_id));
+ if (!entityName ||entityName === "") entityName = command.entity_id;
+ const commandName = Helper.getCommandName(command, this.configEntityCommands);
+
+ if ($event.mode === ButtonMode.ShortPress) message = `Short press ${entityName} ${commandName}`;
+ else if ($event.mode === ButtonMode.LongPress) message = `Long press ${entityName} ${commandName}`;
+ else if ($event.mode === ButtonMode.DoublePress) message = `Double press ${entityName} ${commandName}`;
if ($event.error)
message = `${message} : ${$event.error}`;
this.onMessage.emit({severity: $event.severity, detail: message});
}
+
+ getVolumeEntity(): Observable
+ {
+ if (!this.remote) return of(undefined);
+ const button = this.activity?.options?.button_mapping?.find(button => button.button === 'VOLUME_UP');
+ const volumeEntity = button?.short_press?.entity_id;
+ if (!volumeEntity) return of(undefined);
+ const entity = this.activity?.options?.included_entities?.find(entity => entity.entity_id === volumeEntity);
+ if (!entity || entity.entity_type !== 'media_player') return of(undefined);
+ return this.server.getRemotetEntity(this.remote, entity.entity_id!).pipe(map(entity => {
+ if (!Helper.checkFeature(entity, "volume")) return undefined;
+ return {...entity, new_state: {attributes: {...entity.attributes}, features: entity.features}} as MediaEntityState;
+ }))
+ }
+
+ updateVolume(volume: number, entity_id: string) {
+ if (!this.remote) return;
+ console.debug("Volume update", volume, entity_id);
+ let name = Helper.getEntityName(this.volumeEntity);
+ if (!name || name === "") name = entity_id;
+ this.server.executeRemotetCommand(this.remote, {entity_id,
+ cmd_id:"media_player.volume", params: {"volume": volume}}).subscribe({
+ next: (results) => {
+ this.onMessage.emit({severity: "success", detail: `Volume set ${name} : ${volume}%`});
+ },
+ error: err => this.onMessage.emit({severity: "error",
+ detail: `Error volume set ${name} : ${volume}% (${err.toString()})`})
+ });
+ }
+
+ protected readonly Math = Math;
}
diff --git a/src/app/activity-viewer/actiivty-media-entity/activity-media-entity.component.html b/src/app/activity-viewer/actiivty-media-entity/activity-media-entity.component.html
index bbfa51b..a60cd76 100644
--- a/src/app/activity-viewer/actiivty-media-entity/activity-media-entity.component.html
+++ b/src/app/activity-viewer/actiivty-media-entity/activity-media-entity.component.html
@@ -4,13 +4,13 @@
[alt]="mediaEntityState?.new_state?.attributes?.media_title" />
0"
diff --git a/src/app/activity-viewer/actiivty-media-entity/activity-media-entity.component.ts b/src/app/activity-viewer/actiivty-media-entity/activity-media-entity.component.ts
index eca2093..be63bf7 100644
--- a/src/app/activity-viewer/actiivty-media-entity/activity-media-entity.component.ts
+++ b/src/app/activity-viewer/actiivty-media-entity/activity-media-entity.component.ts
@@ -2,17 +2,19 @@ import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
- Component,
- Input,
+ Component, EventEmitter,
+ Input, Output,
ViewEncapsulation
} from '@angular/core';
import {ServerService} from "../../server.service";
-import {MediaEntityState, RemoteWebsocketService} from "../../remote-widget/remote-websocket.service";
+import {MediaEntityState, RemoteWebsocketService} from "../../remote-websocket.service";
import {NgIf} from "@angular/common";
import {ScrollingTextComponent} from "../../controls/scrolling-text/scrolling-text.component";
import {SliderComponent} from "../../controls/slider/slider.component";
import {Helper} from "../../helper";
-import {Remote} from "../../interfaces";
+import {Command, Remote} from "../../interfaces";
+import {ButtonMode} from "../activity-buttons/activity-buttons.component";
+import {HttpErrorResponse} from "@angular/common/http";
@Component({
selector: 'app-activity-media-entity',
@@ -41,6 +43,8 @@ export class ActivityMediaEntityComponent implements AfterViewInit {
protected readonly Helper = Helper;
textStyle = "font-size: 1.2rem";
@Input() size: { width: number; height: number } | undefined;
+ @Output() onSelectButton: EventEmitter<{command: Command, mode: ButtonMode, severity: "success" | "error",
+ error?: string}> = new EventEmitter();
constructor(protected remoteWebsocketService: RemoteWebsocketService, private server:ServerService,
private cdr: ChangeDetectorRef) {
@@ -116,7 +120,14 @@ export class ActivityMediaEntityComponent implements AfterViewInit {
const body = {entity_id: mediaEntity.entity_id,
cmd_id:"media_player.seek", params: {"media_position": newPosition}};
console.debug("Seek", body);
- this.server.executeRemotetCommand(this.remote, body).subscribe(
- {error: err => console.error("Error updting position", err)});
+
+ this.server.executeRemotetCommand(this.remote, body).subscribe({next: results => {
+ this.onSelectButton.emit({command: body, mode: ButtonMode.ShortPress, severity: "success"});
+ }, error: (err: HttpErrorResponse) => {
+ console.error("Error command", err);
+ this.onSelectButton.emit({command: body, mode: ButtonMode.ShortPress, severity: "error"});
+ this.onSelectButton.emit({command:body, mode: ButtonMode.ShortPress, severity: "error",
+ error: `Error updating position : ${err.error.name} (${err.status} ${err.statusText})`});
+ }});
}
}
diff --git a/src/app/activity-viewer/activity-grid/activity-grid.component.html b/src/app/activity-viewer/activity-grid/activity-grid.component.html
index a2e5d4c..2ca27e2 100644
--- a/src/app/activity-viewer/activity-grid/activity-grid.component.html
+++ b/src/app/activity-viewer/activity-grid/activity-grid.component.html
@@ -10,7 +10,6 @@
(itemClicked)="gridItemClicked($event)" [selectionMode]="selectionMode" [runMode]="runMode" class="grid-item">
-
@@ -25,13 +24,14 @@
[style]="Helper.getStyle(getEntityName((item.command | as : Command)?.entity_id!))">
-
+
-
+
diff --git a/src/app/activity-viewer/activity-grid/activity-grid.component.ts b/src/app/activity-viewer/activity-grid/activity-grid.component.ts
index e45c4d2..e25baac 100644
--- a/src/app/activity-viewer/activity-grid/activity-grid.component.ts
+++ b/src/app/activity-viewer/activity-grid/activity-grid.component.ts
@@ -2,9 +2,16 @@ import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
- Component, HostListener,
- Input, Pipe, PipeTransform, QueryList,
- ViewChild, ViewChildren,
+ Component,
+ EventEmitter,
+ HostListener,
+ Input,
+ Output,
+ Pipe,
+ PipeTransform,
+ QueryList,
+ ViewChild,
+ ViewChildren,
ViewEncapsulation
} from '@angular/core';
import {Helper} from "../../helper";
@@ -12,21 +19,14 @@ import {ActivityGridItemComponent} from "../activity-grid-item/activity-grid-ite
import {ChipModule} from "primeng/chip";
import {NgForOf, NgIf} from "@angular/common";
import {TagModule} from "primeng/tag";
-import {
- Activity,
- ActivityPageCommand,
- Command,
- EntityCommand,
- Remote,
- ScreenLayout,
- UIPage
-} from "../../interfaces";
+import {Activity, ActivityPageCommand, Command, EntityCommand, Remote, ScreenLayout, UIPage} from "../../interfaces";
import {UiCommandEditorComponent} from "../../activity-editor/ui-command-editor/ui-command-editor.component";
import {HttpErrorResponse} from "@angular/common/http";
import {ServerService} from "../../server.service";
import {MessageService} from "primeng/api";
import {ToastModule} from "primeng/toast";
import {ActivityMediaEntityComponent} from "../actiivty-media-entity/activity-media-entity.component";
+import {ButtonMode} from "../activity-buttons/activity-buttons.component";
@Pipe({name: 'as', standalone: true, pure: true})
export class AsPipe implements PipeTransform {
@@ -85,6 +85,8 @@ export class ActivityGridComponent implements AfterViewInit {
selection: ActivityGridItemComponent[] = [];
@ViewChild("commandeditor", {static: false}) commandeditor: UiCommandEditorComponent | undefined;
@ViewChildren(ActivityGridItemComponent) gridButtons:QueryList | undefined;
+ @Output() onSelectButton: EventEmitter<{command: Command, mode: ButtonMode, severity: "success" | "error",
+ error?: string}> = new EventEmitter();
configEntityCommands: EntityCommand[] | undefined;
public Command!: Command;
@@ -229,17 +231,17 @@ export class ActivityGridComponent implements AfterViewInit {
executeCommand(command: Command) {
if (!this.remote) return;
this.server.executeRemotetCommand(this.remote, command).subscribe({next: results => {
- this.messageService.add({key: "activityGrid", summary: "Command executed",
- severity: "success", detail: `Results : ${results.code} : ${results.message}`});
+ this.onSelectButton.emit({command, mode: ButtonMode.ShortPress, severity: "success"});
}, error: (err: HttpErrorResponse) => {
console.error("Error command", err);
- this.messageService.add({key: "activityGrid", summary: "Error executing command",
- severity: "error", detail: `Results : ${err.error.name} (${err.status} ${err.statusText})`});
+ this.onSelectButton.emit({command, mode: ButtonMode.ShortPress, severity: "error",
+ error: `${err.error.name} (${err.status} ${err.statusText})`});
}});
this.cdr.detectChanges();
}
+
addGridItem($event: ActivityGridItemComponent) {
const position = {x: $event.item.location.x, y: $event.item.location.y,
width: $event.item.size.width, height: $event.item.size.height};
diff --git a/src/app/controls/scrolling-text/scrolling-text.component.ts b/src/app/controls/scrolling-text/scrolling-text.component.ts
index bcbb728..1ad8b99 100644
--- a/src/app/controls/scrolling-text/scrolling-text.component.ts
+++ b/src/app/controls/scrolling-text/scrolling-text.component.ts
@@ -35,12 +35,13 @@ export class ScrollingTextComponent implements AfterViewInit {
@Input("textStyle") set _textStyle(textStyle: string | undefined)
{
this.textStyle = textStyle;
+ this.cdr.detectChanges();
this.updateClass();
}
@ViewChild("textContainer", {static: false}) textContainer: ElementRef | undefined;
@ViewChild("textContent", {static: false}) textContent: ElementRef | undefined;
- constructor(private cdr:ChangeDetectorRef) {
+ constructor(private elementRef: ElementRef, private cdr:ChangeDetectorRef) {
}
ngAfterViewInit(): void {
diff --git a/src/app/controls/slider/slider.component.css b/src/app/controls/slider/slider.component.css
index 11743e1..1ed5c6e 100644
--- a/src/app/controls/slider/slider.component.css
+++ b/src/app/controls/slider/slider.component.css
@@ -71,3 +71,10 @@
cursor: pointer;
}
+.secondary-state .p-slider .p-slider-range {
+ background: rgba(202, 202, 202, 0.8);
+}
+
+.secondary-state .p-progressbar .p-progressbar-value{
+ background: rgba(202, 202, 202, 0.8);
+}
diff --git a/src/app/controls/slider/slider.component.html b/src/app/controls/slider/slider.component.html
index f91fece..d9d1363 100644
--- a/src/app/controls/slider/slider.component.html
+++ b/src/app/controls/slider/slider.component.html
@@ -1,13 +1,14 @@
-
+
{{textValue}}
{{max}}
diff --git a/src/app/controls/slider/slider.component.ts b/src/app/controls/slider/slider.component.ts
index 6eb0ac6..d6746d2 100644
--- a/src/app/controls/slider/slider.component.ts
+++ b/src/app/controls/slider/slider.component.ts
@@ -47,6 +47,7 @@ export class SliderComponent implements OnInit {
private sliderSubject: Subject = new Subject();
private subscription = new Subscription();
@Input() max: string | undefined;
+ @Input() secondaryState = false;
constructor( private cdr:ChangeDetectorRef) { }
diff --git a/src/app/helper.ts b/src/app/helper.ts
index f76236e..3c31710 100644
--- a/src/app/helper.ts
+++ b/src/app/helper.ts
@@ -9,6 +9,7 @@ import {
Remote,
ActivityPageCommand, OrphanEntity, CommandSequence, EntityCommand, EntityCommandParameter
} from "./interfaces";
+import {MediaEntityState} from "./remote-websocket.service";
export class Helper
{
@@ -560,4 +561,20 @@ export class Helper
static setScale(scale: number) {
localStorage.setItem("scale", scale.toString());
}
+
+ static checkFeature(entity: Entity|undefined, feature: string | string[]): boolean
+ {
+ const features = (Array.isArray(feature)) ? feature as string[] : [feature];
+ return entity?.features?.find(item => features.includes(item)) !== undefined;
+ }
+
+ static getNumber(number: number) {
+ if (isNaN(number)) return 0;
+ return Math.round(number);
+ }
+
+ static isMuted(volumeEntity: MediaEntityState | undefined) {
+ if (!volumeEntity?.new_state?.attributes) return false;
+ return !!volumeEntity?.new_state?.attributes.muted;
+ }
}
diff --git a/src/app/remote-widget/remote-websocket.service.spec.ts b/src/app/remote-websocket.service.spec.ts
similarity index 100%
rename from src/app/remote-widget/remote-websocket.service.spec.ts
rename to src/app/remote-websocket.service.spec.ts
diff --git a/src/app/remote-widget/remote-websocket.service.ts b/src/app/remote-websocket.service.ts
similarity index 97%
rename from src/app/remote-widget/remote-websocket.service.ts
rename to src/app/remote-websocket.service.ts
index 94327d5..0db3c45 100644
--- a/src/app/remote-widget/remote-websocket.service.ts
+++ b/src/app/remote-websocket.service.ts
@@ -1,9 +1,9 @@
import {Injectable, OnDestroy, OnInit} from '@angular/core';
-import {ServerService} from "../server.service";
-import {EventMessage, RequestMessage, ResponseMessage, WebsocketService} from "../websocket.service";
-import {BatteryState, Entity, Remote} from "../interfaces";
+import {ServerService} from "./server.service";
+import {EventMessage, RequestMessage, ResponseMessage, WebsocketService} from "./websocket.service";
+import {BatteryState, Entity, Remote} from "./interfaces";
import {BehaviorSubject, map, Observable, Observer, share, Subject, Subscription, timer} from "rxjs";
-import {Helper} from "../helper";
+import {Helper} from "./helper";
export interface MediaEntityState
{
@@ -28,6 +28,7 @@ export interface MediaEntityState
source_list?: string[];
sound_mode?: string;
sound_mode_list?: string[];
+ muted?: boolean;
}
}
}
@@ -114,6 +115,11 @@ export class RemoteWebsocketService implements OnDestroy {
return this.websocketService.connectionStatus$;
}
+ public isRemoteConnected(): boolean
+ {
+ return this.websocketService.isRemoteConnected();
+ }
+
initWidget()
{
if (!this._mediaEntity && this._mediaEntities?.length > 0) {
diff --git a/src/app/remote-widget/remote-widget.component.html b/src/app/remote-widget/remote-widget.component.html
index 0fdf5c2..df10728 100644
--- a/src/app/remote-widget/remote-widget.component.html
+++ b/src/app/remote-widget/remote-widget.component.html
@@ -26,27 +26,25 @@
-
-
-
-
-
-
-
- {{remoteWebsocketService.getEntityName(mediaEntity)}}
-
-
- {{remoteWebsocketService.getEntityName(item)}}
-
-
-
-
-
-
-
+
+
+
+
+
+
+ {{remoteWebsocketService.getEntityName(mediaEntity)}}
+
+
+ {{remoteWebsocketService.getEntityName(item)}}
+
+
+
+
+
diff --git a/src/app/remote-widget/remote-widget.component.ts b/src/app/remote-widget/remote-widget.component.ts
index 73336c5..a94e5ef 100644
--- a/src/app/remote-widget/remote-widget.component.ts
+++ b/src/app/remote-widget/remote-widget.component.ts
@@ -16,7 +16,7 @@ import {ProgressBarModule} from "primeng/progressbar";
import {ScrollingTextComponent} from "../controls/scrolling-text/scrolling-text.component";
import {DropdownModule} from "primeng/dropdown";
import {FormsModule} from "@angular/forms";
-import {MediaEntityState, RemoteState, RemoteWebsocketService} from "./remote-websocket.service";
+import {MediaEntityState, RemoteState, RemoteWebsocketService} from "../remote-websocket.service";
import {Activity, Remote, RemoteData} from "../interfaces";
import {MediaEntityComponent} from "../active-entities/media-entity/media-entity.component";
import {DropdownOverComponent} from "../controls/dropdown-over/dropdown-over.component";
@@ -47,6 +47,9 @@ import {DropdownOverComponent} from "../controls/dropdown-over/dropdown-over.com
})
export class RemoteWidgetComponent implements OnInit {
@Input() visible = true;
+ @Input() scale = 0.8;
+ protected readonly Math = Math;
+
minimized = false;
remoteState: RemoteState | undefined;
mediaEntity: MediaEntityState | undefined;
@@ -57,6 +60,8 @@ export class RemoteWidgetComponent implements OnInit {
constructor(private server:ServerService, protected remoteWebsocketService: RemoteWebsocketService, private cdr:ChangeDetectorRef) { }
ngOnInit(): void {
+ const scale = localStorage.getItem("scale");
+ if (scale) this.scale = Number.parseFloat(scale);
this.remoteWebsocketService.onRemoteStateChange().subscribe(remoteState => {
this.remoteState = remoteState;
this.cdr.detectChanges();
@@ -114,6 +119,4 @@ export class RemoteWidgetComponent implements OnInit {
changedMediaEntity($event: any) {
this.remoteWebsocketService.mediaEntity = this.mediaEntity;
}
-
- protected readonly Math = Math;
}
diff --git a/src/app/server.service.ts b/src/app/server.service.ts
index 4510a27..6f55526 100644
--- a/src/app/server.service.ts
+++ b/src/app/server.service.ts
@@ -358,6 +358,21 @@ export class ServerService {
}))
}
+ wakeRemote(remote: Remote, broadcast?: string): Observable
+ {
+ const body: any = {}
+ if (broadcast) {
+ let httpOptions = {params: new HttpParams({fromObject: {broadcast}})};
+ return this.http.post(`/api/remote/${remote.address}/wake`, body, httpOptions).pipe(map(results => {
+ return results;
+ }))
+ }
+ else
+ return this.http.post(`/api/remote/${remote.address}/wake`, body).pipe(map(results => {
+ return results;
+ }))
+ }
+
unregisterRemote(remote: Remote): Observable
{
return this.http.delete('/api/config/remote/'+remote.address).pipe(map(results => {
diff --git a/src/app/websocket.service.ts b/src/app/websocket.service.ts
index 34e42a3..89517d1 100644
--- a/src/app/websocket.service.ts
+++ b/src/app/websocket.service.ts
@@ -2,7 +2,7 @@ import {Injectable, OnDestroy, OnInit} from '@angular/core';
import {ServerService} from "./server.service";
import {Remote} from "./interfaces";
import {webSocket, WebSocketSubject} from "rxjs/webSocket";
-import {BehaviorSubject, Observable, retry, Subject, timer} from "rxjs";
+import {BehaviorSubject, delay, Observable, retry, Subject, timer} from "rxjs";
import {distinctUntilChanged, filter, map, skip, take, tap} from "rxjs/operators";
export interface Message
@@ -76,6 +76,11 @@ export class WebsocketService implements OnDestroy {
return this.remoteChanged$;
}
+ isRemoteConnected() : boolean
+ {
+ return this.status$.getValue();
+ }
+
getMessageEvent(): Subject
{
@@ -139,6 +144,7 @@ export class WebsocketService implements OnDestroy {
console.debug("Websocket disconnect, reconnecting...");
this.initWebsocket();
}),
+ delay(this.reconnecInterval)
).subscribe();
}