mirror of
https://github.com/nekename/OpenDeck.git
synced 2026-10-28 09:44:01 +00:00
feat: allow customising the delay in between actions within Multi Actions (#393)
Co-authored-by: nekename <63245705+nekename@users.noreply.github.com>
This commit is contained in:
1 parent
0a0072a648
commit
64aaf168b5
7 files changed
+129
-13
No files matched your search
@@ -171,11 +171,25 @@ pub async fn remove_instance(context: ActionContext) -> Result<(), Error> {
|
||||
*slot = None;
|
||||
} else {
|
||||
let children = instance.children.as_mut().unwrap();
|
||||
for (index, instance) in children.iter().enumerate() {
|
||||
if instance.context == context {
|
||||
let _ = crate::events::outbound::will_appear::will_disappear(instance, true).await;
|
||||
let _ = remove_dir_all(instance_images_dir(&instance.context)).await;
|
||||
for (index, child) in children.iter().enumerate() {
|
||||
if child.context == context {
|
||||
let _ = crate::events::outbound::will_appear::will_disappear(child, true).await;
|
||||
let _ = remove_dir_all(instance_images_dir(&child.context)).await;
|
||||
children.remove(index);
|
||||
|
||||
if instance.action.uuid == "opendeck.multiaction"
|
||||
&& let Some(settings) = instance.settings.as_object_mut()
|
||||
&& let Some(delays) = settings.get_mut("delays").and_then(|v| v.as_array_mut())
|
||||
{
|
||||
if index == 0 {
|
||||
if !delays.is_empty() {
|
||||
delays.remove(0);
|
||||
}
|
||||
} else if index - 1 < delays.len() {
|
||||
delays.remove(index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -224,6 +238,34 @@ pub async fn set_state(context: ActionContext, index: u16, state: ActionState) -
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub async fn set_child_delay(parent_context: ActionContext, index: usize, delay_ms: u64) -> Result<serde_json::Value, Error> {
|
||||
let mut locks = acquire_locks_mut().await;
|
||||
let Some(parent) = get_instance_mut(&parent_context, &mut locks).await? else {
|
||||
return Ok(serde_json::Value::Null);
|
||||
};
|
||||
|
||||
let delays = parent.settings.get_mut("delays").and_then(|v| v.as_array_mut());
|
||||
if let Some(arr) = delays {
|
||||
if arr.len() <= index {
|
||||
arr.resize(index + 1, serde_json::json!(100));
|
||||
}
|
||||
arr[index] = serde_json::json!(delay_ms);
|
||||
} else {
|
||||
if !parent.settings.is_object() {
|
||||
parent.settings = serde_json::Value::Object(serde_json::Map::new());
|
||||
}
|
||||
let map = parent.settings.as_object_mut().unwrap();
|
||||
let mut arr = vec![serde_json::json!(100); index + 1];
|
||||
arr[index] = serde_json::json!(delay_ms);
|
||||
map.insert("delays".to_string(), serde_json::Value::Array(arr));
|
||||
}
|
||||
let parent_settings = parent.settings.clone();
|
||||
|
||||
save_profile_now(&parent_context.device, &mut locks).await?;
|
||||
Ok(parent_settings)
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub async fn update_image(context: Context, image: Option<String>) {
|
||||
if Some(&context.profile) != crate::store::profiles::DEVICE_STORES.write().await.get_selected_profile(&context.device).ok().as_ref() {
|
||||
|
||||
@@ -36,7 +36,17 @@ pub async fn key_down(device: &str, key: u8) -> Result<(), anyhow::Error> {
|
||||
|
||||
let Some(instance) = get_slot_mut(&context, &mut locks).await? else { return Ok(()) };
|
||||
if instance.action.uuid == "opendeck.multiaction" {
|
||||
for child in instance.children.as_mut().unwrap() {
|
||||
let children = instance.children.clone().unwrap_or_default();
|
||||
let delays: Vec<u64> = instance
|
||||
.settings
|
||||
.get("delays")
|
||||
.and_then(|v| v.as_array())
|
||||
.map(|arr| arr.iter().filter_map(|v| v.as_u64()).collect())
|
||||
.unwrap_or_default();
|
||||
|
||||
drop(locks);
|
||||
|
||||
for (i, child) in children.iter().enumerate() {
|
||||
send_to_plugin(
|
||||
&child.action.plugin,
|
||||
&KeyEvent {
|
||||
@@ -51,10 +61,6 @@ pub async fn key_down(device: &str, key: u8) -> Result<(), anyhow::Error> {
|
||||
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
|
||||
if child.states.len() == 2 && !child.action.disable_automatic_states {
|
||||
child.current_state = (child.current_state + 1) % (child.states.len() as u16);
|
||||
}
|
||||
|
||||
send_to_plugin(
|
||||
&child.action.plugin,
|
||||
&KeyEvent {
|
||||
@@ -67,13 +73,27 @@ pub async fn key_down(device: &str, key: u8) -> Result<(), anyhow::Error> {
|
||||
)
|
||||
.await?;
|
||||
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
let delay = delays.get(i).copied().unwrap_or(100);
|
||||
if delay > 0 {
|
||||
tokio::time::sleep(Duration::from_millis(delay)).await;
|
||||
}
|
||||
}
|
||||
|
||||
let contexts = instance.children.as_ref().unwrap().iter().map(|x| x.context.clone()).collect::<Vec<_>>();
|
||||
for child in contexts {
|
||||
let mut locks = acquire_locks_mut().await;
|
||||
|
||||
if let Some(instance) = get_slot_mut(&context, &mut locks).await?
|
||||
&& let Some(children) = &mut instance.children
|
||||
{
|
||||
for child in &mut *children {
|
||||
if child.states.len() == 2 && !child.action.disable_automatic_states {
|
||||
child.current_state = (child.current_state + 1) % (child.states.len() as u16);
|
||||
}
|
||||
}
|
||||
|
||||
for child in children.iter().map(|x| x.context.clone()).collect::<Vec<_>>() {
|
||||
let _ = update_state(crate::APP_HANDLE.get().unwrap(), child, &mut locks).await;
|
||||
}
|
||||
}
|
||||
|
||||
mark_profile_stale(device, &mut locks).await?;
|
||||
} else if instance.action.uuid == "opendeck.toggleaction" {
|
||||
|
||||
@@ -83,6 +83,7 @@ async fn main() {
|
||||
frontend::instances::move_instance,
|
||||
frontend::instances::remove_instance,
|
||||
frontend::instances::set_state,
|
||||
frontend::instances::set_child_delay,
|
||||
frontend::instances::update_image,
|
||||
frontend::instances::trigger_virtual_press,
|
||||
frontend::profiles::get_profiles,
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
$: children = profile.keys[$inspectedParentAction!.position]!.children!;
|
||||
let parentUuid: string;
|
||||
$: parentUuid = profile.keys[$inspectedParentAction!.position]!.action.uuid;
|
||||
let parentContext: string;
|
||||
$: parentContext = profile.keys[$inspectedParentAction!.position]!.context;
|
||||
let parentSettings: any;
|
||||
$: parentSettings = profile.keys[$inspectedParentAction!.position]!.settings;
|
||||
|
||||
function handleDragOver(event: DragEvent) {
|
||||
event.preventDefault();
|
||||
@@ -58,6 +62,12 @@
|
||||
children.splice(index, 1);
|
||||
profile.keys[$inspectedParentAction!.position]!.children = children;
|
||||
|
||||
if (index == 0) {
|
||||
profile.keys[$inspectedParentAction!.position]!.settings.delays?.splice(0, 1);
|
||||
} else {
|
||||
profile.keys[$inspectedParentAction!.position]!.settings.delays?.splice(index - 1, 1);
|
||||
}
|
||||
|
||||
if (!refocus) return;
|
||||
|
||||
await tick();
|
||||
@@ -71,6 +81,13 @@
|
||||
items[targetIndex]?.focus();
|
||||
}
|
||||
|
||||
async function setDelay(index: number, event: Event) {
|
||||
const target = event.currentTarget as HTMLInputElement;
|
||||
const val = Math.max(0, parseInt(target.value) || 0);
|
||||
const settings = await invoke<any>("set_child_delay", { parentContext, index, delayMs: val });
|
||||
profile.keys[$inspectedParentAction!.position]!.settings = settings;
|
||||
}
|
||||
|
||||
function handleListKeydown(event: KeyboardEvent) {
|
||||
if (!["ArrowUp", "ArrowDown", "Home", "End"].includes(event.key)) return;
|
||||
const list = event.currentTarget as HTMLElement;
|
||||
@@ -126,7 +143,8 @@
|
||||
{#each children as instance, index}
|
||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex a11y-no-noninteractive-element-interactions -->
|
||||
<div
|
||||
class="flex flex-row items-center mx-4 my-2 bg-neutral-700 hover:bg-neutral-600 transition-colors border border-neutral-600 rounded-lg focus-within:outline-solid focus-within:outline-offset-2 focus-within:outline-blue-500"
|
||||
class="flex flex-row items-center mx-4 my-1 bg-neutral-700 hover:bg-neutral-600 transition-colors border border-neutral-600 rounded-lg focus-within:outline-solid focus-within:outline-offset-2 focus-within:outline-blue-500"
|
||||
class:my-2={parentUuid == "opendeck.toggleaction"}
|
||||
on:click|stopPropagation={() => ($inspectedInstance = instance.context)}
|
||||
on:focus|stopPropagation={() => ($inspectedInstance = instance.context)}
|
||||
on:keydown={(e) => {
|
||||
@@ -158,6 +176,23 @@
|
||||
<Trash size="32" class="text-neutral-400" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if parentUuid == "opendeck.multiaction" && index < children.length - 1}
|
||||
<div class="flex flex-row items-center gap-2 mx-14 my-1 px-3 py-2 bg-neutral-800 border border-dashed border-neutral-600 rounded-lg">
|
||||
<span class="text-xs text-neutral-400">{$t("parent_action_view.delay.label")}</span>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
max="300000"
|
||||
step="100"
|
||||
value={parentSettings?.delays?.[index] ?? 100}
|
||||
on:input={(e) => setDelay(index, e)}
|
||||
class="no-spinner w-20 px-1 py-0.5 text-center text-sm text-neutral-300 bg-neutral-900 border border-neutral-600 rounded"
|
||||
aria-label={$t("parent_action_view.delay.aria", { name: children[index + 1].action.name })}
|
||||
/>
|
||||
<span class="text-xs text-neutral-500">ms</span>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex a11y-no-noninteractive-element-interactions -->
|
||||
<div
|
||||
@@ -177,3 +212,15 @@
|
||||
<p class="ml-4 text-xl text-neutral-400">{$t("parent_action_view.drag_paste")}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:global(.no-spinner::-webkit-outer-spin-button),
|
||||
:global(.no-spinner::-webkit-inner-spin-button) {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
:global(.no-spinner[type="number"]) {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
</style>
|
||||
@@ -41,6 +41,8 @@
|
||||
"no_devices_detected.title": "Keine Geräte gefunden",
|
||||
"parent_action_view.child": "Unteraktion",
|
||||
"parent_action_view.children": "Unteraktionen",
|
||||
"parent_action_view.delay.aria": "Verzögerung für {{name}}",
|
||||
"parent_action_view.delay.label": "Verzögerung:",
|
||||
"parent_action_view.drag_copy": "Ziehe eine neue Aktion hierher oder kopiere eine mit Strg+C und füge sie mit Strg+V ein.",
|
||||
"parent_action_view.drag_paste": "Ziehe oder füge Aktionen hier ein",
|
||||
"parent_action_view.multi": "Multiaktionen",
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
"no_devices_detected.title": "No devices detected",
|
||||
"parent_action_view.child": "child",
|
||||
"parent_action_view.children": "children",
|
||||
"parent_action_view.delay.aria": "Delay for {{name}}",
|
||||
"parent_action_view.delay.label": "Delay:",
|
||||
"parent_action_view.drag_copy": "Drag a new action here or copy one with Control+C and paste with Control+V.",
|
||||
"parent_action_view.drag_paste": "Drop or paste actions here",
|
||||
"parent_action_view.multi": "Multi Action",
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
"no_devices_detected.title": "Inga enheter hittades",
|
||||
"parent_action_view.child": "underåtgärd",
|
||||
"parent_action_view.children": "underåtgärder",
|
||||
"parent_action_view.delay.aria": "Fördröjning för {{name}}",
|
||||
"parent_action_view.delay.label": "Fördröjning:",
|
||||
"parent_action_view.drag_copy": "Dra en ny åtgärd hit eller kopiera en med Control+C och klistra in med Control+V.",
|
||||
"parent_action_view.drag_paste": "Släpp eller klistra in åtgärder här",
|
||||
"parent_action_view.multi": "Flera åtgärder",
|
||||
|
||||
Reference in new issue
Block a user