Skip to content

Commit

Permalink
Handle long press from web browser on virtual remote
Browse files Browse the repository at this point in the history
  • Loading branch information
albaintor committed Oct 5, 2024
1 parent 5637fbd commit ba74fc3
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 79 deletions.
14 changes: 14 additions & 0 deletions src/app/active-entities/active-entities.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,17 @@
height: 400px !important;
max-height: 600px !important;
}

.message-panel .p-message .p-message-wrapper {
padding: 0.1rem 0.1rem;
}

.message-panel .p-message .p-message-close {
width: 0.9rem;
height: 0.9rem;


.message-panel .p-message .p-message-icon {
font-size: 0.9rem;
margin-right: 0.15rem;
}}
3 changes: 2 additions & 1 deletion src/app/active-entities/active-entities.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<p-tag [value]="(remoteWebsocketService.connectionStatus | async) ? 'Connected' : 'Disconnected'"
[severity]="(remoteWebsocketService.connectionStatus | async) ? 'success' : 'warning'"/>
</div>
<p-messages *ngIf="messages.length > 0" class="message-panel" [(value)]="messages" [enableService]="false" showTransitionOptions="0ms" hideTransitionOptions="0ms"/>
</div>
<div class="flex flex-wrap gap-3">
<div class="flex gap-2 align-content-center justify-content-center media-card-border"
Expand All @@ -63,5 +64,5 @@
</div>
</div>
<app-activity-player *ngFor="let activity of selectedActivities" [remote]="selectedRemote" [activity]="activity" [visible]="true"
(onClose)="removeActivity($event)" [scale]="scale"/>
(onClose)="removeActivity($event)" [scale]="scale" (onMessage)="handleMessage($event)"/>

12 changes: 10 additions & 2 deletions src/app/active-entities/active-entities.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewEncapsulation} from '@angular/core';
import {DropdownModule} from "primeng/dropdown";
import {AsyncPipe, NgForOf, NgIf} from "@angular/common";
import {MenuItem, PrimeTemplate} from "primeng/api";
import {MenuItem, Message, PrimeTemplate} from "primeng/api";
import {ProgressBarModule} from "primeng/progressbar";
import {ScrollingTextComponent} from "../controls/scrolling-text/scrolling-text.component";
import {TagModule} from "primeng/tag";
Expand All @@ -18,6 +18,7 @@ import {MediaEntityComponent} from "./media-entity/media-entity.component";
import {AutoCompleteCompleteEvent, AutoCompleteModule} from "primeng/autocomplete";
import {ActivityPlayerComponent} from "../activity-player/activity-player.component";
import {InputNumberModule} from "primeng/inputnumber";
import {MessagesModule} from "primeng/messages";

