Skip to content

Add context to activity changes#2093

Merged
myieye merged 17 commits into
developfrom
add-context-to-activity
Nov 7, 2025
Merged

Add context to activity changes#2093
myieye merged 17 commits into
developfrom
add-context-to-activity

Conversation

@myieye

@myieye myieye commented Nov 6, 2025

Copy link
Copy Markdown
Collaborator
image image image image image image image

And reused the new design in the history dialog:
image

Still not optimized for mobile, but that's for another day:
image

@github-actions github-actions Bot added the 💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related label Nov 6, 2025
@coderabbitai

coderabbitai Bot commented Nov 6, 2025

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

This PR introduces change context functionality to the activity history feature. Backend adds a new ChangeContext record and LoadChangeContext method to HistoryService, with corresponding JSInvokable and TypeScript type exports. Frontend refactors activity display into new ActivityItem and ActivityItemChangePreview components, replaces headword rendering with a dedicated component, and updates localization across seven language files to reference the new components.

Changes

Cohort / File(s) Summary
Backend Core History Service
backend/FwLite/LcmCrdt/HistoryService.cs
Introduces new ChangeContext record and extends HistoryLineItem with change field; refactors HistoryService constructor to accept IMiniLcmApi, adds LoadChangeContext method with internal helpers (GetCurrentOrLatestEntry, GetAffectedEntryIds, NormalizeTimestamp); updates ChangeNameHelper to use Contains instead of StartsWith for JSON patch detection
Backend Type Exports
backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs
Exports ChangeContext to public TypeScript interface surface
Backend JSInvokable Layer
backend/FwLite/FwLiteShared/Services/HistoryServiceJsInvokable.cs
Adds new JSInvokable method LoadChangeContext(commitId, changeIndex)
Backend Project Setup
backend/FwLite/LcmCrdt/CurrentProjectService.cs, backend/FwLite/FwLiteWeb/HttpHelpers.cs, backend/FwLite/FwLiteWeb/FwLiteWebServer.cs
Renames projectName to projectCode across method signatures and calls; updates SetupProjectContext parameter from projectName to projectCode; replaces GetProjectName with GetProjectCode extension method
Frontend TypeScript Type Generation
frontend/viewer/src/lib/dotnet-types/generated-types/LcmCrdt/IChangeContext.ts, frontend/viewer/src/lib/dotnet-types/generated-types/LcmCrdt/IHistoryLineItem.ts, frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/IHistoryServiceJsInvokable.ts, frontend/viewer/src/lib/dotnet-types/generated-types/LcmCrdt/index.ts
Adds new IChangeContext interface and exports; extends IHistoryServiceJsInvokable with loadChangeContext method; adds change property to IHistoryLineItem
Frontend Activity Components
frontend/viewer/src/lib/activity/ActivityItem.svelte, frontend/viewer/src/lib/activity/ActivityItemChangePreview.svelte, frontend/viewer/src/lib/activity/ActivityView.svelte
Introduces ActivityItem component with reactive history-loading and per-change context display; adds ActivityItemChangePreview component for change preview UI with entity-type-specific editors; refactors ActivityView to delegate to ActivityItem with simplified row layout
Frontend Utility and Service Updates
frontend/viewer/src/lib/activity/utils.ts, frontend/viewer/src/lib/services/history-service.ts
Adds formatJsonForUi utility function; extends history-service with constructor accepting projectContext, adds loaded() getter, loadChangeContext method, and updates activity signature from projectName to projectCode
Frontend Component Refactors
frontend/viewer/src/lib/DictionaryEntry.svelte
Replaces manual headword rendering with new Headwords component
Frontend New Components
frontend/viewer/src/lib/Headwords.svelte
New component rendering vernacular headwords with writing-system service integration
Frontend Service Enhancements
frontend/viewer/src/lib/services/multi-window-service.ts
Adds optional _multiWindowService parameter; integrates FwLitePlatform for mobile detection; provides browser fallback when service unavailable; updates useMultiWindowService to return undefined on mobile platforms
Frontend Format Components
frontend/viewer/src/lib/components/ui/format/format-date.svelte, frontend/viewer/src/lib/components/ui/format/format-duration.svelte, frontend/viewer/src/lib/components/ui/format/format-duration.ts, frontend/viewer/src/lib/components/ui/format/format-relative-date.svelte
Adds tooltip to date display; adds optional maxUnits prop to duration component; wraps duration formatting in try/catch error handling; adds padding to relative date popover
Frontend Editor Components
frontend/viewer/src/lib/entry-editor/EntryOrSenseItemList.svelte
Adds localization and multi-window service integration; adds "Open in new Window" action for entries; adds getHeadword prop
Localization Files
frontend/viewer/src/locales/en.po, frontend/viewer/src/locales/es.po, frontend/viewer/src/locales/fr.po, frontend/viewer/src/locales/id.po, frontend/viewer/src/locales/ko.po, frontend/viewer/src/locales/ms.po, frontend/viewer/src/locales/sw.po
Updates translation source references from ActivityView.svelte to ActivityItem.svelte; introduces new translation keys for ActivityItemChangePreview.svelte including "(Deleted)", "Complex form:", "Component:", "Current version", "Go to {0}", etc.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

  • Areas requiring extra attention:
    • The new ChangeContext record and LoadChangeContext method in HistoryService.cs, particularly the helper methods (GetCurrentOrLatestEntry, GetAffectedEntryIds) and their integration with IMiniLcmApi
    • The reactive history-loading mechanism and per-change context fetching in ActivityItem.svelte to ensure proper async handling and memory efficiency
    • ActivityItemChangePreview.svelte entity-type-specific rendering logic for Entry, Sense, ExampleSentence, and ComplexFormComponent
    • multi-window-service.ts changes, particularly mobile platform detection and fallback behavior for window.open
    • Validation that generated TypeScript types align correctly with backend C# records and signatures
    • Cross-file consistency of the projectNameprojectCode refactoring across backend files

Possibly related PRs

  • move work off UI thread #1804: Both PRs refactor and extend HistoryService.cs, with this PR adding ChangeContext and LoadChangeContext while the prior PR restructured async iterators and DbContextFactory usage.
  • Fix duplicate each-key in activity view #2037: Both PRs modify exported types in ReinforcedFwLiteTypingConfig, with this PR adding ChangeContext to the public interface surface alongside related type exports.
  • New Crowdin updates #1858: Both PRs update multiple localization files (en.po, es.po, fr.po, etc.) for activity-related UI strings, indicating coordinated internationalization changes.

Suggested labels

💻 FW Lite, 🟨Medium

Suggested reviewers

  • hahn-kev
  • rmunn

Poem

🐰 A rabbit's verse on history's view:

With context clues and changes bright,
We weave the threads of past just right,
From headwords bold to previews clear,
Each moment's tale becomes sincere!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive The description consists only of image attachments without any textual explanation, making it impossible to assess whether the description relates to the changeset. Add a text description explaining the purpose, motivation, and key changes in the PR to help reviewers understand the intent and functionality beyond visual mockups.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add context to activity changes' directly and clearly describes the main changes: adding a ChangeContext feature to activity-related components and services throughout the codebase.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/FwLite/LcmCrdt/HistoryService.cs (1)

220-229: Consider reverting to StartsWith for more precise matching.

Line 224 changed from type.Name.StartsWith("JsonPatch") to type.Name.Contains("JsonPatch"). This makes the matching less precise and could incorrectly match type names like "NotJsonPatchChange" or "CustomJsonPatchHandler".

Unless there's a specific requirement for partial matching, the original StartsWith approach was safer and more precise.

Apply this diff to restore precise matching:

-        if (type.Name.Contains("JsonPatch")) return $"Edit{change.EntityType.Name}".Humanize();
+        if (type.Name.StartsWith("JsonPatch")) return $"Edit{change.EntityType.Name}".Humanize();
🧹 Nitpick comments (3)
frontend/viewer/src/lib/components/ui/format/format-date.svelte (1)

44-44: Good UX enhancement with native tooltip.

Adding the full date/time as a tooltip provides helpful additional context while keeping the display concise.

Note: The native title attribute has limited accessibility support (e.g., not keyboard-accessible, inconsistent screen reader behavior). For enhanced accessibility, consider using a custom tooltip component in the future, though the current implementation is acceptable as a progressive enhancement.

