pixelkiln 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -9903,6 +9903,7 @@ function createGalleryEditHandler(opts) {
9903
9903
  }
9904
9904
 
9905
9905
  // src/gallery/snapshot.ts
9906
+ var PROJECT_FILE_TYPE = "application/octet-stream";
9906
9907
  function galleryMediaId(absolutePath) {
9907
9908
  return (0, import_node_crypto6.createHash)("sha256").update(import_node_path25.default.resolve(absolutePath)).digest("hex").slice(0, 24);
9908
9909
  }
@@ -10052,12 +10053,20 @@ async function buildGallerySnapshot(opts) {
10052
10053
  const companion = await readHandEditCompanion(editPath);
10053
10054
  if (companion) {
10054
10055
  const projectPath = handEditProjectPath(editPath);
10056
+ const project = companion.project && (0, import_node_fs21.existsSync)(projectPath) ? await fileInfo(projectPath) : null;
10057
+ let projectUrl = null;
10058
+ if (project) {
10059
+ const id = galleryMediaId(projectPath);
10060
+ media.set(id, { path: projectPath, contentType: PROJECT_FILE_TYPE });
10061
+ projectUrl = `${galleryMediaRoute(id)}?v=${project.bytes}-${Date.parse(project.modifiedAt).toString(36)}`;
10062
+ }
10055
10063
  editMeta = {
10056
10064
  editor: companion.editor,
10057
10065
  savedAt: companion.savedAt,
10058
10066
  basedOn: companion.basedOn,
10059
10067
  changedSince: editSha !== null && editSha !== companion.sha256,
10060
- project: companion.project && (0, import_node_fs21.existsSync)(projectPath) ? portableOutputPath(projectPath, root) : null
10068
+ project: project ? portableOutputPath(projectPath, root) : null,
10069
+ projectUrl
10061
10070
  };
10062
10071
  }
10063
10072
  const regenerated = companion ? generated?.sha256 !== void 0 && generated.sha256 !== null && companion.basedOn !== generated.sha256 : Boolean(generated?.modifiedAt && edit.modifiedAt && generated.modifiedAt > edit.modifiedAt && generated.exists);
@@ -11148,30 +11157,42 @@ function openEditorSheet(item) {
11148
11157
  stage.append(frame, loading);
11149
11158
  panel.append(bar, stage);
11150
11159
  host.append(scrim, panel);
11151
- SHEET = { item, frame, loading, status, msg, save, saveClose, dirty: false, opened: false, ready: null, pending: null, requests: 0, source: src };
11160
+ SHEET = { item, frame, loading, status, msg, save, saveClose, dirty: false, opened: false, ready: null, pending: null, requests: 0, source: src, sentProject: false };
11152
11161
  sheetStatus('cool', 'loading');
11153
11162
  sheetButtons();
11154
11163
  close.focus({ preventScroll: true });
11155
11164
  }
11165
+ // The edit file is what the editor gets; when a browser save kept the layered
11166
+ // project beside it, that goes along too and the editor restores the layers,
11167
+ // falling back to the flattened PNG if the file cannot be read.
11156
11168
  async function sendOpen() {
11157
11169
  const { item, source } = SHEET;
11158
11170
  const style = snap.styles.find((s) => s.id === item.styleId && s.project === item.project);
11159
- let png;
11171
+ const projectUrl = source === item.edit && item.editMeta && item.editMeta.projectUrl && SHEET.ready.version >= 2 ? item.editMeta.projectUrl : null;
11172
+ let png, pxo = null;
11160
11173
  try {
11161
11174
  const res = await fetch(source.url, { cache: 'no-store' });
11162
11175
  if (!res.ok) throw new Error(await res.text());
11163
11176
  png = await res.arrayBuffer();
11177
+ if (projectUrl) {
11178
+ const p = await fetch(projectUrl, { cache: 'no-store' });
11179
+ if (p.ok) pxo = await p.arrayBuffer();
11180
+ }
11164
11181
  } catch (err) {
11165
11182
  if (SHEET) { SHEET.msg.textContent = 'Could not load the image: ' + err.message; sheetStatus('bad', 'failed'); }
11166
11183
  return;
11167
11184
  }
11168
11185
  if (!SHEET) return;
11169
11186
  const request = 'open-' + (++SHEET.requests);
11170
- SHEET.frame.contentWindow.postMessage({
11187
+ SHEET.sentProject = !!pxo;
11188
+ const message = {
11171
11189
  type: 'pixelkiln:open', request,
11172
11190
  asset: { key: item.styleId + '/' + item.assetId, id: item.id, name: item.assetId, width: item.width, height: item.height },
11173
11191
  png, palette: style ? style.palette : [],
11174
- }, location.origin, [png]);
11192
+ };
11193
+ const transfer = [png];
11194
+ if (pxo) { message.pxo = pxo; transfer.push(pxo); }
11195
+ SHEET.frame.contentWindow.postMessage(message, location.origin, transfer);
11175
11196
  sheetStatus('cool', 'opening');
11176
11197
  }
11177
11198
  function requestEditorSave(close) {
@@ -11197,7 +11218,9 @@ async function onEditorMessage(m) {
11197
11218
  case 'pixelkiln:opened':
11198
11219
  SHEET.opened = true;
11199
11220
  SHEET.loading.remove();
11200
- sheetStatus('ok', SHEET.item.edit && SHEET.item.edit.exists ? 'editing the edit file' : 'editing a copy of the generated art');
11221
+ if (m.source === 'pxo') sheetStatus('ok', 'editing the edit file with its ' + (m.layers === 1 ? 'layer' : m.layers + ' layers') + ' restored');
11222
+ else if (SHEET.sentProject) sheetStatus('warn', 'editing the flattened edit file; its layer file could not be opened');
11223
+ else sheetStatus('ok', SHEET.item.edit && SHEET.item.edit.exists ? 'editing the edit file' : 'editing a copy of the generated art');
11201
11224
  sheetButtons();
11202
11225
  break;
11203
11226
  case 'pixelkiln:dirty':