Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 61 additions & 55 deletions src/lib/components/tree/ConfigTree.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,10 @@
handler: () => get(config_manager)?.showConfigInFolder(item),
isDisabled: () => !get(config_manager)?.hasLocalFile(item),
},
{
text: [`Create a copy`, ``],
handler: () => dispatch("create-copy", item),
},
{
text: [`Rename`, ``],
handler: () => startRename(item),
Expand Down Expand Up @@ -563,19 +567,21 @@
{#if renamingFolderTitle === data.title}
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<div class="rename-row" on:keydown|stopPropagation>
<MoltenInput
bind:this={renameFolderInput}
bind:target={renameFolderValue}
on:blur={() => confirmRenameFolder(data.title)}
on:keydown={(e) =>
handleRenameKeydown(
e,
() => renameFolderValue,
(v) => (renameFolderValue = v),
() => confirmRenameFolder(data.title),
cancelRenameFolder,
)}
/>
<div class="rename-input">
<MoltenInput
bind:this={renameFolderInput}
bind:target={renameFolderValue}
on:blur={() => confirmRenameFolder(data.title)}
on:keydown={(e) =>
handleRenameKeydown(
e,
() => renameFolderValue,
(v) => (renameFolderValue = v),
() => confirmRenameFolder(data.title),
cancelRenameFolder,
)}
/>
</div>
<IconButton
onMouseDown={(e) => e.preventDefault()}
onClick={cancelRenameFolder}
Expand Down Expand Up @@ -609,53 +615,53 @@
let:itemProps
>
{@const data = getItemData(item)}
{#if renamingConfigId === data.item.id}
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<div class="rename-row" on:keydown|stopPropagation>
<MoltenInput
bind:this={renameInput}
bind:target={renameValue}
on:blur={() => confirmRename(data.item)}
on:keydown={(e) =>
handleRenameKeydown(
e,
() => renameValue,
(v) => (renameValue = v),
() => confirmRename(data.item),
cancelRename,
)}
/>
{@const isRenaming = renamingConfigId === data.item.id}
<ProfileCloudTreeItem
{itemFunction}
{itemProps}
{item}
compatible={data.compatible}
selected={data.item.id === $selected_config?.id}
{expanded}
editing={isRenaming}
ctxOptions={getItemCtxOptions(item)}
on:drag-start={() => handleDragStart(item)}
on:drag-end={() => handleDragEnd(item)}
on:click={() => handleClick(item)}
on:contextmenu={() => handleContextMenu(item)}
>
<div slot="button-label">
{@html highlightMatches(data.item.name, $filter_value)}
</div>
<div slot="type-label">
{@html highlightMatches(data.item.type, $filter_value)}
</div>
<svelte:fragment slot="edit-content">
<div class="rename-input">
<MoltenInput
bind:this={renameInput}
bind:target={renameValue}
on:blur={() => confirmRename(data.item)}
on:keydown={(e) =>
handleRenameKeydown(
e,
() => renameValue,
(v) => (renameValue = v),
() => confirmRename(data.item),
cancelRename,
)}
/>
</div>
<IconButton
onMouseDown={(e) => e.preventDefault()}
onClick={cancelRename}
iconPath="close"
tooltipText="Cancel"
/>
</div>
{#if renameError}
<p class="rename-error">{renameError}</p>
{/if}
{:else}
<ProfileCloudTreeItem
{itemFunction}
{itemProps}
{item}
compatible={data.compatible}
selected={data.item.id === $selected_config?.id}
{expanded}
ctxOptions={getItemCtxOptions(item)}
on:drag-start={() => handleDragStart(item)}
on:drag-end={() => handleDragEnd(item)}
on:click={() => handleClick(item)}
on:contextmenu={() => handleContextMenu(item)}
>
<div slot="button-label">
{@html highlightMatches(data.item.name, $filter_value)}
</div>
<div slot="type-label">
{@html highlightMatches(data.item.type, $filter_value)}
</div>
</ProfileCloudTreeItem>
</svelte:fragment>
</ProfileCloudTreeItem>
{#if isRenaming && renameError}
<p class="rename-error">{renameError}</p>
{/if}
</svelte:fragment>
</TreeComponent>
Expand All @@ -669,7 +675,7 @@
padding: 0.25rem;
}

.rename-row > :global(:first-child) {
.rename-input {
flex-grow: 1;
min-width: 0;
}
Expand Down
57 changes: 37 additions & 20 deletions src/lib/components/tree/ProfileCloudTreeItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
export let itemProps: any;
export let itemFunction: any;
export let ctxOptions: ContextMenuOptions = { items: [] };
export let editing: boolean = false;

type WithProfileCloudData<T = unknown> = T & ProfileCloudCardData;

Expand All @@ -51,15 +52,16 @@
}
</script>

<button
<svelte:element
this={editing ? "div" : "button"}
id={$item.id}
class="{selected ? 'border-selected' : 'border-unselected'} button"
draggable="true"
use:contextTarget={ctxOptions}
on:click={handleClick}
on:contextmenu={handleContextMenu}
on:dragstart={handleDragStart}
on:dragend={handleDragEnd}
draggable={editing ? "false" : "true"}
use:contextTarget={editing ? { items: [] } : ctxOptions}
on:click={editing ? undefined : handleClick}
on:contextmenu={editing ? undefined : handleContextMenu}
on:dragstart={editing ? undefined : handleDragStart}
on:dragend={editing ? undefined : handleDragEnd}
>
<div class="status-indicator">
<div
Expand All @@ -78,18 +80,25 @@
iconPath={$item.children.length > 0 ? "overlay_02" : "overlay_03"}
/>
<div class="button-content" class:expanded>
<span class="button-label" class:label-incompatible={compatible}>
<slot name="button-label">
{data.name}
</slot>
</span>
<span class="modified-date">{data.modifiedAt.toLocaleDateString()}</span>
<div
class="type-label
{compatible ? 'type-compatible' : 'type-incompatible'}"
>
<slot name="type-label">{data.type}</slot>
</div>
{#if editing}
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<div class="edit-content" on:keydown|stopPropagation>
<slot name="edit-content" />
</div>
{:else}
<span class="button-label" class:label-incompatible={compatible}>
<slot name="button-label">
{data.name}
</slot>
</span>
<span class="modified-date">{data.modifiedAt.toLocaleDateString()}</span>
<div
class="type-label
{compatible ? 'type-compatible' : 'type-incompatible'}"
>
<slot name="type-label">{data.type}</slot>
</div>
{/if}
{#if $item.children.length > 0}
<div
class="trigger-container"
Expand All @@ -109,7 +118,7 @@
</div>
{/if}
</div>
</button>
</svelte:element>

<style>
.button {
Expand Down Expand Up @@ -192,6 +201,14 @@
text-align: left;
}

.edit-content {
grid-column: 1 / span 3;
display: flex;
align-items: center;
gap: 0.5rem;
min-width: 0;
}

.label-incompatible {
opacity: 0.75;
}
Expand Down
18 changes: 13 additions & 5 deletions src/routes/EditorLayout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -586,31 +586,38 @@
});
}

async function handleSyncConfig(config: Config | undefined) {
async function handleSyncConfig(
config: Config | undefined,
forceCopy = false,
) {
if (typeof config === "undefined") {
return;
}

if (
!forceCopy &&
config.isEditable &&
config.syncStatus === "local" &&
!$userAccountService.account
) {
loginToProfileCloud();
return;
}
const makeCopy = forceCopy || !config.isEditable;
let configToSave = config;
if (!configToSave.isEditable) {
if (makeCopy) {
configToSave = {
...configToSave,
name: `Copy of ${configToSave.name}`,
displayName: undefined,
isEditable: true,
owner: undefined,
id: "",
};
}
const cm = get(config_manager);
pendingNewConfigScroll = true;
const action = !config.isEditable
const action = makeCopy
? "Created a copy of"
: config.syncStatus === "cloud"
? "Downloaded"
Expand Down Expand Up @@ -734,6 +741,7 @@
<ConfigTree
{configs}
scrollToSelectionTrigger={scrollToSelectedConfigTrigger}
on:create-copy={(e) => handleSyncConfig(e.detail, true)}
/>
</div></Pane
>
Expand Down Expand Up @@ -778,8 +786,8 @@
tooltipText="Create a copy"
tooltipDelay={0}
stopPropagation
disabled={!config || config.isEditable}
onClick={() => handleSyncConfig(config)}
disabled={!config}
onClick={() => handleSyncConfig(config, true)}
/>
<IconButton
iconPath="download"
Expand Down
Loading