Skip to content

โ† All Skills Knowledge History

Per-memo .txt import-into-form and single-memo export inside the add/edit modal

completed๐Ÿ“ฆ my-memo๐Ÿ‘ค YCEJ9999๐Ÿ—“ 2026-06-21 09:00:00

memoimport-exportuseFileSystemAccessform-prefillui-refactorscope-correction

Request

  • Not an all-memos backup: when adding a memo, let the user import a .txt to FILL the form instead of typing.
  • In the same add/edit modal, export the single memo being edited as a .txt.
  • Update Mono Skills.

Summary

Per-memo .txt import-into-form + single-memo export (inside the add/edit modal)

Corrects the earlier "all-memos backup" design. The real requirement: when adding a memo the user can import a .txt to fill the form (instead of typing), and from the same add/edit modal they can export the single memo being edited as a .txt.

Scope correction (the lesson)

"Downloadable .txt / backup" was first built as an all-memos backup/restore (toolbar, then a dedicated modal). The user actually meant per-memo, in the edit/add modal: import fills the open form; export downloads just the current memo. Removed the whole all-memos path: backupOpen + the dedicated backup modal + the "Cadangan & Impor" toolbar button, the exportBackup/importBackup functions, serializeMemos/backupFileName in utils, and the store.importMemos action. Net code shrank.

What it does now

  • Two buttons in the add/edit modal footer (left of Batal/Simpan): Impor .txt and Ekspor .txt.
  • Import = prefill the form, not create. importMemo() reads a .txt (via useFileSystemAccess.open() or the hidden-input fallback), parses the first memo, and writes its title/content/category/pinned onto store.input. The user reviews and then Simpan as usual (the store assigns id + timestamps on save). Importantly it sets the form ref fields, it does NOT push to the list.
  • Export = the current form memo. exportMemo() serializes store.input (guard: needs a title or content) and saves via saveAs({ suggestedName }), falling back to a Blob/anchor download. Filename is a slug of the title: memo-<slug>.txt.

Reused mechanics (unchanged from the FSA session)

  • useFileSystemAccess({ dataType: 'Text' }); isSupported/data are refs (.value); guard isSupported.value with a Blob-download / hidden <input type=file> fallback; swallow the picker-cancel AbortError.
  • Same human-readable round-trip block (===== MEMO ===== header lines + ----- ISI ----- body), now emitted one block per file by serializeMemo(memo); parseMemos is reused and also accepts a plain .txt (first line = title, rest = content), so importing an arbitrary text file works.

Files

  • src/composables/use-memo-utils.ts โ€” replaced serializeMemos/backupFileName with serializeMemo(memo) + memoFileName(memo); kept parseMemos.
  • src/stores/use-memo.ts โ€” removed importMemos (no longer needed; the page writes store.input).
  • src/pages/memo/index.vue โ€” exportMemo() / importMemo() / applyImported(); modal-footer buttons; removed the dedicated backup modal + toolbar button.

Outcome

successvite module transform + wiring grep /memo, page, store, and use-memo-utils.ts transform 200 Page exposes exportMemo/importMemo/applyImported; utils export serializeMemo/parseMemos/memoFileName All all-memos remnants removed (backupOpen, exportBackup/importBackup, serializeMemos, store.importMemos, the dedicated backup modal + toolbar button)

Decisions

Import PREFILLS the form, it does not create a memo

importMemo() parses the .txt and writes title/content/category/pinned onto store.input; the user then saves normally.

Why: User wanted to 'import instead of typing' while adding โ€” so the file populates the open form and stays editable/reviewable before Simpan. Creation (id + timestamps) still happens in store.save().

Per-memo export from the edit/add modal, not an all-memos backup

exportMemo() serializes only store.input (the open memo) to memo-<title-slug>.txt.

Why: User corrected the earlier all-memos backup: they want to export the single memo being edited, from the same modal.

Removed the all-memos backup path entirely

Deleted the dedicated backup modal, the toolbar button, serializeMemos/backupFileName, and store.importMemos.

Why: It was a misinterpretation of 'backup'. Keeping dead code would confuse the next session; the per-memo design fully covers the actual need.

Kept the round-trip block format + parseMemos

serializeMemo emits one ===== MEMO ===== block; parseMemos is reused (handles one/many blocks and plain text).

Why: Preserves category/pinned/timestamps on re-import and still lets an arbitrary .txt import as a memo (first line = title).

Files changed

FileOperationNote
src/composables/use-memo-utils.tsmodifiedReplaced serializeMemos/backupFileName with serializeMemo(memo) (single block) + memoFileName(memo) (title slug); kept parseMemos (reused for single import + plain-text)
src/stores/use-memo.tsmodifiedRemoved importMemos action (no longer used; the page prefills store.input directly)
src/pages/memo/index.vuemodifiedAdded exportMemo()/importMemo()/applyImported(); Impor .txt + Ekspor .txt buttons in the add/edit modal footer; import prefills the form fields; removed the all-memos backup modal, toolbar button, and exportBackup/importBackup

Commands

pnpm dev
curl /memo + page + store + use-memo-utils.ts (all 200)
MONO_SKILLS=true MONO_SKILLS_GITHUB_TOKEN=[REDACTED] pnpm exec mono skills save --app my-memo --dir .mono/skills/pending/<id>

Validation

Tests: not run Build: passed


โ† All Skills Knowledge History