@Component({
selector: 'app-active-entities',
Expand All @@ -39,7 +40,8 @@ import {InputNumberModule} from "primeng/inputnumber";
MediaEntityComponent,
AutoCompleteModule,
ActivityPlayerComponent,
InputNumberModule
InputNumberModule,
MessagesModule
],
templateUrl: './active-entities.component.html',
styleUrl: './active-entities.component.css',
Expand All @@ -64,6 +66,7 @@ export class ActiveEntitiesComponent implements OnInit {
protected readonly Helper = Helper;
newActivity: Activity | undefined;
scale = 0.8;
messages: Message[] = [];

constructor(private server:ServerService, protected remoteWebsocketService: RemoteWebsocketService, private cdr:ChangeDetectorRef) { }

Expand Down Expand Up @@ -197,4 +200,9 @@ export class ActiveEntitiesComponent implements OnInit {

this.cdr.detectChanges();
}

handleMessage($event: Message) {
this.messages = [$event];
this.cdr.detectChanges();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ export class ButtonEditorComponent {
executeCommand(command: Command) {
if (!this.remote) return;
this.server.executeRemotetCommand(this.remote, command).subscribe(results => {
this.messageService.add({key: "remoteButton", summary: "Command executed",
severity: "success", detail: `Results : ${results.code} : ${results.message}`});
// this.messageService.add({key: "remoteButton", summary: "Command executed",
// severity: "success", detail: `Results : ${results.code} : ${results.message}`});
});
this.cdr.detectChanges();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ export class UiCommandEditorComponent {
executeCommand(command: string | Command) {
if (!this.remote || typeof command === 'string') return;
this.server.executeRemotetCommand(this.remote, command).subscribe(results => {
this.messageService.add({key: "remoteCommand", summary: "Command executed",
severity: "success", detail: `Results : ${results.code} : ${results.message}`});
// this.messageService.add({key: "remoteCommand", summary: "Command executed",
// severity: "success", detail: `Results : ${results.code} : ${results.message}`});
});
this.cdr.detectChanges();
}
Expand Down
20 changes: 11 additions & 9 deletions src/app/activity-player/activity-player.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@
contentStyleClass="widget-dialog" class="widget" styleClass="widget-header" appendTo="body"
(close)="closeDialog($event);dialog.close($event)" [style]="{'width': (scale*400+30)+'px', 'max-height': 'calc(100vh - 20px)'}">
<ng-template pTemplate="header">
<div [style]="'position: absolute;right:0; top:0;scale:'+scale">
<p-button icon="pi pi-times" pTooltip="Close window" (click)="closeDialog($event)" [rounded]="true" [outlined]="true"/>
</div>
<div class="flex align-items-start justify-content-center"
[style]="{width: 400*scale+'px', height: 50*scale+'px'}"></div>
<div [style]="'position: absolute;top:5px;left:0;right:0;text-align: center;transform-origin: top;scale:'+scale*1.2">
[style]="{width: (400*scale+30)+'px', height: 50*scale+'px'}"></div>
<div [style]="'position: absolute;top:5px;left:0;right:0;transform-origin: top;scale:'+scale*1.2">
<div class="flex justify-content-between gap-2 column-gap-2" style="width: 100%">
<div class="flex align-items-center justify-content-center" >
<p-button icon="pi pi-window-minimize" pTooltip="Minimize" (click)="minimized = !minimized"/>
</div>
<div class="flex flex-grow-1 align-items-center justify-content-center">
<h3>Activity {{Helper.getEntityName(activity)}}</h3>
<div class="flex flex-grow-1">
<app-icon *ngIf="remote && activity?.icon" [remote]="remote" [icon]="activity!.icon" [size]="50"
style="pointer-events: none"/>&nbsp;
<h3>{{Helper.getEntityName(activity)}}</h3>
</div>
</div>

</div>
<div [style]="'position: absolute;right:0; top:0;scale:'+scale">
<p-button icon="pi pi-times" pTooltip="Close window" (click)="closeDialog($event)" [rounded]="true" [outlined]="true"/>
</div>

</ng-template>
Expand All @@ -29,7 +30,8 @@ <h3>Activity {{Helper.getEntityName(activity)}}</h3>
<p-button icon="pi pi-cog" [rounded]="true" pTooltip="Edit activity" [routerLink]="'/activity/edit/'+activity?.entity_id" />
</div>
<ng-container *ngIf="!minimized">
<app-activity-buttons [remote]="remote" [activity]="activity" [editMode]="false" [scale]="scale" [hideButtonsInfo]="true"/>
<app-activity-buttons [remote]="remote" [activity]="activity" [editMode]="false" [scale]="scale" [hideButtonsInfo]="true"
(onSelectButton)="handleMessage($event)"/>
<div style="position: relative">
<app-activity-grid [activity]="activity" [editMode]="false" [remote]="remote" [width]="400*scale" [height]="500*scale"
[selectionMode]="false" [currentPage]="currentPage" [runMode]="true"/>
Expand Down
21 changes: 17 additions & 4 deletions src/app/activity-player/activity-player.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import {
ViewEncapsulation
} from '@angular/core';
import {DialogModule} from "primeng/dialog";
import {MessageService, PrimeTemplate} from "primeng/api";
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, EntityCommand, Remote, UIPage} from "../interfaces";
import {Activity, ButtonMapping, EntityCommand, Remote, UIPage} from "../interfaces";
import {Helper} from "../helper";
import {Button} from "primeng/button";
import {TooltipModule} from "primeng/tooltip";
import {ActivityButtonsComponent} from "../activity-viewer/activity-buttons/activity-buttons.component";
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 {ActivityGridComponent} from "../activity-viewer/activity-grid/activity-grid.component";
Expand All @@ -25,6 +25,7 @@ import {HttpErrorResponse} from "@angular/common/http";
import {ProgressBarModule} from "primeng/progressbar";
import {PaginationComponent} from "../controls/pagination/pagination.component";
import {RouterLink} from "@angular/router";
import {IconComponent} from "../controls/icon/icon.component";

@Component({
selector: 'app-activity-player',
Expand All @@ -41,7 +42,8 @@ import {RouterLink} from "@angular/router";
ToastModule,
ProgressBarModule,
PaginationComponent,
RouterLink
RouterLink,
IconComponent
],
templateUrl: './activity-player.component.html',
styleUrl: './activity-player.component.css',
Expand Down Expand Up @@ -69,6 +71,7 @@ export class ActivityPlayerComponent {
@Input() visible = false;
@Input() scale = 0.7;
@Output() onClose: EventEmitter<ActivityPlayerComponent> = new EventEmitter();
@Output() onMessage: EventEmitter<Message> = new EventEmitter();
minimized = false;
currentPage: UIPage | undefined;
progress = 0;
Expand Down Expand Up @@ -155,4 +158,14 @@ export class ActivityPlayerComponent {
this.currentPage = this.activity?.options?.user_interface?.pages?.[$event];
this.cdr.detectChanges();
}

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}`;
if ($event.error)
message = `${message} : ${$event.error}`;
this.onMessage.emit({severity: $event.severity, detail: message});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<div class="flex align-items-start justify-content-center" *ngIf="getRemoteModel()?.model == 'UCR2'"
[style]="'position: absolute;top:0;left:0;right:0;text-align: center;transform-origin: top;scale:'+scale">
<app-image-map image="assets/remote/remote-two.png" [imageSize]="{width: 400, height: 400}" (overElement)="buttonOver($event)"
(mouseLongPress)="selectButton($event, true)"
(clickElement)="selectButton($event)" [selectedTags]="mappedButtons" [imageTemplate]="r2Areas">
<ng-template #r2Areas>
<area target="" alt="Volume +" title="Volume +" href="#" data-tag="volumeup" coords="5,87,83,163" shape="rect">
Expand Down Expand Up @@ -78,15 +79,15 @@ <h3>{{mouseOverButtonName!}}</h3>

<ng-template let-button="button" #buttonTemplate>
<ng-container *ngIf="button.short_press">
<div class="col-3 button-action" (click)="executeCommand(button.short_press)">
<div class="col-3 button-action" (click)="executeCommand(button, ButtonMode.ShortPress)">
<p-tag severity="success" value="Short press"/>
</div>
<div class="col-3 button-action" (click)="executeCommand(button.short_press)">
<div class="col-3 button-action" (click)="executeCommand(button, ButtonMode.ShortPress)">
<p-chip [label]="getEntityName(button.short_press.entity_id)"
[style]="Helper.getStyle(Helper.getEntityName(button.short_press.entity_id))"
[pTooltip]="button.short_press.entity_id"></p-chip>&nbsp;
</div>
<div class="col-3 button-action" (click)="executeCommand(button.short_press)">
<div class="col-3 button-action" (click)="executeCommand(button, ButtonMode.ShortPress)">
<p-tag [value]="Helper.getCommandName(button.short_press, configEntityCommands)" [pTooltip]="button.short_press.cmd_id"
severity="secondary"></p-tag>
</div>
Expand All @@ -102,15 +103,15 @@ <h3>{{mouseOverButtonName!}}</h3>
</div>
</ng-container>
<ng-container *ngIf="button && button.long_press">
<div class="col-3 button-action" (click)="executeCommand(button.long_press)">
<div class="col-3 button-action" (click)="executeCommand(button, ButtonMode.LongPress)">
<p-tag severity="warning" value="Long press"/>
</div>
<div class="col-3 button-action" (click)="executeCommand(button.long_press)">
<div class="col-3 button-action" (click)="executeCommand(button, ButtonMode.LongPress)">
<p-chip [label]="getEntityName(button.long_press.entity_id)"
[style]="Helper.getStyle(Helper.getEntityName(button.long_press.entity_id))"
[pTooltip]="button.long_press.entity_id"></p-chip>&nbsp;
</div>
<div class="col-3 button-action" (click)="executeCommand(button.long_press)">
<div class="col-3 button-action" (click)="executeCommand(button, ButtonMode.LongPress)">
<p-tag [value]="Helper.getCommandName(button.long_press, configEntityCommands)" [pTooltip]="button.long_press.cmd_id"
severity="secondary"></p-tag>
</div>
Expand All @@ -126,15 +127,15 @@ <h3>{{mouseOverButtonName!}}</h3>
</div>
</ng-container>
<ng-container *ngIf="button && button.double_press">
<div class="col-3 button-action" (click)="executeCommand(button.double_press)">
<div class="col-3 button-action" (click)="executeCommand(button, ButtonMode.DoublePress)">
<p-tag severity="danger" value="Double press"/>
</div>
<div class="col-3 button-action" (click)="executeCommand(button.double_press)">
<div class="col-3 button-action" (click)="executeCommand(button, ButtonMode.DoublePress)">
<p-chip [label]="getEntityName(button.double_press.entity_id)"
[style]="Helper.getStyle(Helper.getEntityName(button.double_press.entity_id))"
[pTooltip]="button.double_press.entity_id"></p-chip>&nbsp;
</div>
<div class="col-3 button-action" (click)="executeCommand(button.double_press)">
<div class="col-3 button-action" (click)="executeCommand(button, ButtonMode.DoublePress)">
<p-tag [value]="Helper.getCommandName(button.double_press, configEntityCommands)" [pTooltip]="button.double_press.cmd_id"
severity="secondary"></p-tag>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component, ElementRef, EventEmitter,
Component, EventEmitter,
Input, Output, ViewChild,
ViewEncapsulation
} from '@angular/core';
Expand All @@ -14,23 +14,25 @@ import {NgForOf, NgIf, NgTemplateOutlet} from "@angular/common";
import {
Activity,
ButtonMapping,
Command,
EntityCommand,
EntityCommandParameter,
Remote, RemoteData,
RemoteModel, RemoteModels, RemoteVersion,
ScreenLayout
} from "../../interfaces";
import {ServerService} from "../../server.service";
import {ImageMapComponent, MapElement} from "../../image-map/image-map.component";
import {HttpErrorResponse} from "@angular/common/http";
import {MessageService} from "primeng/api";
import {ToastModule} from "primeng/toast";
import {ButtonEditorComponent} from "../../activity-editor/button-editor/button-editor.component";
import {MediaEntityState} from "../../remote-widget/remote-websocket.service";
import {IconComponent} from "../../controls/icon/icon.component";
import {OverlayPanel, OverlayPanelModule} from "primeng/overlaypanel";

export enum ButtonMode {
ShortPress,
LongPress,
DoublePress
}

@Component({
selector: 'app-activity-buttons',
standalone: true,
Expand Down Expand Up @@ -88,7 +90,8 @@ export class ActivityButtonsComponent implements AfterViewInit {
buttonsMap:{ [id: string]: string } = {};
reversedButtonMap:{ [id: string]: string } = {};
mappedButtons: string[] | undefined;
@Output() onSelectButton: EventEmitter<ButtonMapping> = new EventEmitter();
@Output() onSelectButton: EventEmitter<{button: ButtonMapping, mode: ButtonMode, severity: "success" | "error",
error?: string}> = new EventEmitter();
@Input() hideButtonsInfo = false;
executeButton: ButtonMapping | undefined;
@ViewChild("executeButtonPanel") executeButtonPanel: OverlayPanel | undefined;
Expand Down Expand Up @@ -116,15 +119,16 @@ export class ActivityButtonsComponent implements AfterViewInit {
ngAfterViewInit(): void {
}

executeCommand(command: Command) {
if (!this.remote) return;
executeCommand(button: ButtonMapping, mode: ButtonMode) {
const command = (mode === ButtonMode.ShortPress) ? button.short_press : (mode === ButtonMode.LongPress) ? button.long_press : button.double_press;
if (!this.remote || !command) return;
this.server.executeRemotetCommand(this.remote, command).subscribe({next: results => {
this.onSelectButton.emit({button, mode, severity: "success"});
// this.messageService.add({key: "activityButtons", summary: "Command executed",
// severity: "success", detail: `Results : ${results.code} : ${results.message}`});
}, error: (err: HttpErrorResponse) => {
console.error("Error command", err);
this.messageService.add({key: "activityButtons", summary: "Error executing command",
severity: "error", detail: `Results : ${err.error.name} (${err.status} ${err.statusText})`});
this.onSelectButton.emit({button, mode, severity: "error", error: `${err.error.name} (${err.status} ${err.statusText})`});
}});
this.cdr.detectChanges();
}
Expand All @@ -139,20 +143,34 @@ export class ActivityButtonsComponent implements AfterViewInit {
this.cdr.detectChanges();
}

selectButton($event: MapElement) {
selectButton($event: MapElement, longPress = false) {
if (!$event.tag) return;
const buttonId = $event.tag;
const button = this.activity?.options?.button_mapping?.find(button => button.button === this.buttonsMap[buttonId]);
if (!this.editMode && button?.short_press)
{//executeButtonPanel
const commands = (button?.short_press ? 1 : 0) + (button?.long_press ? 1 : 0) + (button?.double_press ? 1 : 0);
if (commands == 1)
this.executeCommand(button.short_press);
else if (commands > 1)
if (!this.editMode)
{
if (longPress)
{
this.executeButton = button;
this.executeButtonPanel?.show($event.event, $event.event.target);
this.cdr.detectChanges();
if (button?.long_press) {
this.executeCommand(button, ButtonMode.LongPress);
}
else if (button?.double_press) {
this.executeCommand(button, ButtonMode.DoublePress);
}
else if (button?.short_press) {
this.executeCommand(button, ButtonMode.ShortPress);
}
}
else {
if (button?.short_press) {
this.executeCommand(button, ButtonMode.ShortPress);
}
else if (button?.long_press) {
this.executeCommand(button, ButtonMode.LongPress);
}
else if (button?.double_press) {
this.executeCommand(button, ButtonMode.DoublePress);
}
}
return;
}
Expand Down Expand Up @@ -189,4 +207,6 @@ export class ActivityButtonsComponent implements AfterViewInit {
this.updateButtons();
this.cdr.detectChanges();
}

protected readonly ButtonMode = ButtonMode;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
}

.grid-item-run {
padding: 5px;
padding: 1px;
text-align: center;
cursor: pointer;
width: 100%;
Expand Down
Loading

0 comments on commit ba74fc3

Please sign in to comment.