Skip to content

Fix modal action button click handling#1785

Merged
riderx merged 16 commits into
mainfrom
riderx/fix-deploy-modal
Mar 18, 2026
Merged

Fix modal action button click handling#1785
riderx merged 16 commits into
mainfrom
riderx/fix-deploy-modal

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented Mar 12, 2026

Summary (AI generated)

  • Fixed DialogV2 footer actions to handle click events consistently so links and buttons can trigger expected dialog behavior.
  • Preserved normal keyboard/mouse modified click handling for anchor-based modal actions.
  • Added secure window.open options for _blank navigation to always include noopener.
  • Updated close flow to avoid swallowing href link interactions when modifier keys are used.

Motivation (AI generated)

Users reported the deployment-status modal action button was not behaving correctly and needed a safe interaction model that still supports browser-native link semantics.

Business Impact (AI generated)

This restores reliable modal action behavior while preserving expected navigation patterns, preventing users from being blocked or redirected unexpectedly.

Test Plan (AI generated)

  • bun lint
  • Manual verification of modal actions for normal left click and modifier-click behavior (Cmd/Ctrl/Shift/middle)
  • Playwright coverage for deployment modal action interactions

Screenshots

  • Not included (UI interaction behavior change only).

Checklist (AI generated)

  • My code follows the code style of this project and passes lint checks.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • My change has adequate E2E test coverage.
  • I have tested my code manually, and I have provided steps how to reproduce my tests

Summary by CodeRabbit

  • New Features

    • Improved dialog button handling: normalized link attributes and a skip-navigation option to control post-close navigation; Escape-key and route-change dismissals are tracked and cleaned up.
  • Bug Fixes

    • Click handling tightened to respect disabled state, modifier/non-left clicks, and prevent-close behavior; route watcher and Escape listener removed on unmount.
  • Style

    • Disabled controls now use opacity/pointer-event handling; disabled links expose aria-disabled/tabindex.
  • Localization

    • Updated onboarding/install copy across many locales to include a 2–10 minute time estimate.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds typed close handling, Escape-key listener, and route-change watcher to DialogV2; normalizes link rel, unifies button/anchor click handling to detect modifier/non-left clicks and optionally prevent navigation; dialog store gains skipNavigation on buttons and conditionally performs navigation after close; multiple localization strings updated.

Changes

