Skip to content

Lilnemo instruction modal (tips) #1493

Merged
duckduckhero merged 6 commits intomainfrom
lilnemo-instruction-modal
Sep 24, 2025
Merged

Lilnemo instruction modal (tips) #1493
duckduckhero merged 6 commits intomainfrom
lilnemo-instruction-modal

Conversation

@duckduckhero
Copy link
Contributor

No description provided.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 24, 2025

📝 Walkthrough

Walkthrough

Adds a tips modal feature and integrates it into EditorArea. Introduces a modal component, types, and a service to programmatically show it. EditorArea now determines whether to show the modal after note enhancement using a helper and session/localStorage checks, and consumes an added thankYouSessionId from useHypr.

Changes

Cohort / File(s) Summary
EditorArea integration
apps/desktop/src/components/editor-area/index.tsx
Integrates tips modal flow post-enhancement with a 1.2s delay; adds shouldShowTipsModal helper using dbCommands and localStorage; imports and invokes showTipsModal; propagates thankYouSessionId from useHypr; excludes onboarding sessions; logs errors and defaults to not showing modal.
Tips modal feature
apps/desktop/src/components/tips-modal/index.tsx, apps/desktop/src/components/tips-modal/service.ts, apps/desktop/src/components/tips-modal/types.ts
Adds TipsModal component with multi-slide UI, navigation, analytics events, and controlled open/close; adds showTipsModal(userId?) to mount/unmount modal and return a Promise; defines and exports TipsModalProps and TipSlide types; re-exports types from index.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant EA as EditorArea
  participant SH as shouldShowTipsModal
  participant DB as dbCommands
  participant LS as localStorage
  participant SV as showTipsModal (service)
  participant TM as TipsModal

  U->>EA: Trigger enhance
  EA->>EA: Enhancement succeeds
  EA->>EA: If not onboarding, wait 1.2s
  EA->>SH: shouldShowTipsModal(userId, thankYouSessionId)
  SH->>DB: Query sessions/flags
  SH->>LS: Read "tipsModalShown"
  SH-->>EA: true/false

  alt should show
    EA->>SV: showTipsModal(userId)
    SV->>TM: Render TipsModal (isOpen=true)
    TM-->>U: Display slides
    U-->>TM: Close/Complete
    TM-->>SV: onClose
    SV-->>EA: Promise resolved
    EA->>LS: Set "tipsModalShown"=true
  else skip
    EA->>EA: Continue without modal
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description Check ❓ Inconclusive No pull request description was provided by the author; while the raw summary documents multiple related changes (TipsModal component, service, types, and EditorArea integration), the PR body is empty so there is no author-written context or intent to verify. Because the description is missing, this check is inconclusive. Please add a brief PR description summarizing the motivation and key changes (including the new TipsModal, showTipsModal service, types, EditorArea integration, and the useHypr() signature change returning thankYouSessionId) and include any migration, testing steps, or backward-compatibility notes.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "Lilnemo instruction modal (tips)" directly reflects the primary change in this PR by naming the new instruction/tips modal feature; it is concise and clearly related to the changeset shown in the raw summary. It identifies the main UI component introduced and is specific enough for a teammate scanning history to understand the primary change.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch lilnemo-instruction-modal

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
apps/desktop/src/components/tips-modal/service.ts (1)

5-26: De‑dupe modal instances to avoid multiple concurrent tips modals.

If showTipsModal is called twice before the first closes, you’ll end up with stacked modals. Add a lightweight guard.

