Commit graph

6 commits

Author SHA1 Message Date
lin onetwo
4c5e1d16c7
Fix/misc bug (#691)
* Use git service for backups and dynamic AI menus

Switch backup actions to call gitService.commitAndSync(commitOnly) so local backups work without remote auth and AI commit generation is triggered by omitting commitMessage. Make AI-related menu items always registered but use dynamic visibility/enabled checks (isAIEnabled) so they appear/disappear at runtime. Update menu item types/imports accordingly. Optimize workspace persistence to write only the single updated workspace to settings.json (stripping syncable fields when tidgi.config exists) instead of saving all workspaces; remove the old saveWorkspacesToSettings method. Add warnings/logging: warn if git worker observable is undefined, log/notify when cloud sync is skipped due to missing auth/gitUrl. Misc: remove a redundant debug log in tidgiConfig, remove native process monitoring startup call, include commitMessage for CommitDetailsPanel sync, and drop entriesFingerprint/debug noise from git log data.

* fix: avoid rewriting unchanged workspace config

* fix: separate plain and ai backup flows

* feat: add searchable settings views

* fix: narrow sync adaptor revision type

* chore: release tidgi-shared 0.1.3

* Preferences: unify Scheduled/Background tasks and fix skeleton nav

- Remove legacy background task UI/dialogs (use ScheduledTask unified system)
- Attach invisible anchors to skeleton placeholders so sidebar scrollIntoView works while loading
- Add English/zh translation keys for AddAlarm/AddHeartbeat
- Add requestIdleCallback polyfill (tests) and speed up to 0ms for tests
- Search: match English translations (txEn) in SearchResultsView

* Fix view zero-size on minimize; realign on restore/show

Guard view bounds from 0x0 content size to prevent BrowserView disappearing when window is minimized; fall back to safe offscreen size. Add window 'restore' and 'show' handlers to realign views. Add getMemoryUsage() in wiki worker and expose RSS/heap via getWorkersInfo; show worker memory in Developer Tools diagnostics.

* Fix background/quit behavior: synchronous close handler; platform-specific runOnBackground default; add getWindowMetaSync; add forced-exit timeout for before-quit cleanup

* Refactor preferences: add definitions and registry

Add a new structured preferences system: introduce definition schemas, typed item/section types, explicit section files, a registry (allSections/sectionById), side effects, action handlers, and helper builders (zodPreferencesSchema). Add custom preference UI items and registration (customItems, registerCustomSections) and tests validating schemas. Replace previous zod/settings schema files with the new definitions and make IPreferences an explicit TypeScript interface. Small UI updates: use LanguageSelectorItem and WikiUserNameItem in Guide and Help pages. Also remove net.isOnline() pre-checks from Git.commitAndSync and Git.forcePull to avoid false-negative network detections.

* Fix blank wiki after hide+reopen: re-attach orphaned views on realign

Root cause: three compounding issues when the main window is hidden and then re-shown via a second-instance shortcut click.

1. getView() now auto-removes stale entries whose webContents.isDestroyed() == true.
   This allows addView() / showWorkspaceView() to recreate destroyed views instead of
   silently skipping them (which left the new window blank).

2. realignView() now calls browserWindow.contentView.addChildView(view) before setBounds().
   If a view survived window destruction but became orphaned (detached from its parent
   BrowserWindow), re-attaching it makes it visible again.  addChildView is idempotent
   so normal re-entrant calls are safe.

3. window.open() existing-window branch now calls addViewForAllBrowserViews(activeWorkspace)
   before realignActiveWorkspace(). This ensures that any destroyed/missing view is
   recreated BEFORE the realign attempts to reposition it.  The call is a no-op when
   views already exist and are healthy.

* Fix blank WebContentsView after restoring hidden window (Windows bug)

Electron on Windows sometimes fails to repaint a WebContentsView that remains attached to a window that is hidden and then shown again. By unconditionally calling \
emoveChildView\ followed by \ddChildView\ during \
ealignView\ and \showView\, we force the Chromium compositor to reparent and paint the view correctly, ensuring the Wiki becomes visible as soon as the user restores the app from the background.

* Fix blank WebView on window restore: show view before realign, fix same-workspace click

Two root causes identified and fixed:

1. openWorkspaceTiddler silently skipped setActiveWorkspaceView when the user
   clicked the already-active workspace icon (guard: oldId !== newId).  The view
   was blank and clicking its icon did nothing.  Guard removed  setActiveWorkspaceView
   is now always called; it is safe with the same ID (hibernation guard is already
   correct for that case).

2. The 'show' event handler and window.open() existing-window path were calling
   realignActiveWorkspace() which only calls setBounds.  On Windows, when a window
   transitions from hidden/background to visible the Chromium compositor may not
   repaint a WebContentsView whose bounds have not changed.  Both paths now call
   refreshActiveWorkspaceView()  a new lightweight helper that calls showView()
   (removeChildView + addChildView + setBounds + webContents.focus) before realigning.
   This forces a compositor repaint and makes the wiki page visible immediately.

* Refactor view restore chain: clean up redundant repaint/realign calls

Full chain analysis identified 4 structural problems:

1. refreshActiveWorkspaceView() called TWICE concurrently on window restore:
   window.open() called existedWindow.show() which fired the 'show' event
    refreshActiveWorkspaceView() AND THEN immediately called refreshActiveWorkspaceView()
   again explicitly, creating a race condition on removeChildView+addChildView.

2. realignView() contained removeChildView+addChildView, which ran immediately after
   showView() already did removeChildView+addChildView+setBounds+focus.  The second
   remove+add clobbered the focus state set by showView, breaking keyboard focus.

3. setActiveWorkspaceView() called showWorkspaceView + realignActiveWorkspace, meaning
   the view was remove+add+setBounds+focused by showView, then immediately remove+add+
   setBounds-without-focus again by realignView.  Double bounds, lost focus.

4. Same pattern in refreshActiveWorkspaceView: showWorkspaceView + realignActiveWorkspace.

Clean design after refactor:
- showView()        = force-repaint path: remove+add+setBounds+focus (unchanged)
- realignView()     = bounds-only:        setBounds ONLY, no remove+add
- showWorkspaceView = calls showView for main+mini windows
- realignActiveWorkspace = calls realignView (now just setBounds) + buildMenu;
                     used for fullscreen/sidebar/resize events
- setActiveWorkspaceView = showWorkspaceView + buildMenu (not +realignActiveWorkspace)
- refreshActiveWorkspaceView = showWorkspaceView + buildMenu (not +realignActiveWorkspace);
                     called from 'show' window event (fire-and-forget: no rethrow)
- window.open() existing-window = show() only; 'show' event handler calls
                     refreshActiveWorkspaceView automatically, no duplicate call

* chore: bump electron-ipc-cat to 2.4.0

Rolling Observable timeout (120s initial, 60s idle) fixes git-upload-pack
timeout for large repos (100+ MB) during mobile sync.

* style: unify layout between Preferences and EditWorkspace

Use PageRoot and PageInner from PreferenceComponents to eliminate subtle padding/background differences. Resize EditWorkspace window to match Preferences. Clean up lint errors.

* Add E2E test for window-restore blank-view bug + log markers

Two changes:

1. Log markers added to aid diagnosis and enable E2E verification:
   - [test-id-VIEW_SHOWN]             in ViewService.showView()
   - [test-id-REFRESH_ACTIVE_VIEW_START/DONE] in WorkspaceView.refreshActiveWorkspaceView()

2. New E2E feature: features/windowRestore.feature
   Scenario 1: 'Wiki WebContentsView is visible immediately after restoring hidden window'
     - hides main window (same path as close+runOnBackground)
     - triggers second-instance via app.emit('second-instance')
     - asserts [test-id-REFRESH_ACTIVE_VIEW_DONE] and [test-id-VIEW_SHOWN] log markers
     - asserts browser view is within visible window bounds
     - asserts wiki content is readable
   Scenario 2: 'Clicking already-active workspace icon re-shows the WebContentsView'
     - verifies the removed oldId !== newId guard: clicking current workspace must
       now call setActiveWorkspaceView which fires showView

   Two step definitions added to features/stepDefinitions/application.ts:
   - 'I hide the main window as if closing with runOnBackground'
     calls BrowserWindow.hide() directly in main process
   - 'I reopen the main window as second instance would'
     emits app 'second-instance' event in main process

* Fix E2E test: correct second-instance emit args, add wiki-ready wait in Background

Three issues found and fixed by running the tests:

1. app.emit('second-instance') argument order wrong
   DeepLinkService listener: (_event, commandLine) => commandLine.pop()
   Our emit: app.emit('second-instance', [], process.cwd(), {})
   This made 'process.cwd()' land in commandLine, .pop() failed on a string.
   Fix: app.emit('second-instance', {}, [], '', {})  fake Event first,
   then empty argv array, then workingDirectory.

2. In test mode, window.open() skips existedWindow.show() to avoid UI popups.
   The 'show' event never fired so refreshActiveWorkspaceView was never called
   and the window stayed hidden from Playwright's perspective.
   Fix: explicitly call mainWindow.show() via app.evaluate() after emitting
   second-instance, replicating what production window.open() does.

3. Background used 'the browser view should be loaded and visible' which has
   a 21-second timeout and fails before TiddlyWiki finishes initializing in
   the test environment (pre-existing issue in defaultWiki.feature too).
   Fix: replaced with deterministic log marker waits:
     [test-id-WIKI_WORKER_STARTED] + [test-id-VIEW_LOADED]
   plus 'I confirm the main window browser view is positioned within visible
   window bounds' for a structural check without content dependency.

Result: both @window-restore scenarios pass (31/31 steps green, ~48s).

* Fix reopened main window restore after recreation and rebind view resize

Root cause on Windows was not the hide/show path, but the close+recreate path when tidgi mini window keeps the app alive while runOnBackground is false.

What was actually happening:
1. The user closed the main window.
2. The app stayed alive because tidgi mini window still existed.
3. A second-instance launch recreated a new main BrowserWindow.
4. The old workspace WebContentsView still existed in ViewService.
5. But the new main window missed the automatic restore because the BrowserWindow 'show' event fired inside handleCreateBasicWindow() before registerBrowserViewWindowListeners() attached the 'show' listener.
6. If the user then clicked the workspace icon, showView() reattached the old view manually, but its resize listener was still bound to the old destroyed BrowserWindow, so resizing the new window no longer resized the view.

Fix:
- ViewService now rebinds the debounced resize handler every time showView() attaches an existing view to a BrowserWindow.
- Window.open() now detects the recreate-main-window case for BrowserView windows and immediately calls refreshActiveWorkspaceView() if the active workspace already has an existing view instance.
  This restores the view without waiting for a workspace icon click.

Why old E2E missed it:
- It simulated hide/show (runOnBackground=true) instead of the real user path (main window close + app kept alive by tidgi mini window).
- It only checked that the view was within visible bounds; it did not resize the window and assert the view filled the content area after the reopen.

New E2E coverage:
- Configures tidgiMiniWindow=true and runOnBackground=false before launch.
- Closes the main window, reopens it via second-instance, verifies refresh/view-shown markers, verifies bounds, resizes the recreated main window, and asserts the BrowserView fills the content area after the debounced resize handler runs.
- Scenario passes locally: 1 scenario, 20 steps, all green.

* Update pnpm-lock.yaml

* fix: address Copilot PR review issues

- Restore workspaceID from window.meta() in EditWorkspace (was hard-coded debug value)
- Add missing React/type imports to customComponentRegistry.ts, workspaceCustomComponentRegistry.ts, registerCustomSections.tsx, registerWorkspaceCustomSections.tsx, useSections.ts
- Fix HighlightText regex: use index parity (odd index = match) instead of stateful regex.test() with global flag
- Fix actionHandlers native.pickDirectory to read current preference value instead of passing the key string as a path
- Move PreferenceComponents import before registerCustomSections() call to fix import ordering

* fix: fix import ordering to satisfy dprint/eslint format rules

* fix: stabilize e2e selectors and EditWorkspace loading fallback

- align workspace section testids in e2e features
- migrate background-task e2e to scheduled-task selectors
- add edit workspace fallback loading when metadata/observable is late
- add deterministic switch testid for schema boolean items
- make sync snackbar assertion resilient to progress text changes
- clear draft-check timeout handle in sync service

* fix: add apiKey to test provider config so isAIAvailable() returns true

The AI commit message e2e test expects both commit-now-button and
commit-now-ai-button to appear. The AI button only renders when
isAIGenerateBackupTitleEnabled() returns true, which internally calls
externalAPIService.isAIAvailable(). That method requires a non-empty
apiKey for openAICompatible providers, but the test's
createProviderConfig() never set one, causing isAIAvailable() to
return false and the AI button to never render.

* feat(gitServer): add generateFullArchive for fast mobile clone

- Add generateFullArchive() to IGitServerService interface
- Implement tar archive generation: git archive + system tar append
- Archives working tree + minimal .git metadata (HEAD, refs, objects)
- Cache by HEAD commit hash, auto-cleanup old archives
- Bump tidgi-shared to 0.1.5

* fix(e2e): resolve workspace by runtime name/folder in step defs

* fix(ci): satisfy lint rules in gitServer archive generation
2026-04-01 15:45:26 +08:00
lin onetwo
c53292b548
Fix/misc bug2 (#689)
* Improve IPC sync and multi-window browser views

Add robust revision tracking and per-title save serialization to the IPC sync adaptor to ignore stale SSE echoes and prevent overlapping saves (titlesBeingSaved, lastSavedRevisions, pendingSaveOperations, queueSaveOperation, markSaveStart/Finish). Ensure deletions and loads update stored revisions. Disable backgroundThrottling for BrowserWindow/WebContentsView so renderer callbacks (SSE/observables) continue while windows/views are hidden. Update webContents view helpers and step definitions to target a specific window/page (pass Page/currentWindow through executeInBrowserView, getTextContent, click/type/press helpers), and improve view selection by matching target window URL. Update docs to document hidden-window behavior and revision filtering, and add/update feature tests for cross-window sync, hidden TidGi mini window sync, and a rapid-save tiddler scenario.

* Handle main workspace routing for tiddlers

Adjust FileSystemAdaptor routing so that when a tiddler matches the main workspace it uses the main watch path (watchPathBase) instead of treating it as a sub-wiki folder. Add an isMainWorkspaceMatch check to pick the correct target directory and to avoid generating sub-wiki file info for the main workspace.

Also update tests and feature file: extend subWiki.feature to verify routing to the main workspace path when the workspace has a routing tag configured, and add unit tests to assert routing to the main wiki tiddlers folder and to the wiki root when useWikiFolderAsTiddlersPath is enabled.

* review

* v0.13.0-prerelease22
2026-03-24 18:28:38 +08:00
lin onetwo
949c7b00bb
Fix/misc bug1 (#688)
* fix: possible error on wiki creation

* Add isSubWiki/mainWikiToLink and optimize tidgi.config

Introduce new syncable wiki fields (isSubWiki, mainWikiToLink) with schema, types, and defaults; add localization for an autofill note. Expose Database.readWikiConfig over IPC and implement readTidgiConfig usage. When updating workspaces, only write tidgi.config.json if syncable fields actually changed to avoid redundant O(n) disk writes. Update AddWorkspace UI to eagerly read tidgi.config.json (when enabled) to pre-fill form fields and show a helper note. Improve workspace hibernation logic: avoid hibernating page workspaces' servers when switching and prevent concurrent duplicate hibernation calls. Also update template submodule reference.

* Update ErrorDuringRelease.md

* Fix workspace config sync and sub-workspace settings

* adjust menu

* Add sub-workspace UI, view navigation & types

Expose view navigation helpers and types, add sub-workspace UI and related translations, and introduce provider registry types.

- Add canGoBack/canGoForward/goBack/goForward APIs to view service and IPC interface to allow navigating embedded views.
- Implement UI for sub-workspace management in EditWorkspace: list bound sub-workspaces, open sub-workspace settings, and select main workspace for sub-wikis. Add tests IDs and small UX tweaks (cancel button test id).
- Update SaveAndSyncOptions and SubWorkspaceRouting to reflect new sub-workspace flows and remove deprecated main workspace path field.
- Add provider registry interface that re-exports external API types and IPC descriptor (src/services/providerRegistry/interface.ts).
- Add ambient type declarations for @modelcontextprotocol SDK client transports.
- Improve test/e2e support: detect packaged e2e runs via --test-scenario arg in environment constants, update step definition to open edit workspace via the window service using WindowNames, and adjust feature file assertions for sub-wiki bindings.
- Add English and Simplified Chinese translation keys for sub-workspace UI strings.

These changes enable managing sub-workspaces from the Edit Workspace window, provide programmatic view navigation, and add types/interfaces required for integrating external provider tooling and tests.

* fix lint

* Add diagnostics, process monitoring, and menu improvements

Add process diagnostics and monitoring: introduce shared processInfo types, native.getProcessInfo and startProcessMonitoring (30s snapshots + logs), label the main Node process and give descriptive initial window titles; include renderer PIDs in view info and log view creation. Unified Developer Tools panel into a Process & View Diagnostics dialog that shows Node/renderer memory and wiki worker info (wiki.getWorkersInfo). Fix FileSystemAdaptor to pass old fileInfo to generateTiddlerFileInfo to avoid numeric suffixes when overwriting tiddlers. Menu and workspace changes: add a Sync menu and move git items there, simplify context menu generation, remove some developer menu items, and adjust createBackupMenuItems signature. Window and workspace improvements: add recreateUnlessWorkspaceID option and safer window close handling, restore hibernated flag when bringing workspace views up, and improve sub-workspace settings UI. Also add several i18n entries for the new diagnostics and UI text.

* Add renderer metrics; fix hibernation & menus

Collect and display renderer process metrics and harden workspace/window logic.

Highlights:
- Add new i18n keys for renderer PID/CPU/private memory (en and zh-Hans).
- Native service: check and throw on shell.openPath errors; gather per-renderer metrics (private/working set KB and cpu percent) via app.getAppMetrics() and webContents, and improve logging.
- Extend IRendererProcessInfo with private_KB, workingSet_KB and cpu_percent.
- DeveloperTools UI: show PID tooltip, private memory and CPU columns, sort renderers by memory, color-code values, and fix SquirrelTemp path/openPath call.
- Git/menu changes: consolidate backup/sync items to include AI option inline; only show sync for cloud workspaces with a git remote and authenticated user; always show local backup.
- Workspaces/view: prevent races when switching to a workspace by tracking hibernation as awaitable promises (Map), awaiting in-flight hibernations, and re-fetching workspace state before actions.
- View/window safety: add null/undefined checks for view.webContents in several handlers (setupViewEventHandlers, handleAttachToTidgiMiniWindow) to avoid operations on destroyed/closed webContents.

These changes improve diagnostics, prevent race conditions, and make menu behavior more consistent.

* fix: lint errors - remove unused WindowNames import, fix import order and indentation

* fix: address review comments - remove mainWikiToLink from syncable config (absolute path unsafe to sync), fix missing-field detection in syncableChanged, precompute viewsInfo Map in renderer table, use stable pid as row key

* fix: auto-expand SubWorkspaceRouting accordion when bound sub-wikis exist, so e2e test selectors are visible

* fix: update e2e test menu paths - git/sync items moved from Wiki menu to Sync menu

* fix: stabilize sync settings and e2e sync helper
2026-03-23 02:48:46 +08:00
lin onetwo
6384fd8bd1
Fix/misc bug (#677)
* fix: not removed

* Optimize tidgi.config.json writes for workspace updates

Update logic to write tidgi.config.json only for the modified workspace instead of all wiki workspaces on each update. This reduces redundant file operations and improves performance during workspace updates.

* Refactor workspace saving and UI update logic

Introduced a private saveWorkspacesToSettings method to centralize logic for saving workspaces and removing syncable fields from wiki workspaces. The set and setWorkspaces methods now support skipping UI updates for batch operations, improving performance. Fixed minor issues in legacy migration and error messages.

* Add 'Ask AI' context menu and wiki embed split view

Introduces an 'Ask AI' option to the wiki context menu, enabling users to send selected text to an agent chat in a split view with the wiki embedded. Implements new tab type WIKI_EMBED, updates tab and channel types, adds localization, manages BrowserView bounds for embedding, and ensures persistence and IPC wiring for the new workflow.

* Update wiki

* electron chrome mcp mode sometimes wont show browser view

Clarified troubleshooting steps in docs/MCP.md regarding browser view issues and updated the instructions. Reordered the 'start:dev:mcp' script in package.json for better organization.

* Add agent selection to 'Talk with AI' context menu

Replaces the 'Ask AI' context menu with 'Talk with AI' and adds a submenu for selecting different agent definitions. Updates translations for all supported languages, modifies the askAIWithSelection channel to support agentDefId, and refactors tab creation logic to support split view with agent selection. Improves robustness in view management by handling case-insensitive workspace IDs and custom bounds logic.

* Add e2e test and refactor 'Talk with AI' split view logic

Introduces a new Cucumber feature for 'Talk with AI' from wiki selection, adds a step definition to trigger the workflow via IPC, and refactors split view tab creation to reuse existing tabs when possible. Updates the agent browser service to support finding or creating the appropriate split view tab, and adjusts menu and view services for improved robustness and code clarity. Also adds test IDs to relevant components for more reliable UI testing.

* Update defaultWiki.feature

* Add config error handling and i18n for agent errors

Introduces a new feature test for configuration error handling, adds step definition to remove AI settings for testing, and updates error message rendering to support new error types. Internationalized error messages and button labels for configuration issues are added in both English and Chinese locales. The error message renderer now uses a data-testid for easier testing and recognizes additional error types as fixable in settings.

* Refactor feature files to use two-column selector tables

Updated all feature files to use a standardized two-column format for selector tables, with explicit 'element description' and 'selector' columns. Step definitions in ui.ts were refactored to support this format, improving readability and maintainability of test steps and error handling.

* Delete tiddlywiki

* test: allow parallel

* test: implement scenario isolation for E2E tests

- Isolate each test scenario in test-artifacts/{scenarioSlug}/ directory
- Use dynamic ports for mock OpenAI server to avoid port conflicts
- Log VIEW_LOADED event via did-finish-load in main process (more reliable)
- Search all .log files when waiting for log markers
- Increase timeout for log marker steps to 15 seconds
- Fix ts-node cache issues by clearing cache before tests
- Move application launch to individual scenarios (required for mock server setup)

All 45 E2E test scenarios now pass consistently.

* refactor: optimize agent.feature by moving common steps to Background

- Add MockOpenAIServer.addRules() method to append responses dynamically
- Add 'I have started the mock OpenAI server without rules' step for Background
- Add 'I add mock OpenAI responses:' step to inject responses per scenario
- Move application launch and navigation to Background (shared by all scenarios)
- Keep scenario-specific mock responses in individual scenarios

This improves test maintainability by reducing duplication while keeping
scenario-specific configuration flexible.

* lint

* Refactor scenario path helpers into shared module

Moved scenario-specific path helper functions from individual step definition files to a centralized 'features/supports/paths.ts' module. Updated imports in step definitions to use the shared helpers, improving code reuse and maintainability. Also enhanced test for ContextService to skip optional runtime keys.

* Refactor slug generation to use shared slugify helper

Introduced a new src/helpers/slugify.ts utility for consistent slug generation across the codebase. Updated appPaths.ts to use the shared slugify function, improving maintainability and ensuring identical behavior for test scenario slugs. Added documentation and clarified slugification rules in relevant files. Minor comments and clarifications were added to E2E and mock server code.

* Enforce strict timeout rules in E2E test steps

Added and clarified critical warnings for AI agents regarding timeout modifications in application, cleanup, and wiki step definitions. All timeouts are now strictly limited to 5s local and 10s CI, with explicit comments and environment-based values. Updated documentation and code comments to reinforce that timeouts indicate real bugs and should not be increased.

* Update features/stepDefinitions/application.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Refactor E2E helpers, improve test reliability and cleanup

Centralizes data table parsing for UI step definitions, refactors mock OpenAI server setup, and improves workspace settings path handling for tests. Adjusts timeouts for window and app closing to better reflect real-world performance. Fixes type usage in workspace ID lookups and adds error handling for resize observer and cleanup in WikiEmbedTabContent. Enhances agent browser tab logic and view service cleanup to prevent memory leaks and catch workspace ID casing issues.

* Update agent.ts

* fix: resolve all E2E test timeout issues

* fix: improve CI test reliability with better timing and cleanup

- Use exponential-backoff library for agent creation retry logic
- Extend agent cancel delay to 1000ms for CI environments
- Fix git log refresh marker timing with queueMicrotask
- Improve cleanup timeout handling with force close strategy

All E2E tests passing locally including previously failing CI tests.

* Improve Git log E2E signal and add debug logging

Renames the test artifact in the CI workflow for clarity. Moves the E2E test timing log in useGitLogData to after entries are rendered, using a more reliable signal. Adds a debug log to notifyGitStateChange for better traceability.

* test-artifacts-ci

* Optimize test artifact handling and Git log logging

Update CI workflow to clean up large cache folders in test artifacts and only upload logs, settings, and screenshots to reduce artifact size. Refactor useGitLogData to log immediately after state updates for improved E2E test reliability, removing unnecessary setTimeout.

* Update useGitLogData.ts

* Improve Git log E2E test logging and .gitignore

Added 'test-artifacts-ci.zip' to .gitignore. Moved the '[test-id-git-log-refreshed]' log to immediately after data load for more reliable E2E test detection, and removed redundant logging from the render effect in useGitLogData.ts.

* Update useGitLogData.ts

* Update useGitLogData.ts

* Fix git log refresh marker not appearing in CI

- Move git-log-refreshed marker before RAF to ensure it's recorded
- RAF callbacks may not execute reliably in headless CI environments
- Add debug logging to track loadGitLog execution
- Add try-catch around log call to catch any errors
- Keep git-log-data-rendered in useEffect for UI tracking

* Update useGitLogData.ts

* Update useGitLogData.ts

* Add comprehensive logging to diagnose git-log-refreshed issue

- Log before RAF and inside RAF to pinpoint exact failure location
- Add try-catch to capture any errors
- Two log markers: before-raf and in-raf
- This will definitively show where the logging fails in CI

* Fix race condition: prevent concurrent loadGitLog calls

Root cause: commit triggers 2 refreshes (gitStateChange$ + handleCommitSuccess)
- First loadGitLog (refreshTrigger=1) succeeds
- Second loadGitLog (refreshTrigger=2) starts but never completes
- Add loadGitLogInProgress guard to prevent concurrent execution
- Log when loadGitLog is skipped due to in-progress call

This ensures git-log-refreshed is always logged after commit.

* Remove redundant triggerRefresh calls causing race condition

- handleCommitSuccess/Revert/Undo no longer call triggerRefresh
- gitStateChange\$ observable already triggers refresh for these operations
- Redundant calls caused 2 concurrent loadGitLog, causing CI test failures
- Local tests passed because both completed; CI failed because 2nd never completed

This ensures only 1 loadGitLog runs per git operation.

* Remove unused triggerRefresh parameter from useCommitSelection

- triggerRefresh no longer used in handlers
- Remove from interface and call site
- Clean up lint errors

* Remove triggerRefresh completely - no longer needed

- Observable subscription handles all git state changes
- Remove function definition and exports
- Fix all lint errors

Root cause resolved: commit triggered double refresh causing race condition.
Now only single refresh via observable.

* Remove fixed time waits from gitLog.feature and fix race condition

- Remove all fixed time wait steps from gitLog.feature (14 instances)
- Remove redundant triggerRefresh calls in handleCommitSuccess/Revert/Undo
- Add loadGitLogInProgress guard to prevent concurrent loadGitLog
- Root cause: commit triggered 2 refreshes causing race condition
- Only gitStateChange\$ observable now triggers refresh
- All 4 gitLog tests pass locally

* Fix clear timing: clear log BEFORE commit, not after

Root cause: test cleared git-log-refreshed AFTER commit completed
- But commit already triggered refresh and logged git-log-refreshed
- Clear deleted it, then test waited for new log that would never come
- Solution: clear BEFORE clicking commit button
- This way commit's git-log-refreshed is the first one after clear

Test now passes locally.

* Update cleanup.ts

* Initial commit when init a new git.

* Refactor feature steps for multi-element and log marker tables

Updated multiple feature files and step definitions to support table-driven steps for clicking and asserting multiple elements, and for waiting for multiple log markers in sequence. This reduces redundant waits, improves test reliability, and streamlines Gherkin syntax for multi-element actions and assertions. Also removed unnecessary manual wait steps where content or element checks now handle waiting automatically.

* Minor code cleanup and formatting improvements

Reordered imports in browserView.ts, fixed whitespace in cleanup.ts and useGitLogData.ts, and improved line formatting in GitLog/index.tsx for better readability and consistency.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: tidgi <tiddlygit@gmail.com>
2026-01-20 11:11:28 +08:00
lin onetwo
7edb132d32
Fix/watch fs and ai commit (#674)
* fix: missing return

* feat: showApiKey

* feat: undo commit

* feat: amend commit

* fix: file name quoted in git log

* fix: wikiWorkspaceDefaultValues

* fix: no ai commit message sometimes

* Persist only non-default preferences to storage

Added a utility to store only preferences that differ from defaults, reducing storage size and improving config readability. Updated the setPreferences method to use this utility before saving preferences.

* fix: External Attachment Handling in fs plugin instead of ext-attachment-plugin to handle direct tag update case which won't trigger  th-saving-tiddler hook

* feat: api for plugin to create base64 file

* Show all untracked files and recreate Git history window

Updated git status commands to use '-uall' for displaying all untracked files, not just directories. Modified windowService.open calls for Git history to include the { recreate: true } option, ensuring the window is refreshed when opened from various menus.

* fix: handling of external attachments with _canonical_uri

Ensure tiddlers with _canonical_uri are always saved as .tid files, not as binary files, by forcing the .tid extension in FileSystemAdaptor. Update tests to verify this behavior. Also, skip loading files from the external attachments folder in loadWikiTiddlersWithSubWikis to prevent them from being loaded as separate tiddlers.

* Refactor external attachment utilities to module exports

Refactored externalAttachmentUtilities to use ES module exports instead of attaching functions to $tw.utils. Updated imports and mocks accordingly, removed related type definitions from ExtendedUtilities, and cleaned up obsolete meta file.

* disable enableFileSystemWatch to prevent bug for innocent users

* fix: test that requires enableFileSystemWatch use new step set to true

* Fix extension filter usage and sync workspace state after save

Refactored variable naming for extension filters in FileSystemAdaptor to improve clarity and fixed their usage in generateTiddlerFileInfo calls. Removed an unused import in routingUtilities.type.ts. Added a useEffect in useForm to sync workspace state with originalWorkspace after save, ensuring the save button disappears as expected.

* fix: review

* lint

* feat: unify AI commit entry points and add availability check  - Unified all AI commit message generation to use syncService.syncWikiIfNeeded() for consistent business logic handling - Added externalAPI.isAIAvailable() method to check if AI provider and model are properly configured - Updated gitService.isAIGenerateBackupTitleEnabled() to use the new availability check - Removed redundant logging code since generateFromAI() automatically logs to database when externalAPIDebug is enabled - Simplified menu item creation logic in menuItems.ts - Ensured AI menu options only appear when both API credentials and free model are configured - Updated documentation to reflect the unified architecture

* Improve AI commit message diff filtering and API checks

Renamed the AI commit message entry points doc for clarity. Enhanced the AI availability check to better handle provider API key requirements, including support for providers that do not require keys. Improved plugin diff filtering to retain small config file diffs while omitting large plugin file contents, optimizing AI token usage.

* Update wiki

* Refactor and enhance Tidgi mini window initialization and sync

Refactors Tidgi mini window startup to use a new initializeTidgiMiniWindow method, improving workspace selection logic and view management. Adds concurrency locks to prevent race conditions during open/close operations. Enhances workspace sync/fixed mode handling, view cleanup, and error logging. Updates interfaces and utilities to support new behaviors and improves robustness of tray icon creation and view realignment.

* Refactor file system sync to use $tw.syncer.syncFromServer()

Introduces FileSystemWatcher to monitor file changes and collect updates for the syncer, replacing direct wiki updates in WatchFileSystemAdaptor. Updates documentation to describe the new syncer-driven architecture, echo prevention, and event handling. WatchFileSystemAdaptor now delegates file change detection and lazy loading to FileSystemWatcher, improving batch change handling and eliminating echo loops.

* Improve logging and cleanup in file system watcher and git ops

Added detailed logging to WatchFileSystemAdaptor and FileSystemWatcher for better traceability during initialization and test stabilization. Introduced a constant for the temporary git index prefix in gitOperations. Removed the unused comparison.ts utility for tiddler comparison. Enhanced comments and logging for AI commit message generation context.

* Improve GitLog i18n test and config refresh logic

Updated gitLog.feature to use only Chinese selectors for actions, revert, and discard buttons, improving i18n test reliability. In FileSystemWatcher, re-fetch workspace config before checking enableFileSystemWatch to ensure latest settings are respected. In useGitLogData, prevent file-change events from overriding commit/undo events to maintain correct auto-selection behavior.

* Improve Git log selection and test stability

Refines auto-selection logic in the Git log window to better handle uncommitted changes, commits, reverts, and undos. Updates the feature test to explicitly verify selection and UI state after each operation, improving reliability. Removes unnecessary config re-fetch in FileSystemWatcher and enhances logging for more accurate DOM update detection.

* Implement workspace config sync via tidgi.config.json

Adds support for syncing workspace configuration to tidgi.config.json in the wiki folder, enabling settings persistence and migration across devices. Introduces new documentation, feature tests, and supporting utilities for config file reading, writing, migration, and validation. Updates step definitions and test helpers to support config sync scenarios, and refactors database config utilities for modularity.

* Improve workspace config handling and sync logic

Enhances workspace lookup in step definitions to check both settings.json and tidgi.config.json, ensuring properties are found even if moved. Updates tidgiConfig write logic to remove the config file if all values are default. Refactors workspace save logic to always write syncable config to tidgi.config.json for all wiki workspaces before removing those fields from settings.json, preventing config loss.

* Update .gitignore

* Update wiki.ts

* Add delay before waiting for git log render after revert

- Add 1 second wait after clearing git-log-data-rendered markers following revert
- This gives UI time to start refreshing before we check for the new marker
- Fixes CI timing issue where revert operation needs more time to trigger UI refresh

* Update test log markers for git log refresh events

Replaces '[test-id-git-log-data-rendered]' with '[test-id-git-log-refreshed]' in gitLog.feature to better reflect UI refresh events after commit and revert actions. Adds a debug log marker '[test-id-git-revert-complete]' in revertCommit for improved test synchronization.

* Fix git revert refresh timing - remove intermediate step and rely on git-log-refreshed

* Add detailed logging to handleRevert for CI debugging

* Fix git log refresh by adding manual triggerRefresh fallback

- Add triggerRefresh function to useGitLogData hook for manual refresh
- Call triggerRefresh in handleCommitSuccess, handleRevertSuccess, and handleUndoSuccess
- This fixes cross-process IPC observable subscription issues where gitStateChange$
  notifications from main process may not reach renderer process reliably
- Add detailed logging to handleRevert for CI debugging

* Update index.tsx
2026-01-10 23:57:59 +08:00
lin onetwo
c2be8e4186
Fix/sub wiki tag tree (#667)
* fix: different out path on macos

* fix: let go hibernation promise, so it's faster on macos

* log marker [test-id-TIDGI_MINI_WINDOW_CREATED]

* Skip registerShortcutByKey  in test

* fix: mini window on mac

* Remove useless log marker

* Update handleAttachToTidgiMiniWindow.ts

* fix: log marker check all log files

* lint

* fix: open in new window now showing wiki title

* Update package.json

* feat: basic load and save to sub wiki using in-tag-tree-of

* fix: load sub-wiki content and prevent echo

* fix: test and ui logic

* test: refactor subwiki test logic to a file

* refactor: shorten steps by using dedicated step, and test underlying micro steps

* fix: review

* refactor: remove outdated method signature

* test: unit cover adaptor subwiki routing

* Update FileSystemAdaptor.routing.test.ts

* fix: merge issue
2025-12-07 03:31:34 +08:00