Initial PlayBull release with Trilogy Hub integration.
Includes homelab deploy tooling, image position/zoom manifest persistence, and full trading/casino stack. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
72
public/js/upload-helper.js
Normal file
72
public/js/upload-helper.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import { openImagePositionEditor } from './image-editor.js';
|
||||
|
||||
/**
|
||||
* Öffnet Editor und lädt Bild hoch. Für Avatar, Galerie und alle anderen Uploads.
|
||||
*/
|
||||
export async function uploadImageWithEditor(file, { frame, uploadFn }) {
|
||||
if (!file) return null;
|
||||
const result = await openImagePositionEditor({ file, frame });
|
||||
if (!result) return null;
|
||||
return uploadFn(file, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Editor für bestehendes Bild, dann Position speichern.
|
||||
*/
|
||||
export async function repositionImageWithEditor(item, { frame, saveFn }) {
|
||||
const result = await openImagePositionEditor({
|
||||
url: item.url,
|
||||
focus: item.focus,
|
||||
zoom: item.zoom,
|
||||
frame: frame || item.frame || 'gallery',
|
||||
});
|
||||
if (!result) return null;
|
||||
return saveFn(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verbindet einen File-Input mit Editor + Upload-Callback.
|
||||
*/
|
||||
export function wireImageFileInput(input, { frame, onPick }) {
|
||||
input.addEventListener('change', async () => {
|
||||
const file = input.files?.[0];
|
||||
input.value = '';
|
||||
if (!file) return;
|
||||
try {
|
||||
await onPick(file, frame);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt versteckten File-Input + Button — Editor öffnet sich immer vor Upload.
|
||||
*/
|
||||
export function createImageUploadButton({ label, frame, onPick, className = 'btn btn-accent' }) {
|
||||
const wrap = document.createElement('div');
|
||||
wrap.className = 'image-upload-wrap';
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.className = className;
|
||||
btn.textContent = label;
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.accept = 'image/*';
|
||||
input.hidden = true;
|
||||
btn.onclick = () => input.click();
|
||||
wireImageFileInput(input, {
|
||||
frame,
|
||||
onPick: async (file) => onPick(file, frame),
|
||||
});
|
||||
wrap.append(btn, input);
|
||||
return wrap;
|
||||
}
|
||||
|
||||
export function appendPositionFields(fd, result, frame) {
|
||||
fd.append('focusX', result.focus.x);
|
||||
fd.append('focusY', result.focus.y);
|
||||
fd.append('zoom', result.zoom);
|
||||
if (frame) fd.append('frame', frame);
|
||||
return fd;
|
||||
}
|
||||
Reference in New Issue
Block a user