Notes block editor overhaul: GroupBlock, multi-select, drag-to-split, list sub-blocks
Details
Phase 1 - Fix UTI drag error: Replace bare "PageBlock" drag format key with
reverse-DNS "com.privstack.pageblock" constant to fix macOS UTI validation error.
Phase 2 - Fix child block alignment: Remove 24px left indent from ChildBlocksHost
so nested block text aligns with parent title text.
Phase 3 - GroupBlock: New container block type for organizing related blocks.
Includes GroupBlock model with label/collapse/children, serialization support,
GroupBlockEditor control with collapse toggle and add-block button, picker entry.
Phase 4 - Multi-select: Shift+Click range select, Cmd+Click toggle select.
MultiBlockSelection model tracks selected indices with anchor. Context menu
shows Group Selected / Delete Selected / Move Up / Move Down when multi-selected.
Phase 5 - Drag-to-split columns: Center-zone drop creates ColumnLayoutBlock
with both blocks side-by-side (50/50). Tables/TOC refuse split and fall back
to reorder. BlockTemplateFactory extracts shared block DataTemplates used by
ColumnLayoutEditor, GroupBlockEditor (replaces limited Paragraph/Heading-only
inline templates with full block type support).
Phase 6 - List sub-blocks: BulletListEditor, NumberedListEditor, TaskListEditor
now render PageListItem.ChildBlocks via BlockTemplateFactory. BlockTreeHelper
CollectBlockText extended to traverse list item ChildBlocks for word count.
Version: 1.62.3 → 1.63.0
Add HTTP integration tests for ICS fetch and RSS fetch services
Details
Refactored IcsFetchService and RssParserService to accept HttpClient
via internal constructor (with InternalsVisibleTo for test projects),
enabling mock HTTP transport in tests.
IcsFetchServiceTests (8 tests): ETag/If-None-Match headers, 304 Not
Modified returns null, multi-event parsing, error handling.
RssFetchServiceTests (11 tests): RSS and Atom feed parsing, article
URL/read/star extraction, refresh deduplication by URL, custom title
preservation, network error handling.
Add integration tests for GitHubIssueSyncService (28 tests)
Details
Extract IGitHubIssueApiClient interface from the sealed GitHubIssueApiClient
to enable mocking the HTTP layer in tests. The sync service constructor now
accepts the interface instead of the concrete class.
Tests cover the full sync orchestration:
- Source validation and access token retrieval
- Pull sync: new issues create tasks, remote-newer updates existing tasks
- Push sync: local-newer pushes to GitHub (bidirectional only), skips for pull-only
- Conflict resolution: same-timestamp skips, last-write-wins by updated_at
- Orphan handling: full sync marks missing open tasks as done, incremental skips
- Comment sync with deduplication by GitHubCommentId
- Timeline event sync with untracked event filtering
- Filter resolution (assignee "me" → username, labels joined with comma)
- Source status updates on success and error
- Cancellation token propagation
- Progress reporting
- Tasks from other sources are not affected by sync
- PushTaskAsync: bidirectional push, pull-only skip, non-GitHub task skip,
missing task/source ref handling
Add shared test infrastructure and Phase 1 plugin unit tests (259 tests)
Details
Phase 0: Shared test infrastructure
- PrivStack.TestUtilities class library with GenericMockSdk (registration-based
entity routing), MockSdkExtensions (Seed, AssertStored, AssertActionSent),
and shared TestAppBuilder for Avalonia headless testing
- Living design doc (TESTING_STRATEGY.md) with full test plan across 4 phases
Phase 1: Pure logic tests (no SDK dependency)
- Calendar: RecurrenceGeneratorTests (49 tests) — daily/weekly/monthly/yearly
patterns, end conditions, excluded dates, exception events, DST, safety limits
- Calendar: IcsParserTests — RFC 5545 parsing, date formats, RRULE, export roundtrip
- Habits: StreakCalculatorTests (23 tests) — boolean/numeric/duration streaks,
frequency-aware gaps, completion rate, sparkline data, performance
- Email: HtmlSanitizerTests (44 tests) — element/attribute stripping, XSS vectors,
CID replacement, tracking pixels, media queries, constraint CSS
- Email: EmailThreadingServiceTests (12 tests) — MessageId chains, subject fallback,
circular reference protection, deduplication
- Notes: MarkdownBlockParserTests, BlockTreeHelperTests, LinkSearchScorerTests
(60 tests) — all 23 block types, tree traversal/mutation, fuzzy search scoring
- Contacts: VCardParserTests (20 tests) — vCard 2.1/3.0, QP encoding, types, bday
- Contacts: CsvContactParserTests (7 tests) — delimiter detection, header mapping
- Tasks: GitHubIssueFieldMapperTests (22 tests) — state/priority mapping, parsing
- Data: ContextDetectorTests + ProblemDetectorTests (19 tests) — SQL cursor context,
schema validation, ambiguous columns
- Journal: GpxParserTests (7 tests) — GPX 1.0/1.1, Haversine distance
- RSS: OpmlTests (7 tests) — OPML parse/export roundtrip
InternalsVisibleTo added to Contacts and Email plugins for test access.
Add Notes plugin unit tests for parser, tree helper, and search scorer
Details
Add three test files covering the core Notes plugin service classes:
- MarkdownBlockParserTests (24 tests): ATX/setext headings, paragraphs,
bullet/numbered/task lists, fenced code, blockquotes, horizontal rules,
images, footnotes, callouts, indents, tables, definition lists, mixed
content, and unique ID generation.
- BlockTreeHelperTests (14 tests): FindBlockById, GetBlockAtPath,
GetParentList, FlattenTree, IndentBlock, OutdentBlock, CollectBlockText
across nested block tree structures.
- LinkSearchScorerTests (12 tests): empty query, exact/prefix/fuzzy match,
case insensitivity, multi-word scoring, subtitle contribution, starts-with
bonus, and short-word fuzzy tolerance threshold.
Also adds InternalsVisibleTo attribute to Notes plugin csproj to expose
internal static classes (MarkdownBlockParser, LinkSearchScorer) to the
test project.
Get notified about new releases