Skip to content

Conversation

@grv-saini-20
Copy link
Collaborator

@grv-saini-20 grv-saini-20 commented Nov 17, 2025

Description of change

  • Button is disabled now if verification code field is empty.
  • Cancel button working perfectly now in delete account modal.
  • Fixed the closing of drawer which was not working earlier.

Issue Number

closes #445
closes #442
closes #450

Type of change

  • Update (a change which updates existing functionality)
  • Fix (a change which fixes an issue)

How the change has been tested

manual

Change checklist

  • I have ensured that the CI Checks pass locally
  • I have removed any unnecessary logic
  • My code is well documented
  • I have signed my commits
  • My code follows the pattern of the application
  • I have self reviewed my code

Summary by CodeRabbit

  • New Features

    • Reworked onboarding UI into staged pre-verification and verification steps with clearer device-check messaging, reliable loading/error handling, and dynamic Next/Continue button states.
    • Version tap interaction enhanced with multi-tap feedback and retry behavior.
  • Bug Fixes

    • Confirmation drawers now render conditionally and can be dismissed by tapping the backdrop.
    • Loading and error states consistently reset on failures.
  • Chores

    • Minor formatting and whitespace cleanups.

@grv-saini-20 grv-saini-20 self-assigned this Nov 17, 2025
@grv-saini-20 grv-saini-20 requested a review from coodos as a code owner November 17, 2025 07:22
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 17, 2025

Walkthrough

Refactors onboarding control flow into explicit branches, converts pre-verification provisioning into an entropy → provision two-step with centralized try/catch/finally error handling, disables Next/Continue until required inputs are non-empty, conditions Settings drawers rendering, and adds backdrop-to-close handling to the Drawer.

Changes

Cohort / File(s) Summary
Onboarding flow & UI
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
Restructures conditional rendering (checkingHardware, showHardwareError, preVerified, final). Changes provisioning to fetch entropy then call provision, validates provision response, centralizes pre-verification error handling (resets verificationId, sets user error with 6s timeout), ensures loading cleared in finally, and ties Next/Continue button variant & disabled state to verificationId.length and demoName.length.
Settings pages & drawer visibility
infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte
Adds onDestroy import and timeoutId lifecycle cleanup; manages tap-count timeout for version taps and retry flow with try/catch; replaces unconditional Drawer blocks with conditional {#if isDeleteConfirmationOpen} / {#if isFinalConfirmationOpen} blocks to control drawer visibility.
Drawer backdrop-to-close
infrastructure/eid-wallet/src/lib/ui/Drawer/Drawer.svelte
Adds onBackdropTap handler to CupertinoPane init to destroy the pane and set isPaneOpen = false when backdrop is tapped, enabling tap-outside-to-close behavior.
Image preview / utils formatting
platforms/blabsy/src/components/input/image-preview.tsx, platforms/blabsy/src/lib/utils/image-utils.ts
Whitespace and multi-line formatting adjustments only; no behavior changes.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Onboard as Onboarding Page
    participant Keys as Key Manager
    participant Verif as Verification Service

    User->>Onboard: Open onboarding
    Onboard->>Keys: Check hardware / initialize keys
    alt checkingHardware
        Onboard->>User: "Checking device capabilities..."
        Keys-->>Onboard: hardware result
    else showHardwareError
        Onboard->>User: Show hardware unavailable
        User->>Onboard: Choose pre-verification
    else preVerified
        Onboard->>User: Show verification input (Next disabled if empty)
        User->>Onboard: Submit code
        Onboard->>Verif: Fetch entropy
        Onboard->>Verif: Provision request (with entropy)
        Verif-->>Onboard: provision response (validate success)
        Onboard->>User: Show verificationId / errors
    else final
        Onboard->>User: Show demo name input (Continue disabled if empty)
        User->>Onboard: Submit
        Onboard->>Keys: Finalize wallet provisioning
        Keys-->>Onboard: success
    end
Loading
sequenceDiagram
    participant User
    participant Drawer as Drawer (CupertinoPane)

    User->>Drawer: Tap backdrop
    Drawer->>Drawer: onBackdropTap handler runs
    Drawer-->>User: Destroy pane, set isPaneOpen = false (pane closed)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

  • Pay extra attention to:
    • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte — provisioning sequence (entropy → provision), response validation, centralized error handling, and that button enablement correctly prevents empty submissions.
    • infrastructure/eid-wallet/src/lib/ui/Drawer/Drawer.svelteonBackdropTap behavior for double-destroy or state races.
    • infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte — timeout cleanup and conditional drawer rendering preserving cancel/confirm callbacks.

Possibly related PRs

  • feat: setup hw crypto #295 — modifies onboarding provisioning payload/flow; likely overlaps onboarding entropy/provision changes.
  • feat: health check #437 — edits Drawer/CupertinoPane initialization/backdrop handling; related to backdrop-to-close addition.
  • feat:Drawer #152 — earlier Drawer/backdrop adjustments; related surface area.

Suggested reviewers

  • coodos
  • sosweetham
  • pixel-punk-20

Poem

🐇 I hopped through branches, tidy and bright,
Buttons wait patient till inputs feel right,
A soft tap on the pane sends the drawer away,
Entropy hums, keys wake at the start of the day,
Hop, click, provision — a wallet leaps to play.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 2 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'fix: ui-bugs-eidwallet' is vague and generic, using non-descriptive terms that don't convey meaningful information about the specific changes made. Use a more specific title that highlights the main fixes, e.g., 'fix: improve button states and drawer closing behavior' or 'fix: handle verification input validation and drawer interactions'.
Out of Scope Changes check ❓ Inconclusive Most changes are in-scope; however, whitespace-only edits in image-preview.tsx and image-utils.ts are formatting changes unrelated to the three linked UI bug fixes. Consider removing formatting-only changes in blabsy platform files (image-preview.tsx, image-utils.ts) as they are outside the scope of eid-wallet UI bug fixes.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The PR description covers all template sections with clear issue references, type of change, testing approach, and completed checklist items, though lacks detailed 'How tested' specifics.
Linked Issues check ✅ Passed Changes address all three linked issues: verification button disabled when empty [#445], cancel button functionality restored in delete modal [#442], and drawer backdrop tap closing enabled [#450].
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/ui-bugs-eidwallet

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92c6042 and 5c88c0c.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte (6 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-14T17:54:47.719Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 437
File: infrastructure/eid-wallet/src/lib/global/controllers/security.ts:138-157
Timestamp: 2025-11-14T17:54:47.719Z
Learning: The `setOnboardingPin` method in `infrastructure/eid-wallet/src/lib/global/controllers/security.ts` is intentionally designed to allow overwriting existing PINs without checking if a PIN already exists. This is a workaround for Android keeping stale files around during app reinstallation or onboarding, which causes errors on some devices. Do not suggest adding guards to prevent PIN overwrites in this method.

Applied to files:

  • infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte
⏰ 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: build
  • GitHub Check: lint
🔇 Additional comments (3)
infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte (3)

15-15: LGTM! Memory leak fixed with lifecycle cleanup.

The addition of onDestroy with timeout cleanup addresses the memory leak concern from the previous review. The timeout will now be properly cleared when the component unmounts, preventing stale state updates.

Also applies to: 30-30, 53-56


48-51: LGTM! Fixes the Cancel button behavior.

The cancelDelete function correctly closes both confirmation drawers, which should fix issue #442. When users tap Cancel, the drawer will close and they'll return to the Settings screen as expected.


160-187: LGTM! Conditional rendering fixes drawer closing behavior.

Wrapping the drawers in {#if} blocks with bind:isPaneOpen enables the Drawer component to properly manage visibility and respond to backdrop clicks. This should fix issue #450, allowing users to close the drawer by clicking outside as expected.

The conditional rendering also improves performance by not rendering drawer DOM elements when they're not needed.

Also applies to: 190-219


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: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7281abd and 93a3f83.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (3 hunks)
⏰ 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). (1)
  • GitHub Check: build

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: 1

Caution

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

⚠️ Outside diff range comments (1)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (1)

232-261: Loading state is never cleared in handleFinalSubmit.

The function sets loading = true at line 233 but never resets it to false. The loading spinner will remain visible for 10 seconds minimum (until navigation), and if navigation fails, the spinner persists indefinitely with no user feedback. Additionally, if any of the operations throw (e.g., setting vault data), there's no error handling.

Apply this diff to properly manage the loading state and add error handling:

 handleFinalSubmit = async () => {
-    loading = true;
-
-    const tenYearsLater = new Date();
-    tenYearsLater.setFullYear(tenYearsLater.getFullYear() + 10);
-    globalState.userController.user = {
-        name:
-            demoName ||
-            capitalize(`${falso.randFirstName()} ${falso.randLastName()}`),
-        "Date of Birth": new Date().toDateString(),
-        "ID submitted": `Passport - ${falso.randCountryCode()}`,
-        "Passport Number": generatePassportNumber(),
-    };
-    globalState.userController.isFake = true;
-    globalState.userController.document = {
-        "Valid From": new Date(Date.now()).toDateString(),
-        "Valid Until": tenYearsLater.toDateString(),
-        "Verified On": new Date().toDateString(),
-    };
-
-    // Set vault in controller - this will trigger profile creation with retry logic
-    globalState.vaultController.vault = {
-        uri,
-        ename,
-    };
-
-    setTimeout(() => {
-        goto("/register");
-    }, 10_000);
+    try {
+        loading = true;
+
+        const tenYearsLater = new Date();
+        tenYearsLater.setFullYear(tenYearsLater.getFullYear() + 10);
+        globalState.userController.user = {
+            name:
+                demoName ||
+                capitalize(`${falso.randFirstName()} ${falso.randLastName()}`),
+            "Date of Birth": new Date().toDateString(),
+            "ID submitted": `Passport - ${falso.randCountryCode()}`,
+            "Passport Number": generatePassportNumber(),
+        };
+        globalState.userController.isFake = true;
+        globalState.userController.document = {
+            "Valid From": new Date(Date.now()).toDateString(),
+            "Valid Until": tenYearsLater.toDateString(),
+            "Verified On": new Date().toDateString(),
+        };
+
+        // Set vault in controller - this will trigger profile creation with retry logic
+        globalState.vaultController.vault = {
+            uri,
+            ename,
+        };
+
+        setTimeout(() => {
+            loading = false;
+            goto("/register");
+        }, 10_000);
+    } catch (err) {
+        console.error("Failed to finalize onboarding:", err);
+        error = "Failed to complete onboarding. Please try again.";
+        loading = false;
+        setTimeout(() => {
+            error = null;
+        }, 5000);
+    }
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 93a3f83 and e27f40b.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-14T17:54:47.711Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 437
File: infrastructure/eid-wallet/src/lib/global/controllers/security.ts:138-157
Timestamp: 2025-11-14T17:54:47.711Z
Learning: The `setOnboardingPin` method in `infrastructure/eid-wallet/src/lib/global/controllers/security.ts` is intentionally designed to allow overwriting existing PINs without checking if a PIN already exists. This is a workaround for Android keeping stale files around during app reinstallation or onboarding, which causes errors on some devices. Do not suggest adding guards to prevent PIN overwrites in this method.

Applied to files:

  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
🔇 Additional comments (2)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (2)

305-311: Button state correctly reflects hardware checking.

The disabled state and dynamic text properly prevent interaction during hardware capability checks, providing clear user feedback.


368-373: Perfect implementation of the PR objective!

The button is now correctly disabled when the verification code field is empty, preventing the error reported in issue #445. Both the disabled attribute and the variant prop provide clear visual feedback to users that the button is not actionable until they enter a code.

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: 1

Caution

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

⚠️ Outside diff range comments (1)
infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte (1)

1-209: Major inconsistency: File doesn't match PR objective.

The PR objective states this fixes issue #445, which requires disabling the "generate ename button" when the verification code field is empty on the onboarding page. However, this file is the settings page and contains no code related to verification code inputs or the generate ename button.

Either the onboarding page changes (infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte mentioned in the AI summary) are missing from this review, or this PR contains unrelated changes that should be in a separate PR.

🧹 Nitpick comments (2)
infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte (2)

150-177: Potential state synchronization issue with conditional rendering and bind.

The pattern {#if isDeleteConfirmationOpen} + bind:isPaneOpen={isDeleteConfirmationOpen} is redundant and may cause issues:

  1. When the drawer closes, it tries to set isPaneOpen to false via the bind
  2. But the {#if} condition removes the component from the DOM when the state becomes false
  3. This race condition could prevent the bind from updating properly or cause the component to be destroyed mid-transition

Either:

  • Remove the {#if} wrapper and let the Drawer component handle visibility internally (if it supports this), OR
  • Remove the bind:isPaneOpen and handle closing purely through the cancelDelete/confirmDelete functions

Example of option 2:

-{#if isDeleteConfirmationOpen}
-    <Drawer bind:isPaneOpen={isDeleteConfirmationOpen}>
+<Drawer isPaneOpen={isDeleteConfirmationOpen} onClose={() => isDeleteConfirmationOpen = false}>

This same issue applies to the final confirmation drawer (lines 180-209).


135-145: Fragile color logic based on emoji string matching.

The color determination uses retryMessage.includes('✅') which is fragile. If the message text changes or the emoji is different, the coloring breaks.

Consider using explicit state for message type:

 let isRetrying = $state(false);
 let retryMessage = $state("");
+let retryStatus = $state<"info" | "success" | "error" | null>(null);

Then update the class binding:

-class="mt-2 text-sm {isRetrying
-    ? 'text-blue-600'
-    : retryMessage.includes('✅')
-      ? 'text-green-600'
-      : 'text-red-600'}"
+class="mt-2 text-sm {retryStatus === 'info'
+    ? 'text-blue-600'
+    : retryStatus === 'success'
+      ? 'text-green-600'
+      : 'text-red-600'}"

And set retryStatus appropriately in handleVersionTap.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e27f40b and f945c2f.

📒 Files selected for processing (2)
  • infrastructure/eid-wallet/src/lib/ui/Drawer/Drawer.svelte (1 hunks)
  • infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • infrastructure/eid-wallet/src/lib/ui/Drawer/Drawer.svelte
⏰ 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: lint
  • GitHub Check: build
🔇 Additional comments (2)
infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte (2)

39-44: LGTM: Proper async state reset and navigation.

The function correctly awaits the state reset, updates both the context and local state reference, then navigates to the onboarding page. The flow is clean and follows proper async patterns.


98-100: The review comment is incorrect.

Your search revealed that runtime.header.title is referenced only within the settings folder—specifically in the settings pages (which set it) and the settings layout (which reads it). Other app routes like scan-qr and ePassport pass hardcoded title values directly to AppNav, they do not read from runtime.header.title.

When navigating away from settings, the router switches layout contexts, and those pages use their own title management—there is no persistence issue. Cleanup is unnecessary.

Likely an incorrect or invalid review comment.

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

Caution

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

⚠️ Outside diff range comments (1)
platforms/blabsy/src/components/modal/mobile-sidebar-modal.tsx (1)

86-114: Remove unused Display modal setup.

Since the Display button is commented out (lines 245-256), the display modal setup and rendering are now dead code. Remove the unused useModal hook and the DisplayModal component to avoid rendering unnecessary components and improve maintainability.

Apply this diff:

-    const {
-        open: displayOpen,
-        openModal: displayOpenModal,
-        closeModal: displayCloseModal
-    } = useModal();
-
     const {
         open: logOutOpen,
         openModal: logOutOpenModal,
         closeModal: logOutCloseModal
     } = useModal();
 
     const allStats: Readonly<Stats[]> = [
         ['following', 'Following', following.length],
         ['followers', 'Followers', followers.length]
     ];
 
     const userLink = username ? `/user/${username}` : null;
 
     return (
         <>
-            <Modal
-                className='items-center justify-center xs:flex'
-                modalClassName='max-w-xl bg-main-background w-full p-8 rounded-2xl hover-animation'
-                open={displayOpen}
-                closeModal={displayCloseModal}
-            >
-                <DisplayModal closeModal={displayCloseModal} />
-            </Modal>
             <Modal
🧹 Nitpick comments (1)
platforms/blabsy/src/components/modal/mobile-sidebar-modal.tsx (1)

245-256: Consider fully removing instead of commenting out.

If the Display feature is being permanently removed, delete the commented code rather than leaving it in place. If it's temporarily disabled, add a TODO or FIXME comment explaining why and when it should be re-enabled.

Apply this diff if permanently removing:

-                        {/* <Button
-                            className='accent-tab accent-bg-tab flex items-center gap-2 rounded-md p-1.5 font-bold transition
-                         hover:bg-light-primary/10 focus-visible:ring-2 first:focus-visible:ring-[#878a8c]
-                         dark:hover:bg-dark-primary/10 dark:focus-visible:ring-white'
-                            onClick={displayOpenModal}
-                        >
-                            <HeroIcon
-                                className='h-5 w-5'
-                                iconName='PaintBrushIcon'
-                            />
-                            Display
-                        </Button> */}
                         <Button

Or add a comment if temporarily disabled:

+                        {/* TODO: Re-enable Display feature after [reason] */}
                         {/* <Button
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d7fd3ac and 568f74d.

📒 Files selected for processing (1)
  • platforms/blabsy/src/components/modal/mobile-sidebar-modal.tsx (2 hunks)
⏰ 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). (1)
  • GitHub Check: build

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 (1)
infrastructure/eid-wallet/src/lib/ui/Drawer/Drawer.svelte (1)

44-49: Honor dismissible flag for backdrop-tap close and align close semantics

Right now the drawer closes on backdrop tap even when dismissible === false, which is inconsistent with how dismissible already controls bottomClose and showDraggable. It also uses bare destroy() while the state effect uses destroy({ animate: true }).

Consider guarding the handler with dismissible and aligning the destroy call:

-        events: {
-            onBackdropTap: () => {
-                pane?.destroy();
-                isPaneOpen = false;
-            },
-        },
+        events: {
+            onBackdropTap: () => {
+                if (!dismissible) return;
+                pane?.destroy({ animate: true });
+                isPaneOpen = false;
+            },
+        },

This keeps non-dismissible drawers truly non-dismissible via backdrop and makes the close path visually consistent with the other destroy({ animate: true }) usage.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e22980 and 02d7e65.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/lib/ui/Drawer/Drawer.svelte (1 hunks)
⏰ 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: build
  • GitHub Check: lint

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

Caution

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

⚠️ Outside diff range comments (1)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (1)

235-264: Add error handling to prevent stuck loading state.

Unlike handleNext and handleContinue, handleFinalSubmit has no error handling. If any operation fails (user data assignment, vault setup, or navigation), loading remains true indefinitely and the user receives no feedback. This leaves the app in an inconsistent state with no recovery path.

Apply this diff to add comprehensive error handling:

 handleFinalSubmit = async () => {
     loading = true;
+    error = null;
 
-    const tenYearsLater = new Date();
-    tenYearsLater.setFullYear(tenYearsLater.getFullYear() + 10);
-    globalState.userController.user = {
-        name:
-            demoName ||
-            capitalize(`${falso.randFirstName()} ${falso.randLastName()}`),
-        "Date of Birth": new Date().toDateString(),
-        "ID submitted": `Passport - ${falso.randCountryCode()}`,
-        "Passport Number": generatePassportNumber(),
-    };
-    globalState.userController.isFake = true;
-    globalState.userController.document = {
-        "Valid From": new Date(Date.now()).toDateString(),
-        "Valid Until": tenYearsLater.toDateString(),
-        "Verified On": new Date().toDateString(),
-    };
-
-    // Set vault in controller - this will trigger profile creation with retry logic
-    globalState.vaultController.vault = {
-        uri,
-        ename,
-    };
-
-    setTimeout(() => {
-        goto("/register");
-    }, 10_000);
+    try {
+        const tenYearsLater = new Date();
+        tenYearsLater.setFullYear(tenYearsLater.getFullYear() + 10);
+        globalState.userController.user = {
+            name:
+                demoName ||
+                capitalize(`${falso.randFirstName()} ${falso.randLastName()}`),
+            "Date of Birth": new Date().toDateString(),
+            "ID submitted": `Passport - ${falso.randCountryCode()}`,
+            "Passport Number": generatePassportNumber(),
+        };
+        globalState.userController.isFake = true;
+        globalState.userController.document = {
+            "Valid From": new Date(Date.now()).toDateString(),
+            "Valid Until": tenYearsLater.toDateString(),
+            "Verified On": new Date().toDateString(),
+        };
+
+        // Set vault in controller - this will trigger profile creation with retry logic
+        globalState.vaultController.vault = {
+            uri,
+            ename,
+        };
+
+        setTimeout(() => {
+            goto("/register");
+        }, 10_000);
+    } catch (err) {
+        console.error("Final submission failed:", err);
+        error = "Failed to complete registration. Please try again.";
+        setTimeout(() => {
+            error = null;
+        }, 6000);
+    } finally {
+        loading = false;
+    }
 };
🧹 Nitpick comments (1)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (1)

43-53: Consider using a constant test key ID to prevent keystore slot accumulation.

Each call to handleGetStarted generates a new timestamp-based key ID, which accumulates keys in the hardware keystore without cleanup. Since the KeyManager API doesn't provide a delete method, consider using a constant ID like "hardware-capability-test" instead of hardware-test-${Date.now()}. This way, repeated capability checks will overwrite the same slot rather than exhausting available hardware keystore slots over time.

Apply this diff to use a constant test key ID:

-    const testKeyId = `hardware-test-${Date.now()}`;
+    const testKeyId = "hardware-capability-test";
     console.log(
         "Testing hardware key generation with test key:",
         testKeyId,
     );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1960362 and 92c6042.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-14T17:54:47.719Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 437
File: infrastructure/eid-wallet/src/lib/global/controllers/security.ts:138-157
Timestamp: 2025-11-14T17:54:47.719Z
Learning: The `setOnboardingPin` method in `infrastructure/eid-wallet/src/lib/global/controllers/security.ts` is intentionally designed to allow overwriting existing PINs without checking if a PIN already exists. This is a workaround for Android keeping stale files around during app reinstallation or onboarding, which causes errors on some devices. Do not suggest adding guards to prevent PIN overwrites in this method.

Applied to files:

  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
⏰ 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: lint
  • GitHub Check: build
🔇 Additional comments (4)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (4)

192-231: Excellent error handling implementation!

The try/catch/finally structure properly handles all failure scenarios in the pre-verification flow. The finally block ensures loading is always reset, error messages are user-friendly, and state is properly cleaned up (resetting preVerified and verificationId) on failure. This addresses the previous review feedback effectively.


355-360: Button disabled states correctly implement the requirement.

The dynamic disabled and variant properties based on input length successfully address issue #445. Both the verification code button (lines 374-379) and demo name button (lines 355-360) are disabled when their respective fields are empty, providing clear visual feedback to users.

Also applies to: 374-379


391-413: Excellent fallback UX for hardware limitations.

The hardware error branch provides a clear explanation and smooth transition to the pre-verification path. Setting isPaneOpen = false before calling handlePreVerified() creates a seamless mode switch, improving the user experience when hardware keys aren't available.


326-326: Drawer backdrop-click-to-close is properly implemented.

The Drawer component at infrastructure/eid-wallet/src/lib/ui/Drawer/Drawer.svelte correctly implements backdrop click handling via the onBackdropTap event handler (lines 45-48), which destroys the pane and updates isPaneOpen = false. The backdrop is enabled with blur and configured opacity. This properly addresses issue #450 and allows the bind:isPaneOpen binding in this file to respond to backdrop interactions.

@coodos coodos merged commit 208acdc into main Nov 20, 2025
4 checks passed
@coodos coodos deleted the fix/ui-bugs-eidwallet branch November 20, 2025 08:31
@coderabbitai coderabbitai bot mentioned this pull request Nov 20, 2025
6 tasks
@coderabbitai coderabbitai bot mentioned this pull request Dec 9, 2025
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants