- feat:记忆拖拽窗口大小和优化动画效果

Add persistent, robust scaling for the proportional editor and remove CSS transitions that interfered with instant restores. Introduces a storageKey, parseScale, applyScaleInstant and logic to restore scale synchronously from localStorage (for immediate UX) and asynchronously from chrome.storage.sync (best-effort), keeping localStorage in sync. Ensures pending RAF updates are flushed before persisting and guards against missing APIs or invalid values. Also removes transition properties in main.css so scale restores remain immediate and predictable.
This commit is contained in:
jonny
2026-03-09 20:00:42 +08:00
parent 2b36fda137
commit 5fac00b5ce
2 changed files with 71 additions and 3 deletions
-3
View File
@@ -44,9 +44,6 @@ a{color: #555;}
background-color: rgb(255,255,255);
margin-top:0.8rem;
padding: 0.6rem;
transition-property: all;
transition-timing-function: cubic-bezier(.4,0,.2,1);
transition-duration: .15s;
}
.memo-editor{
position: relative;
+71
View File
@@ -39,6 +39,8 @@ function initProportionalEditorResize() {
editor.style.minWidth = `${baseW}px`
editor.style.minHeight = `${baseH}px`
const storageKey = 'popupEditorScale'
let maxScale = 1
const computeMaxScale = () => {
// In popup mode, allow scaling up to Chrome's max popup size.
@@ -69,6 +71,15 @@ function initProportionalEditorResize() {
let rafId = 0
let pendingScale = null
const parseScale = (raw) => {
const s = typeof raw === 'number' && Number.isFinite(raw)
? raw
: typeof raw === 'string' && raw.trim() !== '' && !Number.isNaN(Number(raw))
? Number(raw)
: 1
return s > 0 ? s : 1
}
const readCurrentScale = () => {
const w = parseFloat(editor.style.width || '')
const h = parseFloat(editor.style.height || '')
@@ -83,6 +94,47 @@ function initProportionalEditorResize() {
editor.style.height = `${Math.round(baseH * s)}px`
}
const applyScaleInstant = (scale) => {
// In case CSS transitions exist (or get reintroduced), keep restores immediate.
const prevTransition = editor.style.transition
editor.style.transition = 'none'
applyScale(scale)
window.requestAnimationFrame(function () {
editor.style.transition = prevTransition
})
}
// Restore previously saved scale synchronously (localStorage) first.
// This makes the popup *feel* synchronous because it can apply before async chrome.storage returns.
let restoredFromLocal = false
let localScale = 1
try {
const raw = window.localStorage ? window.localStorage.getItem(storageKey) : null
const s = parseScale(raw)
if (s && s !== 1) {
localScale = s
restoredFromLocal = true
applyScaleInstant(s)
}
} catch (_) {
// ignore
}
// Restore from chrome.storage.sync (best-effort) and keep localStorage in sync.
try {
chrome.storage.sync.get({ [storageKey]: 1 }, function (items) {
const raw = items ? items[storageKey] : 1
const s = parseScale(raw)
const shouldApply = !restoredFromLocal || Math.abs(s - localScale) > 1e-6
if (shouldApply) applyScaleInstant(s)
try {
if (window.localStorage) window.localStorage.setItem(storageKey, String(s))
} catch (_) {}
})
} catch (_) {
// ignore
}
const scheduleApply = () => {
if (rafId) return
rafId = window.requestAnimationFrame(() => {
@@ -122,6 +174,25 @@ function initProportionalEditorResize() {
const endDrag = () => {
dragging = false
// Flush any pending RAF update before persisting.
if (pendingScale != null) {
applyScale(pendingScale)
pendingScale = null
}
// Persist current scale (best-effort).
try {
const s = readCurrentScale()
if (typeof s === 'number' && Number.isFinite(s)) {
try {
if (window.localStorage) window.localStorage.setItem(storageKey, String(s))
} catch (_) {}
chrome.storage.sync.set({ [storageKey]: s })
}
} catch (_) {
// ignore
}
}
handle.addEventListener('pointerup', endDrag)