frontend/viewer/src/lib/activity/ActivityItemChangePreview.svelte (2)

38-54: Add type guards for snapshot type assertions.

The type assertions at lines 44 and 47 assume context.snapshot matches the context.entityType without validation. If the data is inconsistent, this could cause runtime errors.

Consider adding type guards or validation:

 let currentEntity = $derived.by(() => {
   if (!affectedEntry) return undefined;

   if (context.entityType === 'Entry') {
     return affectedEntry;
   } else if (context.entityType === 'Sense') {
-    const senseId = (context.snapshot as ISense).id;
+    const snapshot = context.snapshot as ISense;
+    if (!snapshot?.id) return undefined;
+    const senseId = snapshot.id;
     return affectedEntry.senses.find((s) => s.id === senseId);
   } else if (context.entityType === 'ExampleSentence') {
-    const exampleId = (context.snapshot as IExampleSentence).id;
+    const snapshot = context.snapshot as IExampleSentence;
+    if (!snapshot?.id) return undefined;
+    const exampleId = snapshot.id;
     for (const sense of affectedEntry.senses) {
       const example = sense.exampleSentences.find((ex) => ex.id === exampleId);
       if (example) return example;
     }
   }
   return undefined;
 });

120-137: Type assertions lack runtime validation.

The type assertions (showCurrent ? currentEntity : context.snapshot) as IEntry at lines 123, 129, and 135 assume the snapshot type matches the entityType, but there's no runtime check. If the data is inconsistent or currentEntity is undefined when showCurrent is true, this could cause issues.

Consider adding defensive checks or using type guards to ensure type safety at runtime, especially since currentEntity can be undefined based on the derived logic at lines 38-54.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6cf4b2a and 87be896.

📒 Files selected for processing (30)
  • backend/FwLite/FwLiteShared/Services/HistoryServiceJsInvokable.cs (1 hunks)
  • backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs (1 hunks)
  • backend/FwLite/FwLiteWeb/FwLiteWebServer.cs (1 hunks)
  • backend/FwLite/FwLiteWeb/HttpHelpers.cs (1 hunks)
  • backend/FwLite/LcmCrdt/CurrentProjectService.cs (1 hunks)
  • backend/FwLite/LcmCrdt/HistoryService.cs (6 hunks)
  • frontend/viewer/src/lib/DictionaryEntry.svelte (2 hunks)
  • frontend/viewer/src/lib/Headwords.svelte (1 hunks)
  • frontend/viewer/src/lib/activity/ActivityItem.svelte (1 hunks)
  • frontend/viewer/src/lib/activity/ActivityItemChangePreview.svelte (1 hunks)
  • frontend/viewer/src/lib/activity/ActivityView.svelte (3 hunks)
  • frontend/viewer/src/lib/activity/utils.ts (1 hunks)
  • frontend/viewer/src/lib/components/ui/format/format-date.svelte (1 hunks)
  • frontend/viewer/src/lib/components/ui/format/format-duration.svelte (1 hunks)
  • frontend/viewer/src/lib/components/ui/format/format-duration.ts (1 hunks)
  • frontend/viewer/src/lib/components/ui/format/format-relative-date.svelte (1 hunks)
  • frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/IHistoryServiceJsInvokable.ts (1 hunks)
  • frontend/viewer/src/lib/dotnet-types/generated-types/LcmCrdt/IChangeContext.ts (1 hunks)
  • frontend/viewer/src/lib/dotnet-types/generated-types/LcmCrdt/IHistoryLineItem.ts (2 hunks)
  • frontend/viewer/src/lib/dotnet-types/generated-types/LcmCrdt/index.ts (1 hunks)
  • frontend/viewer/src/lib/entry-editor/EntryOrSenseItemList.svelte (2 hunks)
  • frontend/viewer/src/lib/services/history-service.ts (3 hunks)
  • frontend/viewer/src/lib/services/multi-window-service.ts (1 hunks)
  • frontend/viewer/src/locales/en.po (16 hunks)
  • frontend/viewer/src/locales/es.po (16 hunks)
  • frontend/viewer/src/locales/fr.po (16 hunks)
  • frontend/viewer/src/locales/id.po (16 hunks)
  • frontend/viewer/src/locales/ko.po (16 hunks)
  • frontend/viewer/src/locales/ms.po (16 hunks)
  • frontend/viewer/src/locales/sw.po (16 hunks)
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-07-30T04:53:41.702Z
Learnt from: rmunn
Repo: sillsdev/languageforge-lexbox PR: 1844
File: frontend/viewer/src/lib/entry-editor/ItemListItem.svelte:26-37
Timestamp: 2025-07-30T04:53:41.702Z
Learning: In frontend/viewer/src/lib/entry-editor/ItemListItem.svelte, the TODO comments for unused props `index` and `actions` are intentional reminders for future work to be completed in a separate PR, not issues to be resolved immediately. These represent planned functionality that will be implemented later.