Apply this diff:

 export function showTipsModal(userId?: string): Promise<void> {
   return new Promise((resolve) => {
+    // Why: ensure only one tips modal at a time
+    const existing = document.querySelector('[data-hypr-tips-modal="true"]');
+    if (existing) {
+      resolve();
+      return;
+    }
     const modalDiv = document.createElement("div");
+    modalDiv.setAttribute("data-hypr-tips-modal", "true");
     document.body.appendChild(modalDiv);

     const root = createRoot(modalDiv);

     const handleClose = () => {
       root.unmount();
       document.body.removeChild(modalDiv);
       resolve();
     };

Optional: Convert this file to .tsx and use JSX instead of React.createElement for consistency.

apps/desktop/src/components/tips-modal/index.tsx (2)

67-87: Reduce console noise when userId is missing.

Return early instead of logging every render where userId is falsy.

-  useEffect(() => {
-    if (userId) {
+  useEffect(() => {
+    if (!userId) return;
       const events = [
         "tips_modal_intro_show",
         "tips_modal_transcript_show",
         "tips_modal_transcription_show",
         "tips_modal_intelligence_show",
       ];

       const event = events[currentSlide];
       if (event) {
         analyticsCommands.event({
           event,
           distinct_id: userId,
         });
       }
-    } else {
-      console.error("no userId available for analytics");
-    }
+    
   }, [currentSlide, userId]);

125-160: Flatten nested ternaries for slide media.

Move image metadata into an array keyed by slide index and render from it. This lowers cognitive complexity and eases adding slides.

Example outside this block:

const mediaBySlide = [
  { src: "/assets/waving.gif", alt: "Celebration animation", className: "w-48 h-36 object-contain rounded-md", style: {} },
  { src: "/assets/transcript-edit.gif", alt: "Transcript editing demonstration", className: "w-full max-w-lg h-64 object-cover rounded-md", style: { objectPosition: "center top" } },
  { src: "/assets/transcription-setting.gif", alt: "Transcription settings demonstration", className: "w-full max-w-lg h-64 object-cover rounded-md", style: { objectPosition: "center top" } },
  { src: "/assets/intelligence-setting.gif", alt: "Intelligence settings demonstration", className: "w-full max-w-lg h-64 object-cover rounded-md", style: { objectPosition: "center top" } },
];

Then render:

const media = mediaBySlide[currentSlide];
<img src={media.src} alt={media.alt} className={media.className} style={media.style} />
apps/desktop/src/components/editor-area/index.tsx (2)

33-64: Scope the “shown” flag per user to avoid cross-user bleed on shared devices.

Use a user-scoped storage key.

 async function shouldShowTipsModal(
   userId: string,
   onboardingSessionId: string,
   thankYouSessionId: string,
 ): Promise<boolean> {
   try {
-    const hasSeenTips = localStorage.getItem(TIPS_MODAL_SHOWN_KEY) === "true";
+    const storageKey = `${TIPS_MODAL_SHOWN_KEY}:${userId}`;
+    const hasSeenTips = localStorage.getItem(storageKey) === "true";
     if (hasSeenTips) {
       return false;
     }

190-202: Mark tips as shown per user and guard against double invocation.

  • Persist the shown flag with user scoping (complements the earlier refactor).
  • Optional: add a lightweight in‑module sentinel to prevent back‑to‑back timeouts from showing the modal twice.

Apply this diff:

-              localStorage.setItem(TIPS_MODAL_SHOWN_KEY, "true");
+              localStorage.setItem(`${TIPS_MODAL_SHOWN_KEY}:${userId}`, "true");
               showTipsModal(userId);

Optional sentinel outside this block:

// Why: avoid showing tips twice if multiple enhance completions race
let tipsModalInFlight = false;

And inside the timeout:

if (tipsModalInFlight) return;
tipsModalInFlight = true;
// ... after showTipsModal resolves:
tipsModalInFlight = false;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4224cb9 and 7766a24.

⛔ Files ignored due to path filters (4)
  • apps/desktop/public/assets/intelligence-setting.gif is excluded by !**/*.gif
  • apps/desktop/public/assets/transcript-edit.gif is excluded by !**/*.gif
  • apps/desktop/public/assets/transcription-setting.gif is excluded by !**/*.gif
  • apps/desktop/public/assets/waving.gif is excluded by !**/*.gif
📒 Files selected for processing (4)
  • apps/desktop/src/components/editor-area/index.tsx (3 hunks)
  • apps/desktop/src/components/tips-modal/index.tsx (1 hunks)
  • apps/desktop/src/components/tips-modal/service.ts (1 hunks)
  • apps/desktop/src/components/tips-modal/types.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,tsx,rs}

⚙️ CodeRabbit configuration file

**/*.{js,ts,tsx,rs}: 1. Do not add any error handling. Keep the existing one.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".

Files:

  • apps/desktop/src/components/tips-modal/index.tsx
  • apps/desktop/src/components/tips-modal/service.ts
  • apps/desktop/src/components/tips-modal/types.ts
  • apps/desktop/src/components/editor-area/index.tsx
🧬 Code graph analysis (4)
apps/desktop/src/components/tips-modal/index.tsx (3)
apps/desktop/src/components/tips-modal/types.ts (2)
  • TipSlide (7-10)
  • TipsModalProps (1-5)
packages/ui/src/components/ui/modal.tsx (4)
  • Modal (23-83)
  • ModalBody (99-105)
  • ModalTitle (130-136)
  • ModalDescription (143-148)
packages/ui/src/components/ui/button.tsx (1)
  • Button (37-89)
apps/desktop/src/components/tips-modal/service.ts (1)
apps/desktop/src/components/tips-modal/index.tsx (1)
  • TipsModal (30-211)
apps/desktop/src/components/tips-modal/types.ts (1)
apps/desktop/src/components/tips-modal/index.tsx (2)
  • TipsModalProps (213-213)
  • TipSlide (213-213)
apps/desktop/src/components/editor-area/index.tsx (2)
apps/desktop/src/contexts/hypr.tsx (1)
  • useHypr (63-69)
apps/desktop/src/components/tips-modal/service.ts (1)
  • showTipsModal (5-26)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: ci (macos, macos-14)
  • GitHub Check: ci (windows, windows-latest)
🔇 Additional comments (4)
apps/desktop/src/components/tips-modal/types.ts (2)

1-5: Types look good and minimal.

Props surface is concise and matches usage in the modal and service.


7-10: Slide type is appropriately scoped.

Fits current needs; easy to extend later if images/ids are added.

apps/desktop/src/components/tips-modal/index.tsx (1)

30-66: Component structure and analytics hooks look solid.

State reset on close/complete and event emissions are correctly scoped to userId.

apps/desktop/src/components/editor-area/index.tsx (1)

127-127: Resolved — useHypr exposes thankYouSessionId

HyprProvider sets thankYouSessionId and useHypr returns it; no change required.

@duckduckhero duckduckhero merged commit f986a98 into main Sep 24, 2025
11 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Oct 1, 2025
@ComputelessComputer ComputelessComputer deleted the lilnemo-instruction-modal branch December 14, 2025 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant