Skip to content

Save & Undo

Save and Push are separate operations with separate snapshots.

  • Save persists the full config (all themes) to figma.root.pluginData("systema_config") — file-level storage, shared across all users of the file. Does not touch Figma variables. The shortcut is ⌥S (Alt+S).
  • Push Vars is described in the previous section. It always saves the config as step 1, but the inverse isn't true — saving doesn't push. The shortcut is ⌥P (Alt+P).
  • Autosave is an optional Settings dialog setting, off by default. When enabled it calls Save on a timer (interval 10–600 s, default 60 s) while the current theme is dirty — another save trigger.
  • Undo/Redo operates on per-theme stacks, each capped at the last 4 checkpoints (.slice(-4)). The controls appear in the status bar as buttons labeled "Prev save" and "Next save" (not "Undo"/"Redo"). Each Save (and each Push Vars, which saves first) pushes the previous saved state onto the undo stack and clears the redo stack; Undo restores the previous saved state, Redo moves forward. Switching themes swaps stacks, so each theme's history is independent. (Reset to defaults also pushes a checkpoint, so it's undoable.)
  • isDirty = current theme JSON ≠ lastSavedJsons[themeId]. Disables Save when clean.
  • isPushNeeded = current theme JSON ≠ lastPushedJsons[themeId]. Disables Push Vars when clean. Re-evaluated on every theme switch (per-theme), so flipping between themes reflects each one's own push state.
  • Optimistic push snapshot — when Push Vars is clicked, the UI stores pendingPushSnapshot = { themeId, themeJson } and sends apply-palette to the backend. lastPushedJsons and isPushNeeded are NOT updated at this moment. The backend's push-complete { success } message decides: on success → promote the snapshot into lastPushedJsons; on cancel/abort → discard. This is why cancelling the replace-theme dialog leaves Push Vars active instead of looking like the push succeeded.
  • Plugin-load reconcile — on startup handleLoadConfig posts the list of existing Figma collection names alongside config-loaded. The UI checks for any Systema-shape collection name (meta, color, color/meta, color/..., …/meta (legacy prefixed meta collections — names ending in /meta) or legacy {prefix}/color/...). If none are present, every lastPushedJsons entry is dropped and isPushNeeded flips to true. The backend also emits a last-pushed message read from systema_pushed; that narrows the reconcile to just the theme currently in the file.
  • Config is also auto-saved to pluginData at the start of every Push Vars.