Applied to files:

  • frontend/viewer/src/lib/activity/ActivityItem.svelte
  • frontend/viewer/src/lib/activity/ActivityItemChangePreview.svelte
  • frontend/viewer/src/lib/entry-editor/EntryOrSenseItemList.svelte
📚 Learning: 2025-07-22T09:19:37.386Z
Learnt from: rmunn
Repo: sillsdev/languageforge-lexbox PR: 1836
File: frontend/viewer/src/lib/components/audio/AudioDialog.svelte:25-25
Timestamp: 2025-07-22T09:19:37.386Z
Learning: In the sillsdev/languageforge-lexbox project, when file size limits or other constants need to be shared between C# backend and TypeScript frontend code, prefer exposing them through Reinforced.Typings type generation rather than hardcoding the values separately. This ensures consistency and prevents discrepancies when values change.

Applied to files:

  • backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs
📚 Learning: 2025-10-06T12:48:36.601Z
Learnt from: myieye
Repo: sillsdev/languageforge-lexbox PR: 2025
File: frontend/viewer/src/locales/sw.po:146-149
Timestamp: 2025-10-06T12:48:36.601Z
Learning: Do not review or comment on `.po` translation files (e.g., files in `frontend/viewer/src/locales/`) in the languageforge-lexbox repository, as translations are managed by Crowdin.

Applied to files:

  • frontend/viewer/src/locales/en.po
  • frontend/viewer/src/locales/ko.po
📚 Learning: 2025-07-07T06:02:41.194Z
Learnt from: hahn-kev
Repo: sillsdev/languageforge-lexbox PR: 1804
File: backend/FwLite/LcmCrdt/CurrentProjectService.cs:18-19
Timestamp: 2025-07-07T06:02:41.194Z
Learning: In the CurrentProjectService class, the service locator pattern is intentionally used to retrieve IDbContextFactory<LcmCrdtDbContext> and EntrySearchServiceFactory because these services indirectly depend on CurrentProjectService to have the current project set, creating a circular dependency. This is an acceptable use of service locator to break the circular dependency while keeping project context responsibility consolidated.

Applied to files:

  • backend/FwLite/LcmCrdt/CurrentProjectService.cs
📚 Learning: 2025-06-27T09:24:39.507Z
Learnt from: hahn-kev
Repo: sillsdev/languageforge-lexbox PR: 1760
File: backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs:274-277
Timestamp: 2025-06-27T09:24:39.507Z
Learning: In the CrdtMiniLcmApi class, the user prefers to keep the current AddChanges method signature (IEnumerable<IChange>) rather than modifying it to support IAsyncEnumerable for streaming, even when it means materializing collections into memory for bulk operations.

Applied to files:

  • backend/FwLite/LcmCrdt/HistoryService.cs
📚 Learning: 2025-06-02T14:27:02.745Z
Learnt from: myieye
Repo: sillsdev/languageforge-lexbox PR: 1720
File: frontend/viewer/src/locales/es.json:1786-1790
Timestamp: 2025-06-02T14:27:02.745Z
Learning: Spanish locale file (frontend/viewer/src/locales/es.json) contains generated code that may have null line numbers in origin entries due to limitations in the code generation process.

Applied to files:

  • frontend/viewer/src/locales/es.po
📚 Learning: 2025-05-27T06:18:33.852Z
Learnt from: hahn-kev
Repo: sillsdev/languageforge-lexbox PR: 1710
File: frontend/viewer/src/project/browse/BrowseView.svelte:17-19
Timestamp: 2025-05-27T06:18:33.852Z
Learning: The NewEntryButton component in frontend/viewer/src/project/NewEntryButton.svelte already internally checks features.write permission and conditionally renders based on write access, so external disabled props are not needed.

Applied to files:

  • frontend/viewer/src/lib/activity/ActivityItemChangePreview.svelte
🧬 Code graph analysis (7)
frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/IHistoryServiceJsInvokable.ts (1)
frontend/viewer/src/lib/dotnet-types/generated-types/LcmCrdt/IChangeContext.ts (1)
  • IChangeContext (9-17)
backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs (1)
backend/FwLite/LcmCrdt/HistoryService.cs (1)
  • ChangeContext (29-32)
frontend/viewer/src/lib/services/history-service.ts (2)
frontend/viewer/src/lib/project-context.svelte.ts (1)
  • ProjectContext (36-164)
frontend/viewer/src/lib/dotnet-types/generated-types/LcmCrdt/IProjectActivity.ts (1)
  • IProjectActivity (9-16)
backend/FwLite/FwLiteShared/Services/HistoryServiceJsInvokable.cs (2)
backend/FwLite/LcmCrdt/HistoryService.cs (1)
  • ChangeContext (29-32)
frontend/viewer/src/lib/project-context.svelte.ts (1)
  • historyService (93-95)
backend/FwLite/FwLiteWeb/FwLiteWebServer.cs (2)
backend/FwLite/FwLiteWeb/HttpHelpers.cs (1)
  • GetProjectCode (7-11)
backend/FwLite/LcmCrdt/CurrentProjectService.cs (1)
  • CurrentProjectService (11-163)
backend/FwLite/LcmCrdt/HistoryService.cs (3)
backend/FwLite/FwDataMiniLcmBridge/FieldWorksProjectList.cs (2)
  • IMiniLcmApi (45-49)
  • IMiniLcmApi (51-54)
backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs (8)
  • IAsyncEnumerable (121-128)
  • IAsyncEnumerable (162-169)
  • IAsyncEnumerable (215-222)
  • IAsyncEnumerable (259-266)
  • IAsyncEnumerable (352-355)
  • IAsyncEnumerable (388-391)
  • IAsyncEnumerable (393-400)
  • IAsyncEnumerable (613-628)
backend/FwLite/FwLiteShared/Sync/SyncService.cs (1)
  • IAsyncEnumerable (202-222)
frontend/viewer/src/lib/services/multi-window-service.ts (2)
frontend/viewer/src/css-breakpoints.ts (1)
  • MOBILE_BREAKPOINT (2-2)
frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/IMultiWindowService.ts (1)
  • IMultiWindowService (6-9)
🔇 Additional comments (36)
frontend/viewer/src/lib/components/ui/format/format-date.svelte (1)

38-41: LGTM! Well-implemented tooltip enhancement.

The fullDate derived value correctly provides a detailed date/time format for the tooltip. Using the existing formatDate function ensures consistent localization handling.

frontend/viewer/src/lib/components/ui/format/format-duration.ts (1)

60-66: Good addition for observability.

The error handling with contextual logging is helpful for debugging duration formatting issues, especially with the new maxUnits parameter introduced in this PR.

frontend/viewer/src/lib/components/ui/format/format-duration.svelte (2)

21-21: Correct parameter passing.

The maxUnits parameter is correctly passed as the fourth argument to formatDuration, maintaining the proper parameter order.


4-18: Edge case handling for maxUnits is adequate.

Verification confirms the implementation handles edge cases safely:

  • maxUnits = 0: Skipped by falsy check (line 59), returns normalized duration
  • maxUnits < 0: Loop breaks immediately, returns minimal valid duration
  • maxUnits > 0: Works as designed

The code is defensive and matches the .ts function signature. No validation is needed.

frontend/viewer/src/lib/dotnet-types/generated-types/LcmCrdt/IHistoryLineItem.ts (1)

6-6: LGTM! Type definition extended correctly.

The addition of the change property with its corresponding import aligns with the PR's goal of adding change context to activity history.

Also applies to: 16-16

frontend/viewer/src/lib/components/ui/format/format-relative-date.svelte (1)

74-74: LGTM! Improved popover spacing.

The additional padding improves the visual layout of the actual date popover content.

backend/FwLite/LcmCrdt/CurrentProjectService.cs (1)

83-86: LGTM! Consistent parameter naming.

The rename from projectName to projectCode improves consistency across the codebase and aligns with the GetProjectCode method usage.

backend/FwLite/FwLiteWeb/FwLiteWebServer.cs (1)

100-103: LGTM! Consistent naming update.

The change from GetProjectName to GetProjectCode aligns with the parameter rename in CurrentProjectService.SetupProjectContext and improves naming consistency.

frontend/viewer/src/lib/dotnet-types/generated-types/LcmCrdt/index.ts (1)

6-6: LGTM! Public API expanded correctly.

The export of IChangeContext expands the module's public API surface to support the new change context functionality.

frontend/viewer/src/lib/DictionaryEntry.svelte (1)

9-9: LGTM! Good refactoring for code reuse.

Extracting headword rendering into a dedicated Headwords component improves maintainability and promotes consistency across the application.

Also applies to: 100-100

frontend/viewer/src/lib/activity/ActivityItemChangePreview.svelte (1)

100-103: ****

The code is working as designed. Based on the backend implementation in HistoryService.cs, GetAffectedEntryIds yields:

  • Exactly 1 entry for Entry, Sense, and ExampleSentence types (lines 177, 183, 191)
  • Exactly 2 entries for ComplexFormComponent type (lines 197-198)

The component correctly handles this: for non-ComplexFormComponent types, affectedEntry is derived to be defined only when affectedEntries.length === 1, and the outer condition at line 97 enforces this constraint. ComplexFormComponent already has its own separate rendering logic using find() calls.

The nested check at lines 100-103 is redundant but harmless—it cannot occur in any other scenario. No changes are needed.

Likely an incorrect or invalid review comment.

backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs (1)

172-172: LGTM! ChangeContext properly exported for TypeScript generation.

The addition of ChangeContext to the exported interfaces list correctly expands the typing surface to support the new change context functionality. This follows the established pattern for exposing backend types to the frontend.

frontend/viewer/src/lib/services/history-service.ts (3)

33-38: LGTM! Useful addition of loaded() getter.

The loaded() getter provides a clean way to check if the history service is available, improving the service's public interface.


40-53: LGTM! Correctly uses projectCode in API path.

The update to use projectCode in the API path maintains consistency with the renamed parameter throughout the codebase. The timestamp assignment and array reversal logic is correct.


71-73: LGTM! Parameter rename improves consistency.

Renaming the parameter from projectName to projectCode aligns with the broader naming improvements across the codebase.

frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/IHistoryServiceJsInvokable.ts (1)

10-10: LGTM! Generated typings correctly reflect backend API.

The generated TypeScript interface properly exposes the new loadChangeContext method with correct type signatures matching the backend HistoryServiceJsInvokable implementation.

Also applies to: 18-18

backend/FwLite/FwLiteShared/Services/HistoryServiceJsInvokable.cs (1)

34-38: LGTM! JSInvokable method follows established patterns.

The new LoadChangeContext method correctly implements the cross-boundary API pattern used throughout the class, with proper async/await handling and JSInvokable decoration.

frontend/viewer/src/lib/Headwords.svelte (2)

1-29: LGTM! Well-structured component with proper reactive state.

The component correctly derives headwords from writing systems with appropriate filtering and formatting. The use of $derived.by() ensures reactive updates, and the optional placeholder prop provides good UX for empty states.


31-41: LGTM! Clean template with proper separator logic.

The template correctly renders headwords with " / " separators between items (not before the first), and the comment on Line 34 helpfully explains the whitespace preservation requirement.

frontend/viewer/src/lib/activity/ActivityView.svelte (2)

3-3: LGTM! Import updates support the refactored UI.

The changes to use the t function directly and import the new ActivityItem component align with the simplified activity display approach.

Also applies to: 9-10


54-62: LGTM! Refactoring improves component structure.

Delegating activity detail rendering to the ActivityItem component improves separation of concerns and maintainability. The new two-column header layout with relative date and author name provides better UX.

Also applies to: 71-71

frontend/viewer/src/locales/sw.po (1)

21-21: LGTM! Translation file correctly updated for new components.

