Skip to content

Conversation

sosweetham
Copy link
Member

@sosweetham sosweetham commented Aug 12, 2025

Description of change

mobile responsiveness

Issue Number

n/a

Type of change

  • 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
    • Mobile-aware login: mobile users get a “Login with eID Wallet” deep-link button; desktop users continue with QR code.
    • Added expiry note and informational box about eVoting; redirects to home after authentication.
  • Refactor
    • Simplified layout and containers; improved responsive behavior and typography.
    • Streamlined error display and updated copy for clarity.
  • Style
    • Updated branding from WDS to W3DS and added new branding image.

@sosweetham sosweetham requested a review from coodos as a code owner August 12, 2025 08:28
Copy link
Contributor

coderabbitai bot commented Aug 12, 2025

Walkthrough

Converts QR-only login views into device-aware flows. Both pages add mobile detection to choose between rendering a deep-link “Login with eID Wallet” button on mobile or a QR code on desktop. Layouts, headers, and copy are restructured; router navigation is removed in favor of window.location redirects on eVoting.

Changes

Cohort / File(s) Summary
eVoting login page
platforms/eVoting/src/app/(auth)/login/page.tsx
Removes Next.js router usage; adds isMobile detection via isMobileDevice() with useEffect; conditionally renders deep-link button (mobile) or QR (desktop); switches to window.location.href for redirect; refactors layout/typography; updates branding (W3DS), adds expiry note and branding image; adjusts error handling.
Pictique auth page
platforms/pictique/src/routes/(auth)/auth/+page.svelte
Adds isMobile with onMount/onDestroy and resize listener; conditional UI: deep-link button (mobile) vs QR (desktop); keeps QR offer fetch and SSE watching; refines container and text styles; no public API changes.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Page as Auth Page
  participant Device as Device Checker
  participant API as /api/auth/offer
  participant Wallet as eID Wallet

  User->>Page: Open login page
  Page->>Device: Detect isMobile
  Page->>API: Fetch QR/deep-link data
  API-->>Page: qrData (offer URL)

  alt isMobile
    Page-->>User: Show "Login with eID Wallet" button
    User->>Wallet: Open deep link (qrData)
    Wallet-->>Page: Redirect callback (authenticated)
    Page->>User: Navigate to "/"
  else Desktop
    Page-->>User: Render QR code (qrData)
    User->>Wallet: Scan QR with eID Wallet
    Wallet-->>Page: Event stream indicates success
    Page->>User: Navigate to "/"
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Fix/author details #229: Also modifies platforms/pictique/src/routes/(auth)/auth/+page.svelte, adding SSE auth ID storage, intersecting with this PR’s updated mobile/QR flow.

Suggested reviewers

  • coodos
  • JulienAuvo

Poem

I hop between screens, small and wide,
A link for the pocket, a code for the side.
Tap to the Wallet, or scan with a stare—
Either burrow leads you there.
With W3DS sheen and tidy new views,
This bun approves—thump-thump—good news! 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/mobile-responsiveness

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🧹 Nitpick comments (3)
platforms/pictique/src/routes/(auth)/auth/+page.svelte (1)

14-16: Consider using a more robust mobile detection approach.

The current implementation only checks viewport width, which doesn't account for actual device type. This could lead to inconsistent behavior when desktop browsers are resized to mobile widths.

Consider using a more comprehensive mobile detection similar to the eVoting implementation:

 function checkMobile() {
-  isMobile = window.innerWidth <= 640; // Tailwind's `sm` breakpoint
+  isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ||
+             window.innerWidth <= 640;
 }
platforms/eVoting/src/app/(auth)/login/page.tsx (2)

37-40: Improve error handling with specific error message.

The catch block discards the error details, making debugging difficult. Consider preserving the error information.

-} catch {
-  setError("Failed to load QR code");
+} catch (err) {
+  console.error("Failed to fetch QR code:", err);
+  setError(err instanceof Error ? err.message : "Failed to load QR code");
   setIsLoading(false);
 }

58-58: Consider using Next.js router for navigation.

Using window.location.href for navigation causes a full page reload, losing React state and potentially affecting user experience. The original implementation used Next.js router which is more appropriate for a Next.js application.

Consider using Next.js router for client-side navigation:

+"use client";
+import { useRouter } from "next/navigation";
 import { useState, useEffect } from "react";

 export default function LoginPage() {
+  const router = useRouter();
   const { login } = useAuth();
   
   // ... in the eventSource.onmessage handler:
-  window.location.href = "/";
+  router.push("/");
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1362ede and 2b5bf5d.

📒 Files selected for processing (2)
  • platforms/eVoting/src/app/(auth)/login/page.tsx (4 hunks)
  • platforms/pictique/src/routes/(auth)/auth/+page.svelte (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
platforms/eVoting/src/app/(auth)/login/page.tsx (1)
platforms/eVoting/src/lib/utils/mobile-detection.ts (2)
  • isMobileDevice (1-6)
  • getDeepLinkUrl (8-10)
🔇 Additional comments (1)
platforms/pictique/src/routes/(auth)/auth/+page.svelte (1)

65-70: Verify mobile deep link format for eID Wallet login

It looks like we’re using qrData (returned as data.uri) directly in the <a href={qrData}> tag, but there’s no deep-link helper in Pictique (unlike other projects that use a getDeepLinkUrl function). Please confirm that your /api/auth/offer endpoint already returns a correctly formatted deep link (e.g. eidwallet://… or a universal link). If it doesn’t, you’ll need to transform the URI on the client (or add a helper) to ensure mobile wallets open the app as expected.

• File: platforms/pictique/src/routes/(auth)/auth/+page.svelte
• Lines: 65–70 (<a href={qrData}…>Login with eID Wallet</a>)

Comment on lines +17 to +19
useEffect(() => {
setIsMobile(isMobileDevice());
}, []);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding window resize listener for responsive behavior.

Unlike the Pictique implementation, this component doesn't listen for window resize events. Users who rotate their device or resize their browser window won't see the UI update accordingly.

Add a resize event listener to update mobile state dynamically:

 useEffect(() => {
   setIsMobile(isMobileDevice());
+  
+  const handleResize = () => {
+    setIsMobile(isMobileDevice());
+  };
+  
+  window.addEventListener('resize', handleResize);
+  return () => window.removeEventListener('resize', handleResize);
 }, []);
🤖 Prompt for AI Agents
In platforms/eVoting/src/app/(auth)/login/page.tsx around lines 17 to 19, the
useEffect only sets isMobile once and doesn't respond to window resizes; add a
window resize listener inside the same useEffect that recalculates and calls
setIsMobile(isMobileDevice()) on resize, remove the listener in the effect
cleanup to avoid leaks, and optionally debounce the handler to reduce frequent
state updates.

{isMobile ? (
<div className="flex flex-col gap-4 items-center">
<a
href={getDeepLinkUrl(qrData)}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify getDeepLinkUrl implementation.

The getDeepLinkUrl function currently just returns the input without transformation. This may not provide the correct deep link format for mobile wallets.


🌐 Web query:

What is the standard deep link URL format for opening authentication URIs in mobile wallet applications?

💡 Result:

Short answer: there isn’t one universal URL format — mobile wallets use either (A) an app-specific custom URI scheme or (B) an HTTPS universal link that the wallet claims — and the common pattern is:

  • ://wc?uri=<URL‑ENCODED_AUTH_URI>
    or
  • https:///wc?uri=<URL‑ENCODED_AUTH_URI>

Where the embedded auth/connection URI (e.g. a WalletConnect "wc:..." URI or an OAuth redirect) must be percent-encoded. Wallets (and dapps) commonly use that pattern for WalletConnect-style session/auth requests; iOS prefers claimed HTTPS (universal) links for better UX/security. (alpha-docs.walletconnect.com, reddit.com)

Examples

Best practices

If you tell me which wallet/protocol you’re targeting (MetaMask, WalletConnect v1/v2, Phantom, Rainbow, OAuth, Solana, Ethereum EIP‑681, etc.), I can give an exact example URL formatted for that wallet and note any encoding/redirect parameters required.

Citations:


Implement proper deep-link formatting in getDeepLinkUrl

The helper currently returns the raw qrData URI, but mobile wallets expect a percent-encoded URI wrapped in either a custom scheme or a claimed HTTPS link. Please update getDeepLinkUrl to:

  • Percent-encode the embedded auth URI:
    const encoded = encodeURIComponent(qrData)
  • Prefix with the wallet’s scheme or universal link:
    • Custom scheme (e.g. MetaMask/WalletConnect):
    metamask://wc?uri=${encoded}
    • HTTPS universal link (recommended on iOS/Android):
    https://example.wallet/wc?uri=${encoded}
  • Match the exact path and query param names from your target wallet’s docs (MetaMask, WalletConnect v2, Phantom, etc.)

Action items:

  • In platforms/eVoting/src/app/(auth)/login/page.tsx (or wherever getDeepLinkUrl is defined), replace the stub with logic that builds and returns a properly formatted deep link.
  • If you need to support multiple wallets, consider adding a wallet parameter or separate helpers for each format.
  • Add or update unit tests to verify the output URL for your chosen wallet protocols.
🤖 Prompt for AI Agents
In platforms/eVoting/src/app/(auth)/login/page.tsx around line 115, replace the
current stub that returns raw qrData with a helper that percent-encodes the
embedded auth URI (const encoded = encodeURIComponent(qrData)) and then prefixes
it with the chosen wallet deep-link format (e.g. for MetaMask/WalletConnect use
metamask://wc?uri=${encoded} or use an HTTPS universal link like
https://example.wallet/wc?uri=${encoded}); ensure the path and query parameter
names exactly match the target wallet docs, add an optional wallet parameter or
separate helpers if you must support multiple wallets, and add/update unit tests
to assert the expected deep-link outputs for each supported wallet format.

Comment on lines +45 to +47
onDestroy(() => {
window.removeEventListener('resize', checkMobile);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Incorrect placement of onDestroy call.

The onDestroy call is nested inside onMount, which is incorrect. Svelte lifecycle hooks should be called at the top level of the component.

Move the onDestroy call outside of onMount:

 watchEventStream(new URL(qrData).searchParams.get('session') as string);
-
- onDestroy(() => {
-   window.removeEventListener('resize', checkMobile);
- });
 });
+
+onDestroy(() => {
+  window.removeEventListener('resize', checkMobile);
+});
</script>
🤖 Prompt for AI Agents
In platforms/pictique/src/routes/(auth)/auth/+page.svelte around lines 45 to 47,
the onDestroy call is incorrectly nested inside onMount; move the onDestroy(()
=> window.removeEventListener('resize', checkMobile')) call out of the onMount
block so Svelte lifecycle hooks are invoked at the component top level, keeping
the addEventListener in onMount and the corresponding removeEventListener in a
sibling onDestroy to ensure proper cleanup.

@coodos coodos merged commit 8b571ab into main Aug 13, 2025
2 of 4 checks passed
@coodos coodos deleted the feat/mobile-responsiveness branch August 13, 2025 09:06
@coderabbitai coderabbitai bot mentioned this pull request Sep 11, 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
Development

Successfully merging this pull request may close these issues.

2 participants