clavarium 0.2.0-next.2 → 0.2.0-next.4

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.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "clavarium",
3
- "version": "0.2.0-next.2",
3
+ "version": "0.2.0-next.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "clavarium",
9
- "version": "0.2.0-next.2",
9
+ "version": "0.2.0-next.4",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@xterm/addon-fit": "^0.11.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clavarium",
3
- "version": "0.2.0-next.2",
3
+ "version": "0.2.0-next.4",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "A conversation is a VM with a terminal in it. Everything else is a folder.",
package/web/app.js CHANGED
@@ -2164,7 +2164,7 @@
2164
2164
  if (!place) { const files = el('button', '', 'Files'); files.type = 'button'; files.dataset.act = 'files'; files.addEventListener('click', () => { embedFiles(holder, name); files.disabled = true; }); acts.prepend(files); }
2165
2165
  const diagram = el('div', 'as-graph'); diagram.append(el('p', 'hint', 'Drawing the branches...'));
2166
2166
  holder.append(facts, chapter('Branches', acts), diagram);
2167
- const back = place ? { label: 'Assets', go: () => { void paintAssets(); } } : { label: 'Assets', go: () => { void paintRoomAssets(); } };
2167
+ const back = place ? { label: name, go: () => { void paintAssets(); } } : { label: 'Assets', go: () => { void paintRoomAssets(); } };
2168
2168
  review.addEventListener('click', () => { void openGit(name, { back }); });
2169
2169
  const [out, graph] = await Promise.all([getJson(`/git/${name}/outgoing`, null), getJson(`/git/${name}/graph`, null)]);
2170
2170
  facts.replaceChildren();
@@ -2253,6 +2253,7 @@
2253
2253
  function closeRoomAssets() {
2254
2254
  if (!assetsShown) return;
2255
2255
  assetsShown = false; $('cassets').hidden = true; unembedFiles(); paintViews();
2256
+ if ($('cassets').contains($('gitview'))) shutGit();
2256
2257
  }
2257
2258
 
2258
2259
  /* ---- the server's ---- */
@@ -2520,7 +2521,8 @@
2520
2521
  $('access').hidden = which !== 'access';
2521
2522
  $('settings').hidden = which !== 'settings';
2522
2523
  $('assets').hidden = which !== 'assets';
2523
- if (which !== 'conversations') { closeRoomAssets(); for (const id of ['panel', 'files', 'copy', 'gitview']) $(id).hidden = true; view('room'); }
2524
+ if (which !== 'conversations') { closeRoomAssets(); for (const id of ['panel', 'files', 'copy']) $(id).hidden = true; view('room'); }
2525
+ if (which !== 'assets' || !$('assets').contains($('gitview'))) shutGit();
2524
2526
  }
2525
2527
  function placeAddress() {
2526
2528
  const q = new URLSearchParams();
@@ -2609,6 +2611,12 @@
2609
2611
  }
2610
2612
  addEventListener('popstate', (event) => {
2611
2613
  if (DEVICE) return;
2614
+ /* Back while a review is shown: the review closes, as with its own "‹" link. */
2615
+ if (reviewInHistory && !event.state?.review) {
2616
+ reviewInHistory = false;
2617
+ const back = gitBack; shutGit(); if (back?.go) back.go(); else focusTerminal();
2618
+ return;
2619
+ }
2612
2620
  pushed = event.state?.depth ?? 0;
2613
2621
  /* Walked back on purpose (Close): the address is set to what is shown. */
2614
2622
  if (skipPop) { skipPop = false; remember(false); return; }
@@ -3269,17 +3277,40 @@
3269
3277
  if (!commit && out.state === 'ahead') await runChecks();
3270
3278
  }
3271
3279
  /* `commit`: one commit of the diagram. `back`: {label, go} -- where the page goes back to. */
3280
+ /* The review is shown inside the page it was opened from, never over it:
3281
+ in the server's Assets (its header stays), or in a conversation's Assets
3282
+ view (the list of conversations and the bar Chat | Terminal | Assets
3283
+ stay, and leave it). */
3272
3284
  async function openGit(name, { commit = '', back = null, target = '', branch = '' } = {}) {
3273
- gitShown = name; gitCommit = commit; gitAsked = target; gitAskedBranch = branch; gitBack = back; gitTab = 'changes';
3274
3285
  for (const id of ['panel', 'files']) if (!$(id).classList.contains('embedded')) $(id).hidden = true;
3275
- $('gitview').hidden = false; $('gitview').scrollTop = 0;
3286
+ let host = null;
3287
+ if (place === 'assets') host = $('assets');
3288
+ else if (!DEVICE && current) {
3289
+ /* From the chat or a sheet: the Assets view opened on it; closing gives back the view it was in. */
3290
+ if (!assetsShown) { back ??= { label: 'Back', go: () => { closeRoomAssets(); focusTerminal(); } }; roomPick = `git:${name}`; await openRoomAssets(); }
3291
+ host = $('cassets');
3292
+ }
3293
+ const g = $('gitview');
3294
+ if (host && g.parentNode !== host) host.append(g);
3295
+ g.classList.toggle('inset', Boolean(host));
3296
+ /* The device's own Back (a phone's gesture, the browser's button) closes the review: it is a step of its own in the history. */
3297
+ if (!DEVICE && !reviewInHistory) { history.pushState({ depth: pushed, review: true }, '', location.href); reviewInHistory = true; }
3298
+ gitShown = name; gitCommit = commit; gitAsked = target; gitAskedBranch = branch; gitBack = back; gitTab = 'changes';
3299
+ g.hidden = false; g.scrollTop = 0;
3276
3300
  await paintGit();
3277
3301
  }
3302
+ /* Left without its own button (Chat, Terminal, another conversation, another place). */
3303
+ let reviewInHistory = false;
3304
+ function shutGit() {
3305
+ $('gitview').hidden = true; gitShown = ''; gitBack = null;
3306
+ /* Closed by a click: its step in the history stays, as the place it was opened from. */
3307
+ if (reviewInHistory) { reviewInHistory = false; if (history.state?.review) history.replaceState({ depth: history.state.depth ?? 0 }, '', location.href); }
3308
+ }
3278
3309
  for (const b of $('gitview-tabs').querySelectorAll('[data-tab]')) b.addEventListener('click', () => { gitTab = b.dataset.tab; paintReviewTab(); });
3279
3310
  for (const b of $('gitview-layout').querySelectorAll('[data-layout]')) b.addEventListener('click', () => { gitLayout = b.dataset.layout; paintReviewTab(); drawDiff(gitText.replace(/\n$/, '')); });
3280
3311
  for (const b of $('gitview-picker').querySelectorAll('[data-step]')) b.addEventListener('click', () => { showFile(gitFile + Number(b.dataset.step)); $('gitview-diff').scrollIntoView({ block: 'start' }); });
3281
- $('gitview-set-remote').addEventListener('click', () => { const name = gitShown; $('gitview').hidden = true; gitShown = ''; void openAssetsPlace(`git:${name}`, { remote: true }); });
3282
- $('gitview-close').addEventListener('click', () => { $('gitview').hidden = true; gitShown = ''; const back = gitBack; gitBack = null; if (back?.go) back.go(); else focusTerminal(); });
3312
+ $('gitview-set-remote').addEventListener('click', () => { const name = gitShown; shutGit(); void openAssetsPlace(`git:${name}`, { remote: true }); });
3313
+ $('gitview-close').addEventListener('click', () => { const back = gitBack; shutGit(); if (back?.go) back.go(); else focusTerminal(); });
3283
3314
  $('gitview-again').addEventListener('click', () => { void paintGit(); });
3284
3315
  $('gitview-check').addEventListener('click', () => { void runChecks(); });
3285
3316
  $('gitview-branch').addEventListener('change', () => { gitAskedBranch = $('gitview-branch').value; gitAsked = ''; void paintGit(); });
package/web/style.css CHANGED
@@ -1132,6 +1132,9 @@ header .ic, #folders .ic { width: 18px; height: 18px; fill: none; stroke: curren
1132
1132
 
1133
1133
  /* ---------- THE REVIEW (E) ---------- */
1134
1134
  .review { position: fixed; inset: 0; z-index: 30; overflow-y: auto; background: var(--bg); padding: 14px 20px 40px; display: flex; flex-direction: column; gap: 10px; }
1135
+ /* Inside the page it was opened from: the conversation's Assets view, or the server's Assets below its header. */
1136
+ .review.inset { position: static; inset: auto; z-index: auto; flex: 1 1 auto; min-height: 0; }
1137
+ :is(#cassets, #assets):has(> .review:not([hidden])) > .as { display: none; }
1135
1138
  .rv-head { display: flex; align-items: center; gap: 10px 14px; flex-wrap: wrap; }
1136
1139
  .rv-head > b { font-size: 1.375rem; overflow-wrap: anywhere; }
1137
1140
  .rv-branches { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }