mirror of
https://github.com/nekename/OpenDeck.git
synced 2026-10-28 09:44:01 +00:00
feat: implement support for duplicating profiles from the profile manager
This commit is contained in:
3 files changed
+47
-17
No files matched your search
@@ -90,13 +90,13 @@ pub async fn delete_profile(device: String, profile: String) {
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub async fn rename_profile(device: String, old_id: String, new_id: String) -> Result<(), Error> {
|
||||
pub async fn rename_profile(device: String, old_id: String, new_id: String, retain: bool) -> Result<(), Error> {
|
||||
let mut locks = acquire_locks_mut().await;
|
||||
if !DEVICES.contains_key(&device) {
|
||||
return Err(Error::new(format!("device {device} not found")));
|
||||
}
|
||||
|
||||
locks.profile_stores.rename_profile(&DEVICES.get(&device).unwrap(), &old_id, &new_id).await?;
|
||||
locks.profile_stores.rename_profile(&DEVICES.get(&device).unwrap(), &old_id, &new_id, retain).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::Store;
|
||||
|
||||
use crate::shared::{ActionInstance, DEVICES, DeviceInfo, Profile, config_dir};
|
||||
use crate::shared::{ActionInstance, DEVICES, DeviceInfo, Profile, config_dir, copy_dir};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
@@ -86,9 +86,11 @@ impl ProfileStores {
|
||||
let _ = fs::remove_dir_all(images_path);
|
||||
}
|
||||
|
||||
pub async fn rename_profile(&mut self, device: &DeviceInfo, old_id: &str, new_id: &str) -> Result<(), anyhow::Error> {
|
||||
// Remove from the store but don't delete the file
|
||||
self.remove_profile(&device.id, old_id);
|
||||
pub async fn rename_profile(&mut self, device: &DeviceInfo, old_id: &str, new_id: &str, retain: bool) -> Result<(), anyhow::Error> {
|
||||
if !retain {
|
||||
// Remove from the store but don't delete the file
|
||||
self.remove_profile(&device.id, old_id);
|
||||
}
|
||||
|
||||
let config_dir = config_dir();
|
||||
|
||||
@@ -112,12 +114,16 @@ impl ProfileStores {
|
||||
}
|
||||
|
||||
// Rename the profile file
|
||||
fs::rename(&old_path, &new_path)?;
|
||||
if !retain {
|
||||
fs::rename(&old_path, &new_path)?;
|
||||
|
||||
// Clean up empty old directory if profile was in a folder
|
||||
if let Some(parent) = old_path.parent() {
|
||||
// This is safe as `remove_dir` errors if the directory is not empty.
|
||||
let _ = fs::remove_dir(parent);
|
||||
// Clean up empty old directory if profile was in a folder
|
||||
if let Some(parent) = old_path.parent() {
|
||||
// This is safe as `remove_dir` errors if the directory is not empty.
|
||||
let _ = fs::remove_dir(parent);
|
||||
}
|
||||
} else {
|
||||
fs::copy(&old_path, &new_path)?;
|
||||
}
|
||||
|
||||
// Rename images directory if it exists
|
||||
@@ -128,12 +134,17 @@ impl ProfileStores {
|
||||
if let Some(parent) = new_images_path.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
fs::rename(&old_images_path, &new_images_path)?;
|
||||
|
||||
// Clean up empty old images directory
|
||||
if let Some(parent) = old_images_path.parent() {
|
||||
// This is safe as `remove_dir` errors if the directory is not empty.
|
||||
let _ = fs::remove_dir(parent);
|
||||
if !retain {
|
||||
fs::rename(&old_images_path, &new_images_path)?;
|
||||
|
||||
// Clean up empty old images directory
|
||||
if let Some(parent) = old_images_path.parent() {
|
||||
// This is safe as `remove_dir` errors if the directory is not empty.
|
||||
let _ = fs::remove_dir(parent);
|
||||
}
|
||||
} else {
|
||||
copy_dir(&old_images_path, &new_images_path)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import type { Profile } from "$lib/Profile";
|
||||
|
||||
import Browsers from "phosphor-svelte/lib/Browsers";
|
||||
import Copy from "phosphor-svelte/lib/Copy";
|
||||
import FloppyDisk from "phosphor-svelte/lib/FloppyDisk";
|
||||
import Pencil from "phosphor-svelte/lib/Pencil";
|
||||
import Trash from "phosphor-svelte/lib/Trash";
|
||||
@@ -89,7 +90,7 @@
|
||||
}
|
||||
|
||||
try {
|
||||
await invoke("rename_profile", { device: device.id, oldId, newId });
|
||||
await invoke("rename_profile", { device: device.id, oldId, newId, retain: false });
|
||||
} catch (error: any) {
|
||||
message(error, { title: "Failed to rename profile" });
|
||||
console.error(error);
|
||||
@@ -123,6 +124,21 @@
|
||||
}
|
||||
$: if (renameInput) renameInput.focus();
|
||||
|
||||
async function duplicateProfile(id: string) {
|
||||
let newId = id + " Copy";
|
||||
|
||||
// Check if a profile with the new ID already exists
|
||||
const allProfiles = Object.values(folders).flat();
|
||||
let counter = 1;
|
||||
while (allProfiles.includes(newId)) {
|
||||
counter++;
|
||||
newId = `${id} Copy ${counter}`;
|
||||
}
|
||||
|
||||
await invoke("rename_profile", { device: device.id, oldId: id, newId, retain: true });
|
||||
await getProfiles(device);
|
||||
}
|
||||
|
||||
let oldValue: string;
|
||||
$: {
|
||||
if (value == "opendeck_edit_profiles") {
|
||||
@@ -259,6 +275,9 @@
|
||||
</button>
|
||||
{:else}
|
||||
<span class="grow text-neutral-400">{id ? profile.split("/")[1] : profile}</span>
|
||||
<button on:click={() => duplicateProfile(profile)} title="Duplicate" aria-label="Duplicate">
|
||||
<Copy size="20" class="text-neutral-400" />
|
||||
</button>
|
||||
{#if profile != value}
|
||||
<button
|
||||
on:click={() => renamingProfile = newId = profile}
|
||||
|
||||
Reference in new issue
Block a user