Luca448 commited on
Commit
9eab501
·
1 Parent(s): 93eb5ad

Savestate: Revert cinematic animation to top/left/width for smoother trajectory, and add drag support to popover, bump version to 1.8.25

Browse files
Files changed (2) hide show
  1. index.html +1 -1
  2. src/views/documents/documents-view.js +82 -22
index.html CHANGED
@@ -51,7 +51,7 @@
51
  </head>
52
  <body class="dark-theme in-chat-view">
53
 
54
- <div id="live-version-badge" style="position: fixed; top: 50px; left: 50%; transform: translateX(-50%); font-size: 10px; color: var(--text-secondary); opacity: 0.6; z-index: 99999; pointer-events: none; font-weight: 500; font-family: monospace; letter-spacing: 1px; background: rgba(0,0,0,0.2); padding: 2px 8px; border-radius: 10px; border: 1px solid rgba(255,255,255,0.05);">BUILD 1.8.24</div>
55
 
56
  <!-- SVG Filters for Liquid Glass Refraction -->
57
  <svg width="0" height="0" style="position: absolute; pointer-events: none;">
 
51
  </head>
52
  <body class="dark-theme in-chat-view">
53
 
54
+ <div id="live-version-badge" style="position: fixed; top: 50px; left: 50%; transform: translateX(-50%); font-size: 10px; color: var(--text-secondary); opacity: 0.6; z-index: 99999; pointer-events: none; font-weight: 500; font-family: monospace; letter-spacing: 1px; background: rgba(0,0,0,0.2); padding: 2px 8px; border-radius: 10px; border: 1px solid rgba(255,255,255,0.05);">BUILD 1.8.25</div>
55
 
56
  <!-- SVG Filters for Liquid Glass Refraction -->
57
  <svg width="0" height="0" style="position: absolute; pointer-events: none;">