Cohort / File(s) Summary
Dialog Component
src/components/DialogV2.vue
Adds WatchStopHandle import, onUnmounted cleanup, escapeHandler and stopRouteWatch; normalizeRel(rel,target) for anchor rel composition; expands close(button?: DialogV2Button) typing; rewrites handleButtonClick to detect modifiers/non-left clicks, compute shouldPreventNavigation, respect skipNavigation, and unify anchor/button handling; updates disabled styling/attributes for anchors and buttons.
Dialog Store
src/stores/dialogv2.ts
Adds skipNavigation?: boolean to DialogV2Button; resets lastButtonRole and dialogCanceled on open; openButtonHref builds rel via a Set (always includes noopener); closeDialog performs conditional navigation only when button.href exists and button.skipNavigation is not true; preserves preventClose / dismiss behavior.
Localizations
messages/*.json
messages/en.json, messages/de.json, messages/es.json, messages/fr.json, messages/hi.json, messages/id.json, messages/it.json, messages/ja.json, messages/ko.json, messages/pl.json, messages/pt-br.json, messages/ru.json, messages/tr.json, messages/vi.json, messages/zh-cn.json
Expanded copy for two keys (init-capgo-in-your-a, onboarding-cli-where-why) across many locales to add a 2–10 minute time estimate and onboarding context; no logic changes.

Sequence Diagram

sequenceDiagram
    actor User
    participant DialogV2 as DialogV2
    participant Handler as handleButtonClick
    participant Store as dialogv2 Store
    participant Router as Browser/Router

    User->>DialogV2: click button or anchor (or press Escape)
    DialogV2->>Handler: handleButtonClick(button, event)
    Handler->>Handler: normalizeRel -> safeButton
    Handler->>Handler: compute hasModifier / isLeftClick / isModifiedLinkClick
    alt disabled
        Handler-->>DialogV2: ignore click
    else modified or non-left click for href
        Handler->>Handler: event.preventDefault()
        Handler->>Store: close(button with skipNavigation=true)
    else allowed href or non-href
        Handler->>Store: close(button)
    end

    rect rgba(120,180,240,0.5)
    Store->>Store: evaluate preventClose / dialogCanceled
    alt allow close
        Store->>Store: showDialog = false
        opt button.href present and not skipNavigation
            Store->>Router: openButtonHref(button) -> navigate (router.push or window.open)
        end
    else preventClose
        Store-->>DialogV2: remain open
    end
    end

    alt Escape pressed or route change
        DialogV2->>Store: close(undefined) or close due to route watcher
    end

    DialogV2->>DialogV2: onUnmounted -> stopRouteWatch, remove Escape listener
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

enhancement

Poem

🐰 I hop on keys and watch the gate,
I catch Escape and tidy state.
Links that wander, clicks that roam,
I hush the route and guide them home.
A careful rabbit, quick and brave.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description includes a summary with AI-generated context and motivation. However, it lacks detailed steps for the Test Plan and is missing explicit checklist confirmations for documentation and E2E test coverage requirements. Expand the Test Plan section with specific reproducible steps for testing modal action interactions. Clearly confirm or explain the status of documentation updates and E2E test coverage checklist items.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix modal action button click handling' is clear, concise, and directly related to the main changes in the PR, which focus on fixing DialogV2 button/link click event handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch riderx/fix-deploy-modal
📝 Coding Plan
  • Generate coding plan for human review comments

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

Copy link
Copy Markdown
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: 2

Caution

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

⚠️ Outside diff range comments (1)
src/stores/dialogv2.ts (1)

30-34: ⚠️ Potential issue | 🟠 Major

Mark passive dismissals as canceled and clear stale button metadata.

The no-button path only hides the dialog. onDialogDismiss() will therefore resolve false for overlay/Escape/close-icon dismissals, and lastButtonRole can carry over from the previous dialog.

💡 Proposed fix
   const openDialog = (options: DialogV2Options) => {
     dialogOptions.value = options
     showDialog.value = true
     dialogCanceled.value = false
+    lastButtonRole.value = ''
   }
@@
-    // Modal dismissed without a button action (overlay, escape, close icon)
+    // Modal dismissed without a button action (overlay, escape, close icon)
+    dialogCanceled.value = true
+    lastButtonRole.value = ''
     showDialog.value = false
   }

Also applies to: 84-85

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/stores/dialogv2.ts` around lines 30 - 34, openDialog currently only shows
the dialog and resets dialogCanceled but doesn't clear stale button metadata or
ensure passive dismissals are marked canceled; update openDialog (and the
symmetrical close/dismiss path where showDialog is set to false) to explicitly
set dialogCanceled.value = true for passive dismissals and clear
lastButtonRole/any last button metadata when opening a new dialog by resetting
lastButtonRole (and any related lastButton* state) to null/undefined so a
previous button role cannot leak into onDialogDismiss() results; locate and
change the openDialog function and the dismiss/close code path that hides the
dialog (the code that sets showDialog.value = false) to perform these resets.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/DialogV2.vue`:
- Around line 20-29: handleButtonClick currently prevents default for every
button.href which breaks modified clicks; change it so event.preventDefault() is
only called when the click should open in the same tab: i.e., when button.href
is set AND (event is undefined/programmatic OR the event is a MouseEvent with
left-button (event.button === 0) and no modifier keys (event.metaKey,
event.ctrlKey, event.shiftKey, event.altKey) ); otherwise do not call
preventDefault so Cmd/Ctrl/Shift/middle-clicks keep normal browser behavior;
update the logic inside handleButtonClick (and any places using
DialogV2Button/close) to implement this check.

In `@src/stores/dialogv2.ts`:
- Around line 43-47: The _blank branch currently calls window.open without
ensuring noopener is set; modify the block that checks button.target ===
'_blank' so it always supplies a third-argument feature string to window.open
containing "noopener" (and "noreferrer" if desired) by normalizing button.rel
into a comma-separated list, deduplicating any existing entries, and joining
them with commas (e.g., build a variable like relFeatures from button.rel and
"noopener" then call window.open(button.href, button.target, relFeatures));
ensure both branches call window.open with that relFeatures string rather than
omitting the third argument.

---

Outside diff comments:
In `@src/stores/dialogv2.ts`:
- Around line 30-34: openDialog currently only shows the dialog and resets
dialogCanceled but doesn't clear stale button metadata or ensure passive
dismissals are marked canceled; update openDialog (and the symmetrical
close/dismiss path where showDialog is set to false) to explicitly set
dialogCanceled.value = true for passive dismissals and clear lastButtonRole/any
last button metadata when opening a new dialog by resetting lastButtonRole (and
any related lastButton* state) to null/undefined so a previous button role
cannot leak into onDialogDismiss() results; locate and change the openDialog
function and the dismiss/close code path that hides the dialog (the code that
sets showDialog.value = false) to perform these resets.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a5d19fc4-dac1-48a1-905f-68987d0d2d18

📥 Commits

Reviewing files that changed from the base of the PR and between 22020f6 and 2c20416.

📒 Files selected for processing (2)
  • src/components/DialogV2.vue
  • src/stores/dialogv2.ts

Comment thread src/components/DialogV2.vue Outdated
Comment thread src/stores/dialogv2.ts Outdated
Copy link
Copy Markdown
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.

🧹 Nitpick comments (4)
src/stores/dialogv2.ts (1)

77-83: Consider consolidating the duplicate preventClose checks.

The !button.preventClose condition is evaluated twice. Nesting the href check would be cleaner:

♻️ Proposed simplification
-      if (!button.preventClose) {
-        showDialog.value = false
-      }
-
-      if (!button.preventClose && button.href)
-        openButtonHref(button)
+      if (!button.preventClose) {
+        showDialog.value = false
+        if (button.href)
+          openButtonHref(button)
+      }
       return
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/stores/dialogv2.ts` around lines 77 - 83, Consolidate the duplicate
checks by combining the two !button.preventClose branches into one: if
(!button.preventClose) { showDialog.value = false; if (button.href)
openButtonHref(button); } then return; Update the block that currently checks
!button.preventClose twice (the code touching showDialog.value and
openButtonHref) to this single nested check to avoid redundant evaluation.
src/components/DialogV2.vue (3)

50-55: Event listener not cleaned up on unmount.

The keydown listener is added globally but never removed. If this component is ever unmounted and remounted, listeners will accumulate.

♻️ Proposed fix using onUnmounted
+import { onMounted, onUnmounted, watch } from 'vue'
-import { onMounted, watch } from 'vue'

+let escapeHandler: ((event: KeyboardEvent) => void) | null = null
+
 onMounted(() => {
   // Close dialog on route change
   watch(route, () => {
     if (dialogStore.showDialog) {
       dialogStore.closeDialog()
     }
   })

   // Close dialog on Escape key
-  addEventListener('keydown', (event: KeyboardEvent) => {
+  escapeHandler = (event: KeyboardEvent) => {
     if (event.key === 'Escape' && dialogStore.showDialog && !dialogStore.dialogOptions?.preventAccidentalClose) {
       dialogStore.closeDialog()
     }
-  })
+  }
+  addEventListener('keydown', escapeHandler)
+})
+
+onUnmounted(() => {
+  if (escapeHandler) {
+    removeEventListener('keydown', escapeHandler)
+    escapeHandler = null
+  }
 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/DialogV2.vue` around lines 50 - 55, The global keydown
listener added with addEventListener in DialogV2.vue is never removed, causing
handler accumulation on remount; wrap the listener registration in the component
setup and register a named handler (e.g., onKeydown or handleEscape) and call
removeEventListener for that same function inside an onUnmounted hook, keeping
the existing condition using dialogStore.showDialog and
dialogStore.dialogOptions?.preventAccidentalClose and ensuring
dialogStore.closeDialog() is invoked when Escape is detected.

118-120: Redundant cursor-not-allowed class in both button and anchor.

cursor-not-allowed appears twice when disabled (once standalone, once in the compound rule). Can be simplified:

♻️ Proposed cleanup
                  '!cursor-pointer': !button.disabled,
-                 'cursor-not-allowed': button.disabled,
-                 'opacity-70 cursor-not-allowed pointer-events-none': button.disabled,
+                 'opacity-70 cursor-not-allowed': button.disabled,
+                 'pointer-events-none': button.disabled,

Note: For the <button> element, pointer-events-none may not be needed since :disabled handles click prevention natively.

Also applies to: 139-141

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/DialogV2.vue` around lines 118 - 120, The class binding for
the disabled control in DialogV2.vue redundantly applies 'cursor-not-allowed'
twice and adds 'pointer-events-none' where native :disabled already prevents
clicks; update the class object that references button.disabled so it only
includes 'cursor-not-allowed' once (remove the standalone or the one in the
compound rule) and remove 'pointer-events-none' for actual <button> elements
(keep pointer-events-none only for anchors if used); adjust the same pattern
where button.disabled is used later (the similar block around the other
occurrence) so both locations use the simplified class list.

128-146: Add aria-disabled for accessibility on disabled anchor buttons.

Disabled anchors lack semantic indication for assistive technologies. While pointer-events-none prevents clicks visually, screen readers need explicit notification.

♿ Proposed accessibility fix
              <a
                v-else
                :href="button.href"
                :target="button.target"
                :rel="button.rel"
+               :aria-disabled="button.disabled || undefined"
+               :tabindex="button.disabled ? -1 : undefined"
                :class="{
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/DialogV2.vue` around lines 128 - 146, The anchor rendering in
DialogV2.vue should expose disabled state to assistive tech: when rendering the
<a> for a button with button.disabled true, add an aria-disabled attribute bound
to the boolean (e.g., :aria-disabled="button.disabled") and remove it when
false; also ensure the anchor becomes unfocusable when disabled by adding
:tabindex="button.disabled ? -1 : undefined" and keep the existing click guard
in handleButtonClick to no-op when button.disabled is true. Update the <a>
element binding for aria-disabled and tabindex and confirm handleButtonClick
checks button.disabled before acting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/components/DialogV2.vue`:
- Around line 50-55: The global keydown listener added with addEventListener in
DialogV2.vue is never removed, causing handler accumulation on remount; wrap the
listener registration in the component setup and register a named handler (e.g.,
onKeydown or handleEscape) and call removeEventListener for that same function
inside an onUnmounted hook, keeping the existing condition using
dialogStore.showDialog and dialogStore.dialogOptions?.preventAccidentalClose and
ensuring dialogStore.closeDialog() is invoked when Escape is detected.
- Around line 118-120: The class binding for the disabled control in
DialogV2.vue redundantly applies 'cursor-not-allowed' twice and adds
'pointer-events-none' where native :disabled already prevents clicks; update the
class object that references button.disabled so it only includes
'cursor-not-allowed' once (remove the standalone or the one in the compound
rule) and remove 'pointer-events-none' for actual <button> elements (keep
pointer-events-none only for anchors if used); adjust the same pattern where
button.disabled is used later (the similar block around the other occurrence) so
both locations use the simplified class list.
- Around line 128-146: The anchor rendering in DialogV2.vue should expose
disabled state to assistive tech: when rendering the <a> for a button with
button.disabled true, add an aria-disabled attribute bound to the boolean (e.g.,
:aria-disabled="button.disabled") and remove it when false; also ensure the
anchor becomes unfocusable when disabled by adding :tabindex="button.disabled ?
-1 : undefined" and keep the existing click guard in handleButtonClick to no-op
when button.disabled is true. Update the <a> element binding for aria-disabled
and tabindex and confirm handleButtonClick checks button.disabled before acting.

In `@src/stores/dialogv2.ts`:
- Around line 77-83: Consolidate the duplicate checks by combining the two
!button.preventClose branches into one: if (!button.preventClose) {
showDialog.value = false; if (button.href) openButtonHref(button); } then
return; Update the block that currently checks !button.preventClose twice (the
code touching showDialog.value and openButtonHref) to this single nested check
to avoid redundant evaluation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8a69ca97-554a-4437-9cb4-e1aadab69ed7

📥 Commits

Reviewing files that changed from the base of the PR and between 2c20416 and f19cf5e.

📒 Files selected for processing (2)
  • src/components/DialogV2.vue
  • src/stores/dialogv2.ts

Copy link
Copy Markdown
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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/DialogV2.vue`:
- Line 4: Reorder the Vue imports so type-only imports come after value imports
to satisfy the perfectionist/sort-imports rule: move the type import
"WatchStopHandle" (import type { WatchStopHandle } from 'vue') below any
non-type imports from 'vue' in DialogV2.vue (or combine value and type imports
into a single statement with the value members first and "type { WatchStopHandle
}" after), then run the frontend linter fixer (bun lint:fix) before committing.

In `@src/stores/dialogv2.ts`:
- Line 49: The lint error comes from the arrow function used inside
relTokens.some; change the arrow callback from using parentheses around the
single parameter to the idiomatic form without them (i.e., replace (token) =>
token.toLowerCase() === 'noreferrer' with token => token.toLowerCase() ===
'noreferrer') so the style/arrow-parens rule is satisfied in the
relTokens.some(...) expression.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e0c15fc6-9bfb-4894-bbf9-938b6dfcf083

📥 Commits

Reviewing files that changed from the base of the PR and between f19cf5e and a7010cf.

📒 Files selected for processing (2)
  • src/components/DialogV2.vue
  • src/stores/dialogv2.ts

Comment thread src/components/DialogV2.vue
Comment thread src/stores/dialogv2.ts Outdated
Copy link
Copy Markdown
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/DialogV2.vue`:
- Around line 31-35: The early return for modified clicks (isModifiedLinkClick)
skips close(button) and the window.open hardening; change the branch so that for
modified link clicks you still call close(button) and enforce noopener when
button.target === '_blank' (add 'noopener' to button.rel if missing) or
otherwise run the same window.open hardening logic before returning; reference
the hasModifier/isModifiedLinkClick check and ensure close(button),
button.target, button.rel and the window.open hardening code paths are executed
for that case.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 00da4828-35c1-47da-beb9-110836a1eb14

📥 Commits

Reviewing files that changed from the base of the PR and between a7010cf and adfb1a3.

📒 Files selected for processing (2)
  • src/components/DialogV2.vue
  • src/stores/dialogv2.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/stores/dialogv2.ts

Comment thread src/components/DialogV2.vue
Copy link
Copy Markdown
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: 3

🧹 Nitpick comments (2)
messages/id.json (1)

1114-1114: Optional consistency polish for mixed-language terms.

Consider localizing update and web app to keep Indonesian terminology more consistent in this sentence.

✏️ Suggested wording adjustment
-  "onboarding-cli-where-why": "Buka terminal di proyek Capacitor Anda (folder yang berisi package.json) dan jalankan perintah ini. Langkah onboarding sederhana ini biasanya memakan waktu 2 hingga 10 menit dan memungkinkan Anda menguji update pertama di aplikasi Anda dengan Capgo Updater. Kami menggunakan CLI (bukan web app) karena CLI memeriksa kode native, mendeteksi detail aplikasi secara otomatis, dan menerapkan pengaturan paling aman.",
+  "onboarding-cli-where-why": "Buka terminal di proyek Capacitor Anda (folder yang berisi package.json) dan jalankan perintah ini. Langkah onboarding sederhana ini biasanya memakan waktu 2 hingga 10 menit dan memungkinkan Anda menguji pembaruan pertama di aplikasi Anda dengan Capgo Updater. Kami menggunakan CLI (bukan aplikasi web) karena CLI memeriksa kode native, mendeteksi detail aplikasi secara otomatis, dan menerapkan pengaturan paling aman.",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@messages/id.json` at line 1114, The string for key "onboarding-cli-where-why"
mixes English terms "update" and "web app"; please revise the value to
consistently use Indonesian equivalents (e.g., replace "update" with "pembaruan"
and "web app" with "aplikasi web") while preserving the original meaning and
punctuation so the JSON key "onboarding-cli-where-why" remains unchanged.
src/components/DialogV2.vue (1)

13-21: Consider centralizing rel normalization in one shared utility.

normalizeRel here and the _blank feature normalization in the store now encode related rules in two places; extracting one shared helper would reduce drift risk over time.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/DialogV2.vue` around lines 13 - 21, The rel normalization
logic is duplicated between the normalizeRel function in DialogV2.vue and the
_blank handling in the store; extract this into a shared utility (e.g., create a
helper function normalizeRel in a common utils module) and replace both the
local normalizeRel and the store's inline _blank normalization to call that
shared helper (update imports and usages for normalizeRel in DialogV2.vue and
the store code to use the new centralized function).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@messages/es.json`:
- Line 893: Replace the awkward time phrasing for the "init-capgo-in-your-a"
message key: change the string value "Instala Capgo en tu aplicación Capacitor
en 2 a 10 minutos" to the more natural Spanish "Instala Capgo en tu aplicación
Capacitor entre 2 y 10 minutos" so it matches the phrasing used elsewhere (e.g.,
line 1114) and improves readability.

In `@messages/ru.json`:
- Line 1114: The phrasing for the "onboarding-cli-where-why" message is
grammatically awkward due to the feminine pronoun "она" referring to CLI; update
the string to use a neutral construction such as "CLI проверяет нативный код"
(e.g., replace "потому что она проверяет нативный код" with "потому что CLI
проверяет нативный код") and ensure any following verbs/phrases agree (e.g.,
keep "автоматически определяет детали приложения и применяет самый безопасный
вариант настройки") so the whole sentence reads naturally in Russian.

In `@src/stores/dialogv2.ts`:
- Around line 47-53: The code currently passes arbitrary tokens from button.rel
into window.open's features via relFeatures (relTokens, relSet, relFeatures),
which can trigger popup behavior; instead only allow the safe tokens 'noopener'
and 'noreferrer' and drop any other rel values before calling window.open.
Change the logic around relTokens/relSet to explicitly build a list containing
only 'noopener' and, if present in the original rel (case-insensitive),
'noreferrer', then join that list into relFeatures and pass it to
window.open(button.href, button.target, relFeatures).

---

Nitpick comments:
In `@messages/id.json`:
- Line 1114: The string for key "onboarding-cli-where-why" mixes English terms
"update" and "web app"; please revise the value to consistently use Indonesian
equivalents (e.g., replace "update" with "pembaruan" and "web app" with
"aplikasi web") while preserving the original meaning and punctuation so the
JSON key "onboarding-cli-where-why" remains unchanged.

In `@src/components/DialogV2.vue`:
- Around line 13-21: The rel normalization logic is duplicated between the
normalizeRel function in DialogV2.vue and the _blank handling in the store;
extract this into a shared utility (e.g., create a helper function normalizeRel
in a common utils module) and replace both the local normalizeRel and the
store's inline _blank normalization to call that shared helper (update imports
and usages for normalizeRel in DialogV2.vue and the store code to use the new
centralized function).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 652ae220-6084-481f-8843-a7f985a30a5f

📥 Commits

Reviewing files that changed from the base of the PR and between adfb1a3 and f654f2e.

📒 Files selected for processing (17)
  • messages/de.json
  • messages/en.json
  • messages/es.json
  • messages/fr.json
  • messages/hi.json
  • messages/id.json
  • messages/it.json
  • messages/ja.json
  • messages/ko.json
  • messages/pl.json
  • messages/pt-br.json
  • messages/ru.json
  • messages/tr.json
  • messages/vi.json
  • messages/zh-cn.json
  • src/components/DialogV2.vue
  • src/stores/dialogv2.ts
✅ Files skipped from review due to trivial changes (2)
  • messages/vi.json
  • messages/de.json

Comment thread messages/es.json Outdated
Comment thread messages/ru.json Outdated
Comment thread src/stores/dialogv2.ts Outdated
@sonarqubecloud
Copy link
Copy Markdown

@riderx riderx merged commit 32ef36b into main Mar 18, 2026
14 of 15 checks passed
@riderx riderx deleted the riderx/fix-deploy-modal branch March 18, 2026 19:06
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