Add first iteration of the Image DB editor

This commit is contained in:
Oliver 2026-01-18 23:34:24 -07:00
parent 773c506570
commit c7c02702d7
13 changed files with 425 additions and 7 deletions

View file

@ -1,7 +1,33 @@
import { __ID__, filePath } from "../consts.mjs";
import { __ID__, devMode, filePath } from "../consts.mjs";
const { fetchJsonWithTimeout } = foundry.utils;
/**
* Returns a pseudo-hash for a file. If the browser is in a secure
* context this will return a true SHA-1 hash of the file, otherwise
* a random ID is generated using the character set A-Za-z0-9.
*
* @param {File} file The file to hash
*/
export async function hashFile(file) {
// Handle fallback when hashing isn't possible
if (!window.isSecureContext || !crypto.subtle.digest) {
return foundry.utils.randomID(40);
};
// Actually hash the file since we can
const bytes = await file.arrayBuffer();
const buffer = await crypto.subtle.digest(`SHA-1`, bytes);
const intArray = new Uint8Array(buffer);
if (Uint8Array.prototype.toHex) {
return intArray.toHex();
};
return Array.from(intArray)
.map(b => b.toString(16).padStart(2, `0`))
.join(``);
};
export async function lastModifiedAt(path) {
try {
const response = await fetch(filePath(path), { method: `HEAD` });
@ -24,6 +50,22 @@ export async function getFile(path) {
* @param {any} data
*/
export async function uploadJson(path, filename, data) {
const content = JSON.stringify(
data,
undefined,
devMode() ? `\t` : undefined,
);
try {
const file = new File(
[content],
filename,
{ type: `text/plain` },
);
await uploadFile(path, file);
} catch {};
};
export async function uploadFile(path, file) {
// uploadPersistent adds "storage" into the path automatically
if (path.startsWith(`storage/`)) {
@ -35,11 +77,6 @@ export async function uploadJson(path, filename, data) {
const picker = foundry.applications.apps.FilePicker.implementation;
try {
const file = new File(
[JSON.stringify(data)],
filename,
{ type: `text/plain` },
);
await picker.uploadPersistent(
__ID__,
path,
@ -47,3 +84,12 @@ export async function uploadJson(path, filename, data) {
);
} catch {};
};
export function determineFileExtension(file) {
for (const [short, long] of Object.entries(CONST.IMAGE_FILE_EXTENSIONS)) {
if (long === file.type) {
return short;
};
};
return null;
};