OnClosing is async void, so an exception from the view model's cancel
path was unobserved and crashed the process. It is now logged and the
dialog stays open.
The window, the Windows executable and the macOS bundle now use a
placeholder kanban icon (three columns of cards) instead of the template's
avalonia-logo.ico, which had no icon at all on macOS.
The confirming button was the default, so one stray Enter deleted a card,
a column with all its cards or a tag, or discarded an edit. Enter now
answers with Cancel; the action needs an explicit click.
Every editor close rebuilt all columns, so opening a card and cancelling
reset each column's scroll position. The editor now reports whether it
saved the card or created a tag in the nested picker, and the board only
refreshes in that case.
PLAN 4.3 lets a field of the wrong type fall back to its default alone.
Newtonsoft converted such values implicitly, so "delete-card": 0 became
false and "custom-pixels": "500" became 500. Booleans, integers and
strings are now read only from tokens of exactly that type.
PLAN 4.3 writes app.json when the session modified a setting. The store
compared the live configuration with the loaded one instead, so a setting
changed and changed back was never written. Each section now records a
dirty flag in its setters; assigning the current value is not a change and
the load-time field fallbacks are cleared after reading.
PLAN 5.4 says an unchanged confirmation writes nothing, but the shortcut
applied only to existing cards, so OK on a blank new-card editor added an
empty card. A new card with no title, content or tags is now not created.
PLAN 5.6 asks for the theme to take effect immediately, but it was applied
only on OK. Selecting a theme now previews it; OK saves it, and cancel, Escape
or closing the window restores the theme the dialog opened with.
A workspace at a drive root is named "D:\", which made the suggested file name
invalid. Characters that are invalid in a file name on any supported platform are
now removed, and a name left empty (a workspace at /) falls back to YKanBan.
If the first board read failed while WorkspaceViewModel was being constructed,
the open-failed page appeared but the lock and connection stayed held until
exit, which blocked other instances. The session is now closed before the
error page is shown.
An app.json that exists but cannot be read, or a .bak that cannot be written,
now yields defaults instead of an unhandled exception before the main window
exists. A failed write at exit is logged and ignored, and the session is
disposed in a finally block, so the lock and connection are always released.
The save picker used to return only TryGetLocalPath(), so a target without a
local path looked like a cancel and nothing was written. The dialog service now
hands back an opener for the chosen file. The picker call is inside the error
handler, and the workspace is read before the target is opened, so a failed read
leaves an existing file untouched.
A failed read on a UI path (sort change, clear, refresh after a write, opening a
card, the tag picker, the tags tab) used to escape as an unhandled exception.
Reads now run before the view is cleared and report Error_Read_* instead; the
active filter changes only once its query has run. DataWritten and TagsChanged
fire only after a successful refresh, so a broken database shows one dialog.
The compiled SQL chains every atom into one expression, and SQLite rejects
expressions deeper than 1000 levels. A query of about 1000 words parsed but
then failed in SQL, outside the syntax-error handling, and crashed the app.
The parser now rejects more than 256 atoms as a syntax error.
The lexer now keeps token offsets and rejects what the grammar never allowed
but the token rules accepted:
- an empty phrase: "" (matched every card), tag:""
- a phrase touching a word or another phrase: a"b", "a"b, "a""b"
- whitespace between a qualifier and its phrase value: tag: "x"
key:"value" stays the only legal contact; parentheses still delimit phrases.
Listed in PLAN 6.1/6.2 and USAGE.
A backslash right before a pipe, as in the tag name a\|b, turned the escaped
pipe into "\|": the table splitter reads "\\" as an escaped backslash and the
pipe as a column separator, shifting the row. Cells now escape '\' before '|'.
Recorded in PLAN 5.8.
A lock conflict while initializing goes to the lock-conflict page instead of
the open-failed page; a missing ykanban.db goes to the open-failed page and is
never recreated silently.
AppendLine wrote CRLF on Windows; the document now uses LF everywhere and
converts CRLF/CR inside card bodies and column descriptions. Column titles and
the workspace name are collapsed to one line like card titles.
With .ykanban present but ykanban.db gone, opening used to create an empty
database and show an empty board without any hint. It now throws
WorkspaceDatabaseMissingException and shows the open-failed page, telling the
user to restore a backup or delete .ykanban and initialize again.
Follows PLAN 4.2: create .ykanban, take the lock, then build the database.
SqliteDatabase.Create writes every migration and the preset columns in a
single transaction and deletes the file again on failure, so no empty
version-0 database is left behind. WorkspaceSession.Initialize keeps the lock
into the session instead of releasing and re-acquiring it.
A lock conflict while initializing shows the lock-conflict page.
Deep nesting overflowed the stack of the recursive Pidgin parser (around
400-700 levels), an uncatchable crash. The depth is now checked on the token
stream before parsing and reported as a syntax error. Listed in PLAN 6.2 and
USAGE.
- macOS: document open -n -a with an absolute path (plan updated accordingly)
- package.sh: zip with 7z for '/' entry separators; ad-hoc codesign failure is a warning
- USAGE: list blank and unrepresentable paths as invalid arguments
- board: columns in id order, per-column sort via config, column width presets (240/320/480) and custom 160-720
- column header new-card and edit/delete menu; card menu delete and move-to-column
- card editor as one unit of work with dirty check and discard confirmation; nested tag picker writes new tags immediately
- schema constraint violations mapped to typed exceptions and shown inside the modal
- dialog service with owner stack so nested modals center on their parent and get FlowDirection
- repository: filtered GetCards, CountCards; view-model tests