src/views/documents/documents-view.js CHANGED
@@ -488,19 +488,23 @@ export class DocumentsView {
488
  folderEl.style.position = 'fixed';
489
  folderEl.style.top = rect.top + 'px';
490
  folderEl.style.left = rect.left + 'px';
491
- folderEl.style.width = rect.width + 'px';
492
- folderEl.style.zIndex = '100';
493
-
494
- // Set random rotation
495
- const randomRot = (Math.random() > 0.5 ? 1 : -1) * (8 + Math.random() * 8);
496
- folderEl.dataset.rot = randomRot;
497
-
498
- // Combine everything into a single transform
499
- folderEl.style.setProperty('--target-transform', `translate(${translateX}px, ${translateY}px) scale(${scale}) rotate(${randomRot}deg)`);
500
 
501
  folderEl.classList.remove('vault-folder-pressing');
502
  folderEl.classList.add('vault-folder-detail');
503
 
 
 
 
 
 
 
 
 
 
504
  // 4. Update ambient title
505
  const titleEl = document.querySelector('.vault-ambient-title');
506
  if (titleEl) titleEl.textContent = folderName;
@@ -619,6 +623,7 @@ export class DocumentsView {
619
 
620
  // 3. Get fresh layout position in case of scroll
621
  folderEl.classList.remove('vault-folder-detail');
 
622
  folderEl.style.position = '';
623
  folderEl.style.top = '';
624
  folderEl.style.left = '';
@@ -627,30 +632,34 @@ export class DocumentsView {
627
 
628
  const freshRect = folderEl.getBoundingClientRect();
629
 
630
- // RECALCULATE --target-transform so it doesn't jump!
 
 
 
631
  const targetWidth = window.innerWidth * 0.5;
632
  const targetTop = window.innerHeight - (targetWidth * 1.3) - 120;
633
  const targetLeft = window.innerWidth * 0.05;
634
- const scale = targetWidth / freshRect.width;
635
- const translateX = targetLeft - freshRect.left;
636
- const translateY = targetTop - freshRect.top;
637
- const randomRot = folderEl.dataset.rot || -12;
638
 
639
- folderEl.style.setProperty('--target-transform', `translate(${translateX}px, ${translateY}px) scale(${scale}) rotate(${randomRot}deg)`);
 
 
640
 
641
- // Put back to fixed detail state instantly
642
- folderEl.style.position = 'fixed';
643
- folderEl.style.top = freshRect.top + 'px';
644
- folderEl.style.left = freshRect.left + 'px';
645
- folderEl.style.width = freshRect.width + 'px';
646
  folderEl.classList.add('vault-folder-detail');
 
 
 
647
 
648
  // Force reflow
649
  folderEl.offsetHeight;
650
 
651
- // Now animate smoothly
652
- folderEl.style.transition = 'transform 0.45s cubic-bezier(.22,.68,0,1.1)';
 
 
 
 
653
  folderEl.classList.remove('vault-folder-detail');
 
654
 
655
  await this._wait(450);
656
 
@@ -1097,6 +1106,51 @@ export class DocumentsView {
1097
 
1098
  popover.style.top = `${top}px`;
1099
  popover.style.left = `${left}px`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1100
 
1101
  popover.querySelector('#popover-save').addEventListener('click', () => {
1102
  const newColor = popover.querySelector('#popover-color').value;
@@ -1106,9 +1160,15 @@ export class DocumentsView {
1106
  });
1107
 
1108
  const closePopover = (e) => {
 
 
1109
  if (!popover.contains(e.target) && !btnEl.contains(e.target)) {
1110
  popover.remove();
1111
  document.removeEventListener('click', closePopover);
 
 
 
 
1112
  }
1113
  };
1114
  setTimeout(() => {
 
488
  folderEl.style.position = 'fixed';
489
  folderEl.style.top = rect.top + 'px';
490
  folderEl.style.left = rect.left + 'px';
491
+ // Combine everything into a single transform for rotation ONLY
492
+ folderEl.style.setProperty('--folder-rot', `${randomRot}deg`);
493
+ if (randomRot < 0) folderEl.classList.add('tilt-left');
494
+ else folderEl.classList.add('tilt-right');
 
 
 
 
 
495
 
496
  folderEl.classList.remove('vault-folder-pressing');
497
  folderEl.classList.add('vault-folder-detail');
498
 
499
+ // Force reflow
500
+ folderEl.offsetHeight;
501
+
502
+ // Animate to detail position using top, left, width
503
+ folderEl.style.transition = 'top 0.45s cubic-bezier(.22,.68,0,1.1), left 0.45s cubic-bezier(.22,.68,0,1.1), width 0.45s cubic-bezier(.22,.68,0,1.1), transform 0.45s cubic-bezier(.22,.68,0,1.1)';
504
+ folderEl.style.top = targetTop + 'px';
505
+ folderEl.style.left = targetLeft + 'px';
506
+ folderEl.style.width = targetWidth + 'px';
507
+
508
  // 4. Update ambient title
509
  const titleEl = document.querySelector('.vault-ambient-title');
510
  if (titleEl) titleEl.textContent = folderName;
 
623
 
624
  // 3. Get fresh layout position in case of scroll
625
  folderEl.classList.remove('vault-folder-detail');
626
+ folderEl.classList.remove('tilt-left', 'tilt-right');
627
  folderEl.style.position = '';
628
  folderEl.style.top = '';
629
  folderEl.style.left = '';
 
632
 
633
  const freshRect = folderEl.getBoundingClientRect();
634
 
635
+ // Put back to fixed detail state instantly
636
+ folderEl.style.position = 'fixed';
637
+
638
+ // Restore current detail position before animating
639
  const targetWidth = window.innerWidth * 0.5;
640
  const targetTop = window.innerHeight - (targetWidth * 1.3) - 120;
641
  const targetLeft = window.innerWidth * 0.05;
 
 
 
 
642
 
643
+ folderEl.style.top = targetTop + 'px';
644
+ folderEl.style.left = targetLeft + 'px';
645
+ folderEl.style.width = targetWidth + 'px';
646
 
 
 
 
 
 
647
  folderEl.classList.add('vault-folder-detail');
648
+ const rot = folderEl.dataset.rot || -12;
649
+ if (rot < 0) folderEl.classList.add('tilt-left');
650
+ else folderEl.classList.add('tilt-right');
651
 
652
  // Force reflow
653
  folderEl.offsetHeight;
654
 
655
+ // Now animate smoothly back to grid rect
656
+ folderEl.style.transition = 'top 0.45s cubic-bezier(.22,.68,0,1.1), left 0.45s cubic-bezier(.22,.68,0,1.1), width 0.45s cubic-bezier(.22,.68,0,1.1), transform 0.45s cubic-bezier(.22,.68,0,1.1)';
657
+ folderEl.style.top = freshRect.top + 'px';
658
+ folderEl.style.left = freshRect.left + 'px';
659
+ folderEl.style.width = freshRect.width + 'px';
660
+
661
  folderEl.classList.remove('vault-folder-detail');
662
+ folderEl.classList.remove('tilt-left', 'tilt-right');
663
 
664
  await this._wait(450);
665
 
 
1106
 
1107
  popover.style.top = `${top}px`;
1108
  popover.style.left = `${left}px`;
1109
+ popover.style.touchAction = 'none'; // Prevent scrolling while dragging
1110
+
1111
+ // --- Drag Support ---
1112
+ let isDragging = false;
1113
+ let dragStartX = 0;
1114
+ let dragStartY = 0;
1115
+ let popoverStartLeft = 0;
1116
+ let popoverStartTop = 0;
1117
+
1118
+ const dragStart = (e) => {
1119
+ // Don't drag if clicking inside input/button/grid
1120
+ if (e.target.closest('input, button, .icon-grid-item')) return;
1121
+
1122
+ isDragging = true;
1123
+ const clientX = e.touches ? e.touches[0].clientX : e.clientX;
1124
+ const clientY = e.touches ? e.touches[0].clientY : e.clientY;
1125
+ dragStartX = clientX;
1126
+ dragStartY = clientY;
1127
+ popoverStartLeft = parseFloat(popover.style.left);
1128
+ popoverStartTop = parseFloat(popover.style.top);
1129
+ };
1130
+
1131
+ const dragMove = (e) => {
1132
+ if (!isDragging) return;
1133
+ e.preventDefault(); // Stop scrolling
1134
+ const clientX = e.touches ? e.touches[0].clientX : e.clientX;
1135
+ const clientY = e.touches ? e.touches[0].clientY : e.clientY;
1136
+ const dx = clientX - dragStartX;
1137
+ const dy = clientY - dragStartY;
1138
+ popover.style.left = `${popoverStartLeft + dx}px`;
1139
+ popover.style.top = `${popoverStartTop + dy}px`;
1140
+ };
1141
+
1142
+ const dragEnd = () => {
1143
+ isDragging = false;
1144
+ };
1145
+
1146
+ popover.addEventListener('mousedown', dragStart);
1147
+ document.addEventListener('mousemove', dragMove);
1148
+ document.addEventListener('mouseup', dragEnd);
1149
+
1150
+ popover.addEventListener('touchstart', dragStart, { passive: false });
1151
+ document.addEventListener('touchmove', dragMove, { passive: false });
1152
+ document.addEventListener('touchend', dragEnd);
1153
+ // --------------------
1154
 
1155
  popover.querySelector('#popover-save').addEventListener('click', () => {
1156
  const newColor = popover.querySelector('#popover-color').value;
 
1160
  });
1161
 
1162
  const closePopover = (e) => {
1163
+ // Don't close if we were just dragging
1164
+ if (isDragging) return;
1165
  if (!popover.contains(e.target) && !btnEl.contains(e.target)) {
1166
  popover.remove();
1167
  document.removeEventListener('click', closePopover);
1168
+ document.removeEventListener('mousemove', dragMove);
1169
+ document.removeEventListener('mouseup', dragEnd);
1170
+ document.removeEventListener('touchmove', dragMove);
1171
+ document.removeEventListener('touchend', dragEnd);
1172
  }
1173
  };
1174
  setTimeout(() => {