Skip to content

Commit f4e4f6c

Browse files
feat: add page-switcher functionality to sub-actions with page input
1 parent abdedcf commit f4e4f6c

1 file changed

Lines changed: 43 additions & 22 deletions

File tree

src/App.jsx

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ function OpenAppEditor({ target, mode, onChange }) {
678678
}
679679

680680
// ─── Sub-Action Row ─────────────────────────────────────────
681-
function SubActionRow({ subAction, onChange, onRemove }) {
681+
function SubActionRow({ subAction, onChange, onRemove, pageCount = 1 }) {
682682
const label = SUB_ACTION_TYPES.find(t => t.id === subAction.type)?.name ?? subAction.type
683683
return (
684684
<div className="sub-action-row">
@@ -737,6 +737,21 @@ function SubActionRow({ subAction, onChange, onRemove }) {
737737
<span className="delay-unit">ms</span>
738738
</div>
739739
)}
740+
{subAction.type === 'page-switcher' && (
741+
<div className="delay-input-row">
742+
<label className="prop-label">Page</label>
743+
<input
744+
className="prop-input"
745+
type="number"
746+
min="1"
747+
max={pageCount}
748+
step="1"
749+
value={(subAction.targetPage ?? 0) + 1}
750+
onChange={e => onChange({ ...subAction, targetPage: Math.max(0, Math.min(pageCount - 1, Number(e.target.value) - 1)) })}
751+
/>
752+
<span className="delay-unit">/ {pageCount}</span>
753+
</div>
754+
)}
740755
{subAction.type === 'sleep-toggle' && (
741756
<p className="action-hint">Puts the deck to sleep.</p>
742757
)}
@@ -746,7 +761,7 @@ function SubActionRow({ subAction, onChange, onRemove }) {
746761
}
747762

748763
// ─── Multi Action Editor ─────────────────────────────────────
749-
function MultiActionEditor({ actions, onChange }) {
764+
function MultiActionEditor({ actions, onChange, pageCount = 1 }) {
750765
const [addingNew, setAddingNew] = useState(false)
751766

752767
const addSubAction = (type) => {
@@ -772,6 +787,7 @@ function MultiActionEditor({ actions, onChange }) {
772787
subAction={sub}
773788
onChange={updated => updateAt(i, updated)}
774789
onRemove={() => removeAt(i)}
790+
pageCount={pageCount}
775791
/>
776792
))}
777793

@@ -802,21 +818,23 @@ const ENABLED_ACTIONS = new Set(['hotkey', 'open-app', 'open-url', 'run-cmd', 's
802818

803819
// Sub-action types available inside a Multi Action (no nesting)
804820
const SUB_ACTION_TYPES = [
805-
{ id: 'hotkey', name: 'Hotkey', icon: '⌫' },
806-
{ id: 'open-app', name: 'Open Application', icon: '⎈' },
807-
{ id: 'open-url', name: 'Open URL', icon: '⊕' },
808-
{ id: 'run-cmd', name: 'Run Command', icon: '›_' },
809-
{ id: 'sleep-toggle', name: 'Sleep', icon: '☽' },
810-
{ id: 'delay', name: 'Delay', icon: '⏱' },
821+
{ id: 'hotkey', name: 'Hotkey', icon: '⌫' },
822+
{ id: 'open-app', name: 'Open Application', icon: '⎈' },
823+
{ id: 'open-url', name: 'Open URL', icon: '⊕' },
824+
{ id: 'run-cmd', name: 'Run Command', icon: '›_' },
825+
{ id: 'page-switcher', name: 'Page', icon: '⊞' },
826+
{ id: 'sleep-toggle', name: 'Sleep', icon: '☽' },
827+
{ id: 'delay', name: 'Delay', icon: '⏱' },
811828
]
812829

813830
const SUB_ACTION_DEFAULTS = {
814-
'hotkey': { type: 'hotkey', keys: '' },
815-
'open-app': { type: 'open-app', target: '', mode: 'gtk-launch' },
816-
'open-url': { type: 'open-url', url: '' },
817-
'run-cmd': { type: 'run-cmd', command: '' },
818-
'sleep-toggle': { type: 'sleep-toggle' },
819-
'delay': { type: 'delay', ms: 500 },
831+
'hotkey': { type: 'hotkey', keys: '' },
832+
'open-app': { type: 'open-app', target: '', mode: 'gtk-launch' },
833+
'open-url': { type: 'open-url', url: '' },
834+
'run-cmd': { type: 'run-cmd', command: '' },
835+
'page-switcher': { type: 'page-switcher', targetPage: 0 },
836+
'sleep-toggle': { type: 'sleep-toggle' },
837+
'delay': { type: 'delay', ms: 500 },
820838
}
821839

822840
// Default configs for top-level button actions (used by drag-and-drop and the picker)
@@ -856,14 +874,15 @@ const ACTION_DEFAULTS = {
856874
}
857875

858876
// Dispatches a single leaf action — returns a Promise
859-
function dispatchSubAction(sd, act) {
877+
function dispatchSubAction(sd, act, switchToPage) {
860878
if (!act || !sd) return Promise.resolve()
861-
if (act.type === 'hotkey' && act.keys) return sd.executeHotkey(act.keys)
862-
if (act.type === 'open-app' && act.target) return sd.openApplication(act.target, act.mode ?? 'gtk-launch')
863-
if (act.type === 'open-url' && act.url) return sd.openUrl(act.url)
864-
if (act.type === 'run-cmd' && act.command) return sd.runCommand(act.command)
865-
if (act.type === 'sleep-toggle') return sd.sleepToggle()
866-
if (act.type === 'delay') return new Promise(r => setTimeout(r, act.ms ?? 500))
879+
if (act.type === 'hotkey' && act.keys) return sd.executeHotkey(act.keys)
880+
if (act.type === 'open-app' && act.target) return sd.openApplication(act.target, act.mode ?? 'gtk-launch')
881+
if (act.type === 'open-url' && act.url) return sd.openUrl(act.url)
882+
if (act.type === 'run-cmd' && act.command) return sd.runCommand(act.command)
883+
if (act.type === 'page-switcher' && switchToPage) { switchToPage(act.targetPage ?? 0); return Promise.resolve() }
884+
if (act.type === 'sleep-toggle') return sd.sleepToggle()
885+
if (act.type === 'delay') return new Promise(r => setTimeout(r, act.ms ?? 500))
867886
return Promise.resolve()
868887
}
869888

@@ -1123,6 +1142,7 @@ export function ActionSection({ action, onChange, profiles = [], pageCount = 1,
11231142
<MultiActionEditor
11241143
actions={action.actions ?? []}
11251144
onChange={actions => onChange({ action: { type: 'multi-action', actions } })}
1145+
pageCount={pageCount}
11261146
/>
11271147
</div>
11281148
)
@@ -2952,9 +2972,10 @@ export default function App() {
29522972
exitFolderRef.current()
29532973
} else if (action?.type === 'multi-action' && action.actions?.length) {
29542974
const sd = window.streamDeck
2975+
const switchFn = switchToPageRef.current
29552976
;(async () => {
29562977
for (const sub of action.actions) {
2957-
await dispatchSubAction(sd, sub)
2978+
await dispatchSubAction(sd, sub, switchFn)
29582979
}
29592980
})()
29602981
} else if (action?.type === 'volume' && action.operation && action.operation !== 'display-only') {

0 commit comments

Comments
 (0)