mirror of
https://github.com/imgfloat/server.git
synced 2026-02-05 03:39:26 +00:00
Fix asset settings
This commit is contained in:
@@ -537,6 +537,59 @@ body {
|
|||||||
margin: 6px 0;
|
margin: 6px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.upload-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin: 12px 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-field {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-trigger {
|
||||||
|
flex: 1;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px dashed rgba(124, 58, 237, 0.45);
|
||||||
|
border-radius: 10px;
|
||||||
|
background: rgba(124, 58, 237, 0.08);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-color 120ms ease, background 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-trigger:hover {
|
||||||
|
border-color: rgba(124, 58, 237, 0.8);
|
||||||
|
background: rgba(124, 58, 237, 0.14);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-icon {
|
||||||
|
width: 38px;
|
||||||
|
height: 38px;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
background: rgba(124, 58, 237, 0.16);
|
||||||
|
color: #c4b5fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-copy {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-copy strong {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-copy small {
|
||||||
|
color: #cbd5e1;
|
||||||
|
}
|
||||||
|
|
||||||
.title-row {
|
.title-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ const muteInput = document.getElementById('asset-muted');
|
|||||||
const selectedZLabel = document.getElementById('asset-z-level');
|
const selectedZLabel = document.getElementById('asset-z-level');
|
||||||
const playbackSection = document.getElementById('playback-section');
|
const playbackSection = document.getElementById('playback-section');
|
||||||
const controlsPlaceholder = document.getElementById('asset-controls-placeholder');
|
const controlsPlaceholder = document.getElementById('asset-controls-placeholder');
|
||||||
|
const fileNameLabel = document.getElementById('asset-file-name');
|
||||||
const aspectLockState = new Map();
|
const aspectLockState = new Map();
|
||||||
const commitSizeChange = debounce(() => applyTransformFromInputs(), 180);
|
const commitSizeChange = debounce(() => applyTransformFromInputs(), 180);
|
||||||
|
|
||||||
@@ -102,8 +103,10 @@ function renderAssets(list) {
|
|||||||
function storeAsset(asset) {
|
function storeAsset(asset) {
|
||||||
if (!asset) return;
|
if (!asset) return;
|
||||||
asset.zIndex = Math.max(1, asset.zIndex ?? 1);
|
asset.zIndex = Math.max(1, asset.zIndex ?? 1);
|
||||||
if (asset.createdAt && typeof asset.createdAtMs === 'undefined') {
|
const parsedCreatedAt = asset.createdAt ? new Date(asset.createdAt).getTime() : NaN;
|
||||||
asset.createdAtMs = new Date(asset.createdAt).getTime();
|
const hasCreatedAtMs = typeof asset.createdAtMs === 'number' && Number.isFinite(asset.createdAtMs);
|
||||||
|
if (!hasCreatedAtMs) {
|
||||||
|
asset.createdAtMs = Number.isFinite(parsedCreatedAt) ? parsedCreatedAt : Date.now();
|
||||||
}
|
}
|
||||||
assets.set(asset.id, asset);
|
assets.set(asset.id, asset);
|
||||||
zOrderDirty = true;
|
zOrderDirty = true;
|
||||||
@@ -177,6 +180,10 @@ function zComparator(a, b) {
|
|||||||
return (a?.createdAtMs || 0) - (b?.createdAtMs || 0);
|
return (a?.createdAtMs || 0) - (b?.createdAtMs || 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getChronologicalAssets() {
|
||||||
|
return Array.from(assets.values()).sort((a, b) => (a?.createdAtMs || 0) - (b?.createdAtMs || 0));
|
||||||
|
}
|
||||||
|
|
||||||
function drawAsset(asset) {
|
function drawAsset(asset) {
|
||||||
const renderState = smoothState(asset);
|
const renderState = smoothState(asset);
|
||||||
const halfWidth = renderState.width / 2;
|
const halfWidth = renderState.width / 2;
|
||||||
@@ -626,7 +633,7 @@ function renderAssetList() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sortedAssets = getZOrderedAssets().reverse();
|
const sortedAssets = getChronologicalAssets();
|
||||||
sortedAssets.forEach((asset) => {
|
sortedAssets.forEach((asset) => {
|
||||||
const li = document.createElement('li');
|
const li = document.createElement('li');
|
||||||
li.className = 'asset-item';
|
li.className = 'asset-item';
|
||||||
@@ -854,7 +861,7 @@ function recenterSelectedAsset() {
|
|||||||
function bringForward() {
|
function bringForward() {
|
||||||
const asset = getSelectedAsset();
|
const asset = getSelectedAsset();
|
||||||
if (!asset) return;
|
if (!asset) return;
|
||||||
const ordered = getZOrderedAssets();
|
const ordered = [...getZOrderedAssets()];
|
||||||
const index = ordered.findIndex((item) => item.id === asset.id);
|
const index = ordered.findIndex((item) => item.id === asset.id);
|
||||||
if (index === -1 || index === ordered.length - 1) return;
|
if (index === -1 || index === ordered.length - 1) return;
|
||||||
[ordered[index], ordered[index + 1]] = [ordered[index + 1], ordered[index]];
|
[ordered[index], ordered[index + 1]] = [ordered[index + 1], ordered[index]];
|
||||||
@@ -864,7 +871,7 @@ function bringForward() {
|
|||||||
function bringBackward() {
|
function bringBackward() {
|
||||||
const asset = getSelectedAsset();
|
const asset = getSelectedAsset();
|
||||||
if (!asset) return;
|
if (!asset) return;
|
||||||
const ordered = getZOrderedAssets();
|
const ordered = [...getZOrderedAssets()];
|
||||||
const index = ordered.findIndex((item) => item.id === asset.id);
|
const index = ordered.findIndex((item) => item.id === asset.id);
|
||||||
if (index <= 0) return;
|
if (index <= 0) return;
|
||||||
[ordered[index], ordered[index - 1]] = [ordered[index - 1], ordered[index]];
|
[ordered[index], ordered[index - 1]] = [ordered[index - 1], ordered[index]];
|
||||||
@@ -987,6 +994,14 @@ function deleteAsset(asset) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleFileSelection(input) {
|
||||||
|
if (!input) return;
|
||||||
|
const name = input.files && input.files.length ? input.files[0].name : '';
|
||||||
|
if (fileNameLabel) {
|
||||||
|
fileNameLabel.textContent = name || 'No file chosen';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function uploadAsset() {
|
function uploadAsset() {
|
||||||
const fileInput = document.getElementById('asset-file');
|
const fileInput = document.getElementById('asset-file');
|
||||||
if (!fileInput || !fileInput.files || fileInput.files.length === 0) {
|
if (!fileInput || !fileInput.files || fileInput.files.length === 0) {
|
||||||
@@ -1000,6 +1015,7 @@ function uploadAsset() {
|
|||||||
body: data
|
body: data
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
fileInput.value = '';
|
fileInput.value = '';
|
||||||
|
handleFileSelection(fileInput);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,7 +1043,7 @@ function isPointOnAsset(asset, x, y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function findAssetAtPoint(x, y) {
|
function findAssetAtPoint(x, y) {
|
||||||
const ordered = getZOrderedAssets().reverse();
|
const ordered = [...getZOrderedAssets()].reverse();
|
||||||
return ordered.find((asset) => isPointOnAsset(asset, x, y)) || null;
|
return ordered.find((asset) => isPointOnAsset(asset, x, y)) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,17 @@
|
|||||||
<div class="controls-full panel">
|
<div class="controls-full panel">
|
||||||
<h3>Overlay assets</h3>
|
<h3>Overlay assets</h3>
|
||||||
<p>Upload overlay visuals and adjust them inline.</p>
|
<p>Upload overlay visuals and adjust them inline.</p>
|
||||||
<input id="asset-file" type="file" accept="image/*,video/*" />
|
<div class="upload-row">
|
||||||
<button onclick="uploadAsset()">Upload</button>
|
<input id="asset-file" class="file-input-field" type="file" accept="image/*,video/*" onchange="handleFileSelection(this)" />
|
||||||
|
<label for="asset-file" class="file-input-trigger">
|
||||||
|
<span class="file-input-icon"><i class="fa-solid fa-cloud-arrow-up"></i></span>
|
||||||
|
<span class="file-input-copy">
|
||||||
|
<strong>Select an image, GIF, or video</strong>
|
||||||
|
<small id="asset-file-name">No file chosen</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<button onclick="uploadAsset()">Upload</button>
|
||||||
|
</div>
|
||||||
<ul id="asset-list" class="asset-list"></ul>
|
<ul id="asset-list" class="asset-list"></ul>
|
||||||
<div id="asset-controls-placeholder" class="hidden"></div>
|
<div id="asset-controls-placeholder" class="hidden"></div>
|
||||||
<div id="asset-controls" class="hidden asset-settings">
|
<div id="asset-controls" class="hidden asset-settings">
|
||||||
|
|||||||
Reference in New Issue
Block a user