Skip to content

Commit

Permalink
rename mouse actions to drag actions, rename non universal remote mou…
Browse files Browse the repository at this point in the history
…sepad default keys to dragpad and add dragpad to universal remote, add faster multi drag action to drag pads
  • Loading branch information
Nerwyn committed Dec 11, 2024
1 parent 2e83a09 commit e75f3a1
Show file tree
Hide file tree
Showing 16 changed files with 215 additions and 106 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ A super customizable universal remote card iterating on the work of several othe
- Keyboard and search dialog actions for most platforms.
- [Template](#a-note-on-templating) support for almost all fields using nunjucks.
- Toggleable haptics.
- Remappable touchpad with [multi-touch and mouse](#touchpad-actions) gesture support.
- Remappable touchpad with [momentary, multi-touch, and drag](#touchpad-actions) gesture support.
- Remappable slider with vertical orientation support.
- User configurable remote [layout](#layout).
- Icons and labels for all elements.
Expand Down Expand Up @@ -186,7 +186,8 @@ The default keys and sources lists for your selected platform are displayed belo
| Name | Type | Description |
| ------------------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| touchpad | touchpad | A touchpad for swipe navigation. |
| mousepad | touchpad | A touchpad for mouse navigation. |
| dragpad | touchpad | A touchpad for drag navigation. Use two fingers for faster movement. |
| mousepad | touchpad | A touchpad for mouse navigation. **NOTE**: mousepad support is dependent on the platform supporting mouse movement via a Home Assistant action. |
| slider | slider | A slider that controls the volume of the entity defined by `media_player_id`. **NOTE**: Volume slider support is dependent on the media player supporting the `media_player.volume_set` action. |
| volume_buttons | button rows | Shorthand to generate a set of volume down, volume mute, and volume up buttons in a row or column. |
| navigation_buttons | button rows | Shorthand to generate a set of up, down, left, right, and center buttons across three rows within a column. |
Expand Down Expand Up @@ -291,7 +292,7 @@ Almost all fields support nunjucks templating. Nunjucks is a templating engine f

You can include the current value of a remote element and it's units by using the variables `value` and `unit` in a label template. You can also include `hold_secs` in a template if performing a momentary end action. Each remote element can also reference it's configuration using `config` within templates. `config.entity` and `config.attribute` will return the remote element's entity ID and attribute with their templates rendered (if they have them), and other templated config fields can be rendered within templates by wrapping them in the function `render` within a template. You can access the entire card config in a template via `config.card`, and global values such as remote ID within that like `config.card.remote_id`. Note that default values for some fields are not actually in the config and will not appear in templates, and you have to default to them using "or", like `config.card.platform or 'Android TV'`.

You can include touch location information in your templates using the values `initialX`, `initialY`, `currentX`, `currentY`, `deltaX`, and `deltaY` This is especially useful when using mouse interactions on the touchpad, like with the Unified Remote default mousepad.
You can include touch location information in your templates using the values `initialX`, `initialY`, `currentX`, `currentY`, `deltaX`, and `deltaY` This is especially useful when using drag interactions on the touchpad, like with the Unified Remote default mousepad or as a dragpad on all platforms.

## Interactions

Expand Down Expand Up @@ -354,7 +355,7 @@ The touchpad's center acts like a button, with support for the same actions. The

Touchpads also support multi-touch mode, which fires alternate actions when more than one finger is used with it. This mode is disabled by default but can be enabled by setting a touchpad's multi-touch actions to something other than `Nothing`. Multi-touch mode supports center tap, double tap, and hold actions, and direction swipe and hold actions.

Touchpads also support an alternate mouse mode. This action is called whenever movement is detected on the mousepad, and works best with mouse movement actions like Unified Remote's `Relmtech.Basic Input delta`. The mouse X and Y movement can be added to actions using templates using `deltaX` and `deltaY`. Because this action fires every time movement is detected on the touchpad, you may find that it fires too often, or not often enough. You can either use math to modify the values of `deltaX` and `deltaY` within the action data templates, or introduce a delay in which movement will be ignored after a mouse action is fired using the configuration UI option `Sampling delay` to tweak the speed of your mouse movements and action fire rate. The mouse action can also be used in multi-touch mode. Enabling this action disables directional actions.
Touchpads also support an alternate drag mode. This action is called whenever movement is detected on the touchpad, and works best with mouse movement actions like Unified Remote's `Relmtech.Basic Input delta`. The touchpad X and Y movement can be added to actions using templates using `deltaX` and `deltaY`. Because this action fires every time movement is detected on the touchpad, you may find that it fires too often, or not often enough. You can either use math to modify the values of `deltaX` and `deltaY` within the action data templates, or introduce a delay in which movement will be ignored after a drag action is fired using the configuration UI option `Sampling delay` to tweak the speed of your drag movements and action fire rate. The drag action can also be used in multi-touch mode. Enabling this action disables directional actions.

### Keyboard, Textbox, and Search

Expand Down
6 changes: 3 additions & 3 deletions dist/universal-remote-card.min.js

Large diffs are not rendered by default.

14 changes: 9 additions & 5 deletions src/classes/base-remote-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ export class BaseRemoteElement extends LitElement {
sendAction(actionType: ActionType, config: IActions = this.config) {
let action;
switch (actionType) {
case 'mouse_action':
action = config.mouse_action;
case 'drag_action':
action = config.drag_action;
break;
case 'multi_mouse_action':
action = config.multi_mouse_action ?? config.mouse_action;
case 'multi_drag_action':
action = config.multi_drag_action ?? config.drag_action;
break;
case 'momentary_start_action':
action = config.momentary_start_action;
Expand Down Expand Up @@ -184,6 +184,8 @@ export class BaseRemoteElement extends LitElement {

key(action: IAction, actionType: ActionType) {
switch (action.platform) {
case 'Unified Remote':
break;
case 'Kodi':
this.hass.callService('kodi', 'call_method', {
entity_id: action.media_player_id,
Expand All @@ -209,7 +211,7 @@ export class BaseRemoteElement extends LitElement {
command: action.key ?? '',
};
if (
actionType == 'hold_action' &&
actionType.includes('hold_action') &&
(!this.config.hold_action ||
this.config.hold_action.action == 'none')
) {
Expand All @@ -223,6 +225,8 @@ export class BaseRemoteElement extends LitElement {

source(action: IAction) {
switch (action.platform) {
case 'Unified Remote':
break;
case 'Fire TV':
case 'Roku':
case 'Kodi':
Expand Down
16 changes: 8 additions & 8 deletions src/classes/remote-touchpad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class RemoteTouchpad extends BaseRemoteElement {
holdStart: boolean = false;
holdMove: boolean = false;
direction?: DirectionAction;
fireMouseAction: boolean = true;
fireDragAction: boolean = true;

onClick(e: TouchEvent | MouseEvent) {
e.stopImmediatePropagation();
Expand Down Expand Up @@ -166,31 +166,31 @@ export class RemoteTouchpad extends BaseRemoteElement {
const totalDeltaY = (this.currentY ?? 0) - this.initialY;
if (
this.renderTemplate(
this.config[`${multiPrefix}mouse_action`]?.action ?? 'none',
this.config[`${multiPrefix}drag_action`]?.action ?? 'none',
) != 'none'
) {
// Mouse actions
// Drag actions
if (
this.holdMove ||
Math.abs(Math.abs(totalDeltaX) - Math.abs(totalDeltaY)) > 1
) {
if (this.fireMouseAction) {
if (this.fireDragAction) {
clearTimeout(this.holdTimer);
this.holdTimer = undefined;
this.holdMove = true;

const repeatDelay = this.renderTemplate(
this.config[`${multiPrefix}mouse_action`]
this.config[`${multiPrefix}drag_action`]
?.repeat_delay ?? 0, // default to 0 instead of normal repeat delay
) as number;
if (repeatDelay) {
this.fireMouseAction = false;
this.fireDragAction = false;
setTimeout(() => {
this.fireMouseAction = true;
this.fireDragAction = true;
}, repeatDelay);
}

this.sendAction(`${multiPrefix}mouse_action`);
this.sendAction(`${multiPrefix}drag_action`);
}
}
} else {
Expand Down
12 changes: 6 additions & 6 deletions src/models/interfaces/IActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export const ActionTypes = [
'multi_double_tap_action',
'momentary_start_action',
'momentary_end_action',
'mouse_action',
'multi_mouse_action',
'drag_action',
'multi_drag_action',
] as const;
export type ActionType = (typeof ActionTypes)[number];

Expand Down Expand Up @@ -110,7 +110,7 @@ export interface IActions
extends IBasicActions,
IMomentaryActions,
IMultiActions,
IMouseActions {}
IDragActions {}

export interface IBasicActions {
tap_action?: IAction;
Expand All @@ -129,7 +129,7 @@ export interface IMomentaryActions {
momentary_end_action?: IAction;
}

export interface IMouseActions {
mouse_action?: IAction;
multi_mouse_action?: IAction;
export interface IDragActions {
drag_action?: IAction;
multi_drag_action?: IAction;
}
11 changes: 8 additions & 3 deletions src/models/maps/android_tv/defaultKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,21 +145,26 @@ export const androidTVDefaultKeys: IElementConfig[] = [
},
{
type: 'touchpad',
name: 'mousepad',
name: 'dragpad',
tap_action: {
action: 'key',
key: 'DPAD_CENTER',
},
mouse_action: {
drag_action: {
action: 'key',
key: 'DPAD_{{ ("RIGHT" if deltaX > 0 else "LEFT") if (deltaX | abs) > (deltaY | abs) else ("DOWN" if deltaY > 0 else "UP") }}',
repeat_delay: 100,
},
multi_drag_action: {
action: 'key',
key: 'DPAD_{{ ("RIGHT" if deltaX > 0 else "LEFT") if (deltaX | abs) > (deltaY | abs) else ("DOWN" if deltaY > 0 else "UP") }}',
repeat_delay: 50,
},
up: {},
down: {},
left: {},
right: {},
icon: 'mdi:mouse',
icon: 'mdi:drag-variant',
},
{
type: 'button',
Expand Down
11 changes: 8 additions & 3 deletions src/models/maps/apple_tv/defaultKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,21 +168,26 @@ export const appleTVDefaultKeys: IElementConfig[] = [
},
{
type: 'touchpad',
name: 'mousepad',
name: 'dragpad',
tap_action: {
action: 'key',
key: 'select',
},
mouse_action: {
drag_action: {
action: 'key',
key: '{{ ("right" if deltaX > 0 else "left") if (deltaX | abs) > (deltaY | abs) else ("down" if deltaY > 0 else "up") }}',
repeat_delay: 100,
},
multi_drag_action: {
action: 'key',
key: '{{ ("right" if deltaX > 0 else "left") if (deltaX | abs) > (deltaY | abs) else ("down" if deltaY > 0 else "up") }}',
repeat_delay: 50,
},
up: {},
down: {},
left: {},
right: {},
icon: 'mdi:mouse',
icon: 'mdi:drag-variant',
},
{
type: 'button',
Expand Down
11 changes: 8 additions & 3 deletions src/models/maps/bravia/defaultKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,21 +140,26 @@ export const braviaTVDefaultKeys: IElementConfig[] = [
},
{
type: 'touchpad',
name: 'mousepad',
name: 'dragpad',
tap_action: {
action: 'key',
key: 'Confirm',
},
mouse_action: {
drag_action: {
action: 'key',
key: '{{ ("Right" if deltaX > 0 else "Left") if (deltaX | abs) > (deltaY | abs) else ("Down" if deltaY > 0 else "Up") }}',
repeat_delay: 100,
},
multi_drag_action: {
action: 'key',
key: '{{ ("Right" if deltaX > 0 else "Left") if (deltaX | abs) > (deltaY | abs) else ("Down" if deltaY > 0 else "Up") }}',
repeat_delay: 50,
},
up: {},
down: {},
left: {},
right: {},
icon: 'mdi:mouse',
icon: 'mdi:drag-variant',
},
{
type: 'button',
Expand Down
11 changes: 8 additions & 3 deletions src/models/maps/fire_tv/defaultKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,21 +173,26 @@ export const fireTVDefaultKeys: IElementConfig[] = [
},
{
type: 'touchpad',
name: 'mousepad',
name: 'dragpad',
tap_action: {
action: 'key',
key: 'CENTER',
},
mouse_action: {
drag_action: {
action: 'key',
key: '{{ ("RIGHT" if deltaX > 0 else "LEFT") if (deltaX | abs) > (deltaY | abs) else ("DOWN" if deltaY > 0 else "UP") }}',
repeat_delay: 100,
},
multi_drag_action: {
action: 'key',
key: '{{ ("RIGHT" if deltaX > 0 else "LEFT") if (deltaX | abs) > (deltaY | abs) else ("DOWN" if deltaY > 0 else "UP") }}',
repeat_delay: 50,
},
up: {},
down: {},
left: {},
right: {},
icon: 'mdi:mouse',
icon: 'mdi:drag-variant',
},
{
type: 'button',
Expand Down
11 changes: 8 additions & 3 deletions src/models/maps/jellyfin/defaultKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,21 +137,26 @@ export const jellyfinTVDefaultKeys: IElementConfig[] = [
},
{
type: 'touchpad',
name: 'mousepad',
name: 'dragpad',
tap_action: {
action: 'key',
key: 'Select',
},
mouse_action: {
drag_action: {
action: 'key',
key: '{{ ("MoveRight" if deltaX > 0 else "MoveLeft") if (deltaX | abs) > (deltaY | abs) else ("MoveDown" if deltaY > 0 else "MoveUp") }}',
repeat_delay: 100,
},
multi_drag_action: {
action: 'key',
key: '{{ ("MoveRight" if deltaX > 0 else "MoveLeft") if (deltaX | abs) > (deltaY | abs) else ("MoveDown" if deltaY > 0 else "MoveUp") }}',
repeat_delay: 50,
},
up: {},
down: {},
left: {},
right: {},
icon: 'mdi:mouse',
icon: 'mdi:drag-variant',
},
{
type: 'button',
Expand Down
11 changes: 8 additions & 3 deletions src/models/maps/kodi/defaultKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,21 +189,26 @@ export const kodiDefaultKeys: IElementConfig[] = [
},
{
type: 'touchpad',
name: 'mousepad',
name: 'dragpad',
tap_action: {
action: 'key',
key: 'Input.Select',
},
mouse_action: {
drag_action: {
action: 'key',
key: 'Input.{{ ("Right" if deltaX > 0 else "Left") if (deltaX | abs) > (deltaY | abs) else ("Down" if deltaY > 0 else "Up") }}',
repeat_delay: 100,
},
multi_drag_action: {
action: 'key',
key: 'Input.{{ ("Right" if deltaX > 0 else "Left") if (deltaX | abs) > (deltaY | abs) else ("Down" if deltaY > 0 else "Up") }}',
repeat_delay: 50,
},
up: {},
down: {},
left: {},
right: {},
icon: 'mdi:mouse',
icon: 'mdi:drag-variant',
},
{
type: 'button',
Expand Down
11 changes: 8 additions & 3 deletions src/models/maps/roku/defaultKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,21 +131,26 @@ export const rokuDefaultKeys: IElementConfig[] = [
},
{
type: 'touchpad',
name: 'mousepad',
name: 'dragpad',
tap_action: {
action: 'key',
key: 'select',
},
mouse_action: {
drag_action: {
action: 'key',
key: '{{ ("right" if deltaX > 0 else "left") if (deltaX | abs) > (deltaY | abs) else ("down" if deltaY > 0 else "up") }}',
repeat_delay: 100,
},
multi_drag_action: {
action: 'key',
key: '{{ ("right" if deltaX > 0 else "left") if (deltaX | abs) > (deltaY | abs) else ("down" if deltaY > 0 else "up") }}',
repeat_delay: 50,
},
up: {},
down: {},
left: {},
right: {},
icon: 'mdi:mouse',
icon: 'mdi:drag-variant',
},
{
type: 'button',
Expand Down
11 changes: 8 additions & 3 deletions src/models/maps/samsung_tv/defaultKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,21 +155,26 @@ export const samsungTVDefaultKeys: IElementConfig[] = [
},
{
type: 'touchpad',
name: 'mousepad',
name: 'dragpad',
tap_action: {
action: 'key',
key: 'KEY_ENTER',
},
mouse_action: {
drag_action: {
action: 'key',
key: 'KEY_{{ ("RIGHT" if deltaX > 0 else "LEFT") if (deltaX | abs) > (deltaY | abs) else ("DOWN" if deltaY > 0 else "UP") }}',
repeat_delay: 100,
},
multi_drag_action: {
action: 'key',
key: 'KEY_{{ ("RIGHT" if deltaX > 0 else "LEFT") if (deltaX | abs) > (deltaY | abs) else ("DOWN" if deltaY > 0 else "UP") }}',
repeat_delay: 50,
},
up: {},
down: {},
left: {},
right: {},
icon: 'mdi:mouse',
icon: 'mdi:drag-variant',
},
{
type: 'button',
Expand Down
Loading

0 comments on commit e75f3a1

Please sign in to comment.