The localization updates properly reflect the component restructuring, with new keys added for ActivityItem and ActivityItemChangePreview. Empty translation strings (msgstr "") are expected pending translator input.

Also applies to: 25-27, 258-275, 310-312, 352-354, 860-863

backend/FwLite/FwLiteWeb/HttpHelpers.cs (1)

7-7: LGTM! Method rename improves naming accuracy.

Renaming GetProjectName to GetProjectCode better reflects the method's purpose of extracting the project code from route values. This aligns with the broader naming improvements across the codebase.

frontend/viewer/src/lib/entry-editor/EntryOrSenseItemList.svelte (2)

8-13: LGTM!

The imports and service initializations correctly integrate routing and multi-window functionality, enabling context-aware menu actions.


37-42: LGTM!

The new "Open in new Window" menu item is correctly implemented with defensive null checking on multiWindowService, preventing potential runtime errors when the service is unavailable.

frontend/viewer/src/lib/activity/ActivityItem.svelte (3)

1-13: LGTM!

The exported types Activity and ChangeWithContext are well-structured and provide a clean public API for the activity item functionality.


29-35: LGTM!

The reactive changes derivation correctly uses the resource helper to asynchronously load change contexts, ensuring all contexts are available before rendering.


70-102: LGTM!

The template correctly implements defensive rendering with changes?.current checks and uses VList for performance optimization when displaying many changes. The tabbed interface for Preview and Details provides good UX.

frontend/viewer/src/lib/dotnet-types/generated-types/LcmCrdt/IChangeContext.ts (1)

1-18: LGTM!

The generated IChangeContext interface correctly defines the TypeScript type for the backend ChangeContext record, providing proper type safety for the change context functionality.

frontend/viewer/src/locales/ko.po (1)

1-1346: Skipping review of translation file.

Translation files in frontend/viewer/src/locales/ are managed by Crowdin and should not be reviewed here.

Based on learnings

backend/FwLite/LcmCrdt/HistoryService.cs (6)

22-34: LGTM!

The ChangeContext record is well-structured with proper null handling for the EntityType property.


36-69: LGTM!

The HistoryLineItem record has been correctly updated to include the IChange field, with proper constructor chaining.


73-91: LGTM!

The refactored LINQ query for ProjectActivity() properly uses NormalizeTimestamp to address timezone issues and correctly structures the multi-join query.


159-171: LGTM!

The GetCurrentOrLatestEntry method properly handles both existing and deleted entries with appropriate fallback logic and exception handling.


202-207: LGTM!

The NormalizeTimestamp method correctly addresses the Linq2DB timezone issue with a clear explanation and proper UTC reinterpretation.


139-157: Verify the GetAtCommit method signature.

Line 150 calls dataModel.GetAtCommit<IObjectWithId>(commitId, change.EntityId, changeIndex) with three parameters, but the GetObject method at line 99 shows that GetAtCommit only accepts two parameters (commitId and entityId). This would cause a compilation error unless there's an overload that accepts changeIndex.

Run the following script to check if an overload exists:

Comment thread backend/FwLite/LcmCrdt/HistoryService.cs
Comment thread frontend/viewer/src/lib/activity/utils.ts
Comment thread frontend/viewer/src/lib/services/history-service.ts
Comment thread frontend/viewer/src/lib/services/multi-window-service.ts
@github-actions

github-actions Bot commented Nov 7, 2025

Copy link
Copy Markdown
Contributor

UI unit Tests

  1 files  ±0   45 suites  ±0   21s ⏱️ +2s
111 tests ±0  111 ✅ ±0  0 💤 ±0  0 ❌ ±0 
160 runs  ±0  160 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 43288a2. ± Comparison against base commit 9f6ff7f.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Nov 7, 2025

Copy link
Copy Markdown
Contributor

C# Unit Tests

130 tests  ±0   130 ✅ ±0   19s ⏱️ +2s
 20 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 43288a2. ± Comparison against base commit 9f6ff7f.

@argos-ci

argos-ci Bot commented Nov 7, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Nov 7, 2025, 10:27 AM

@myieye
myieye merged commit 36aec34 into develop Nov 7, 2025
30 checks passed
@myieye
myieye deleted the add-context-to-activity branch November 7, 2025 11:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant