Skip to content

Fixed the Onboarding Page Setup#485

Merged
rahulharpal1603 merged 2 commits intoAOSSIE-Org:mainfrom
ssz2605:onboarding-layout
Aug 30, 2025
Merged

Fixed the Onboarding Page Setup#485
rahulharpal1603 merged 2 commits intoAOSSIE-Org:mainfrom
ssz2605:onboarding-layout

Conversation

@ssz2605
Copy link
Contributor

@ssz2605 ssz2605 commented Aug 17, 2025

Implemented Complete Onboarding Flow: Avatar, Name, Folder, and Theme Steps

This PR implements the full onboarding flow for PictoPy, including AvatarandNameSelection, FolderSetupStep, and ThemeSelection, fully aligned with Redux state management.

Key Changes

  1. Avatar & Name Selection

    • Combined AvatarSelection and NameSelection into a single component for simplicity.
    • Managed state using Redux, removing reliance on local state.
  2. Theme Selection

    • Implemented theme selection logic.
    • State is managed via Redux and synced with local storage for persistence.
  3. Folder Setup Step

    • Updated SetUpScreen inside FolderSetupStep to use Redux for state management, keeping consistency across onboarding steps.
  4. Onboarding Steps Integration

    • Imported and rendered the new steps (AvatarSelection and ThemeSelection) alongside existing steps like FolderSetupStep.
    • Updated the STEPS array in Steps.tsx to include the new steps, maintaining correct flow order.
  5. Onboarding Slice Updates

    • Extended OnboardingState and reducers in onboardingSlice to handle avatar and name.

closes #473

Summary by CodeRabbit

  • New Features
    • Added Avatar Selection and Theme Selection onboarding steps with progress indicators, Back/Next navigation, name input, and avatar picker with validation.
    • Theme options: Light, Dark, and System; preference is persisted and applied app-wide.
    • Folder selection step updated with clearer controls and two-panel layout.
    • Introduced rotating feature preview showcasing app highlights.
  • Refactor
    • Unified onboarding flow into a consistent two-card layout.
  • Chores
    • Added UI dependencies for label and radio controls.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 17, 2025

Walkthrough

Adds three new onboarding steps (avatar, folder, theme), new UI primitives (Label, RadioGroup) using Radix, extends onboarding Redux slice with avatar/name/theme/folders, updates step constants, centralizes step rendering, and adds Radix deps; Update-step behavior/code largely unchanged but is no longer ordered first.

Changes

Cohort / File(s) Summary
Dependencies
frontend/package.json
Adds @radix-ui/react-label and @radix-ui/react-radio-group.
New Onboarding Steps
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx, frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx, frontend/src/components/OnboardingSteps/appFeatures.tsx
Adds AvatarSelectionStep and ThemeSelectionStep components and AppFeatures carousel component; both read/write onboarding state via Redux and render two-panel UI (left step card, right AppFeatures).
Folder Setup refactor
frontend/src/components/OnboardingSteps/FolderSetupStep.tsx
Refactors FolderSetupStep to use Redux (folders state, add/removeFolder), converts to exported function, adds totalSteps prop and two-panel layout.
Onboarding orchestration
frontend/src/components/OnboardingSteps/OnboardingStep.tsx
Introduces VISIBLE_STEPS array, passes shared navigation props (onNext/onBack/totalSteps) to step components, and centralizes rendering via a switch.
Update step minor edits
frontend/src/components/OnboardingSteps/UpdateStep.tsx
Minor signature/dispatch/useEffect stylistic changes; logic/gating unchanged.
UI primitives
frontend/src/components/ui/label.tsx, frontend/src/components/ui/radio-group.tsx
Adds Label, RadioGroup, and RadioGroupItem components built on Radix primitives with tailwind-style classes and data-slot attributes.
State & constants
frontend/src/features/onboardingSlice.ts, frontend/src/constants/steps.ts
Extends onboardingSlice with avatar, name, theme, folders and related reducers/actions; updates exported STEPS to include avatarSelection and themeSelection and moves updates to the end.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant OnboardingStep
  participant StepComponent
  participant Redux as "Redux Store"

  rect rgba(230,245,255,0.6)
  note over OnboardingStep,StepComponent: New ordered flow (Avatar -> Folder -> Theme)
  User->>OnboardingStep: Open onboarding
  OnboardingStep->>StepComponent: Render current step (by name)
  StepComponent->>Redux: Read state (name, avatar, folders, theme)
  User->>StepComponent: Interact (select/input)
  StepComponent->>Redux: Dispatch setAvatar/setName/addFolder/removeFolder/setTheme
  User->>StepComponent: Click Next
  StepComponent->>Redux: Dispatch markCompleted(stepIndex)
  Redux-->>OnboardingStep: State update
  OnboardingStep->>StepComponent: Render next step
  end
Loading
sequenceDiagram
  autonumber
  actor User
  participant OnboardingStep
  participant UpdateStep
  participant Redux as "Redux Store"

  rect rgba(255,240,230,0.6)
  note over OnboardingStep,UpdateStep: Expected: update check before other steps (per issue)
  User->>OnboardingStep: Open onboarding
  OnboardingStep-->>UpdateStep: (not included in VISIBLE_STEPS by default)
  Note right of OnboardingStep: Current implementation renders Avatar first
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Assessment against linked issues

Objective Addressed Explanation
Implement new onboarding page with steps similar to prototype (#473)
Use standard ShadCN components; dark mode styling consistent (#473)
Keep update check before all onboarding steps; do not alter update flow (#473) Update step is not included as the first VISIBLE_STEP; onboarding now starts with avatar.
Use provided icons/assets from referenced repo (#473) Avatars referenced as /avatars/avatarN.png; repository asset usage not verifiable in diff.

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Omission of update check from initial onboarding order — VISIBLE_STEPS in frontend/src/components/OnboardingSteps/OnboardingStep.tsx The linked issue requires update check before onboarding steps; moving updates out of the initial visible sequence changes that ordering.
Reordering/removal of UPDATE_STEP from primary position — frontend/src/constants/steps.ts STEPS now places updates last, which diverges from the issue requirement that update-check occurs before other onboarding steps.

Possibly related PRs

Suggested labels

GSoC 2025

Poem

Thump-thump! I hop through steps so bright,
Pick an avatar, set theme by night.
Folders lined up in a tidy row,
Redux carrots help me grow.
Radix radios, labels neat — onboarding’s now a carrot treat! 🥕✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@rahulharpal1603 rahulharpal1603 left a comment

Choose a reason for hiding this comment

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

Could you remove the comments written in all 60 files, and only keep those comments that explain why something is there, not what that part of the code is doing? Sixty file changes are not needed to solve this issue.

@rahulharpal1603 rahulharpal1603 marked this pull request as ready for review August 20, 2025 09:55
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: 22

Caution

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

⚠️ Outside diff range comments (24)
frontend/src/components/ui/Slider.tsx (1)

13-22: Bug: renders two thumbs by default for single-value sliders

When neither value nor defaultValue is provided, _values becomes [min, max], causing two thumbs to render (range behavior). This diverges from Radix/ShadCN defaults and likely breaks uncontrolled single-value sliders.

Apply this fix to derive the thumb count instead of synthesizing values, and default to a single thumb:

-  // Determine slider values (support both single and range sliders)
-  const _values = React.useMemo(
-    () =>
-      Array.isArray(value)
-        ? value
-        : Array.isArray(defaultValue)
-          ? defaultValue
-          : [min, max],
-    [value, defaultValue, min, max],
-  );
+  // Determine number of thumbs (support both single and range sliders)
+  const thumbCount = React.useMemo(
+    () =>
+      Array.isArray(value)
+        ? value.length
+        : Array.isArray(defaultValue)
+          ? defaultValue.length
+          : 1,
+    [value, defaultValue],
+  );
@@
-      {/* Thumb(s): draggable handle(s) */}
-      {Array.from({ length: _values.length }, (_, index) => (
+      {/* Thumb(s): draggable handle(s) */}
+      {Array.from({ length: thumbCount }, (_, index) => (
         <SliderPrimitive.Thumb
           data-slot="slider-thumb"
           key={index}
-          className="border-primary bg-background ring-ring/50 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
+          className="border-primary bg-background ring-ring/50 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50"
         />
       ))}

Note: focus-visible:outline-hidden is not a valid utility; replaced with outline-none.

Also applies to: 53-60

backend/app/database/faces.py (2)

12-23: faces table lacks uniqueness on image_id; current upsert intent will not work

INSERT OR REPLACE only triggers on PRIMARY KEY/UNIQUE conflicts. Since image_id is not unique, you’ll accumulate duplicate rows per image. Add a unique index to enforce one row per image_id.

     cursor.execute(
         """
         CREATE TABLE IF NOT EXISTS faces (
             id INTEGER PRIMARY KEY AUTOINCREMENT,
             image_id INTEGER,
             embeddings TEXT,
             FOREIGN KEY (image_id) REFERENCES image_id_mapping(id) ON DELETE CASCADE
         )
     """
     )
+    # Ensure one row per image_id to support upserts
+    cursor.execute(
+        "CREATE UNIQUE INDEX IF NOT EXISTS idx_faces_image_id ON faces(image_id)"
+    )

Optional: enable foreign keys explicitly to ensure ON DELETE CASCADE works on SQLite connections.

-    conn = sqlite3.connect(DATABASE_PATH)
+    conn = sqlite3.connect(DATABASE_PATH)
+    conn.execute("PRAGMA foreign_keys = ON")

43-51: Fix upsert: use ON CONFLICT(image_id) DO UPDATE to truly update existing rows

With the unique index in place, switch to a proper upsert so embeddings are updated instead of creating new rows.

-    cursor.execute(
-        """
-        INSERT OR REPLACE INTO faces (image_id, embeddings)
-        VALUES (?, ?)
-    """,
-        (image_id, embeddings_json),
-    )
+    cursor.execute(
+        """
+        INSERT INTO faces (image_id, embeddings)
+        VALUES (?, ?)
+        ON CONFLICT(image_id) DO UPDATE SET
+          embeddings=excluded.embeddings
+        """,
+        (image_id, embeddings_json),
+    )
frontend/src/components/Updater/UpdateDialog.tsx (1)

155-157: Retry button is disabled when error is present — users cannot retry.

disabled={isDownloading || !!error} prevents clicking “Retry” exactly when error is shown. Allow retry while not downloading.

Apply:

-            disabled={isDownloading || !!error}
+            disabled={isDownloading}
frontend/src/contexts/ThemeContext.tsx (1)

30-58: Unify theme persistence across ThemeContext and onboarding slice

The ThemeContext uses storageKey = 'vite-ui-theme' while the onboarding slice and ThemeSelectionStep read/write 'theme' directly. This leads to two separate sources of truth and duplicate persistence logic. Please consolidate:

• Export a single THEME_STORAGE_KEY constant and use it everywhere instead of hard-coding.
• Update frontend/src/features/onboardingSlice.ts (currently at line 22) to use that key.
• In ThemeSelectionStep.tsx, replace localStorage.getItem('theme') / .setItem('theme', …) with the shared key or invoke ThemeContext.setTheme.
• Ensure onboarding dispatches to the same ThemeContext (or vice versa) so setting the theme updates both the Redux slice and the DOM-class effect in one flow.

This will guarantee a single source of truth for theme state and avoid drift between contexts.

backend/app/routes/test.py (3)

27-31: Use get_running_loop() instead of get_event_loop() inside async context.

asyncio.get_event_loop() is discouraged in asyncio coroutines and may behave unexpectedly in newer Python versions. Use asyncio.get_running_loop() to reliably access the current loop.

-async def run_get_classes(img_path):
-    loop = asyncio.get_event_loop()
-    await loop.run_in_executor(None, get_classes, img_path)
+async def run_get_classes(img_path):
+    loop = asyncio.get_running_loop()
+    await loop.run_in_executor(None, get_classes, img_path)

46-56: 400 errors are being converted to 500 due to broad exception handling.

Raising HTTPException(status_code=400, ...) inside the try block is immediately caught by the broad except Exception and returned as 500, masking client errors. Re-raise HTTPException separately.

     if img is None:
         # Image path is invalid or unreadable
         raise HTTPException(
             status_code=status.HTTP_400_BAD_REQUEST,
             detail=ErrorResponse(
                 success=False,
                 message=f"Failed to load image: {img_path}",
                 error="Failed to load image",
             ).model_dump(),
         )
@@
-    except Exception as e:
-        raise HTTPException(
-            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
-            detail=ErrorResponse(
-                success=False, error="Internal server error", message=str(e)
-            ).model_dump(),
-        )
+    except HTTPException:
+        # Preserve intended HTTP errors (e.g., 400)
+        raise
+    except Exception as e:
+        # Unexpected server error
+        raise HTTPException(
+            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+            detail=ErrorResponse(
+                success=False, error="Internal server error", message=str(e)
+            ).model_dump(),
+        )

Also applies to: 69-75


121-131: Do not swallow 400 errors; ensure destination dir exists and handle collisions.

  • Same HTTPException masking issue as above.
  • Ensure IMAGES_PATH exists.
  • Consider guarding against overwriting existing files.
 def add_single_image(payload: AddSingleImageRequest):
     try:
         image_path = payload.path
 
         # Check if path exists and is a file
         if not os.path.isfile(image_path):
             raise HTTPException(
                 status_code=status.HTTP_400_BAD_REQUEST,
                 detail=ErrorResponse(
                     success=False,
                     error="Invalid file path",
                     message="The provided path is not a valid file",
                 ).model_dump(),
             )
 
         image_extensions = [".jpg", ".jpeg", ".png", ".bmp", ".gif"]
         file_extension = os.path.splitext(image_path)[1].lower()
 
         if file_extension not in image_extensions:
             raise HTTPException(
                 status_code=status.HTTP_400_BAD_REQUEST,
                 detail=ErrorResponse(
                     success=False,
                     error="Invalid file type",
                     message="The file is not a supported image type",
                 ),
             )
 
         # Copy image to gallery folder
-        destination_path = os.path.join(IMAGES_PATH, os.path.basename(image_path))
-        shutil.copy(image_path, destination_path)
+        os.makedirs(IMAGES_PATH, exist_ok=True)
+        filename = os.path.basename(image_path)
+        destination_path = os.path.join(IMAGES_PATH, filename)
+        if os.path.exists(destination_path):
+            raise HTTPException(
+                status_code=status.HTTP_400_BAD_REQUEST,
+                detail=ErrorResponse(
+                    success=False,
+                    error="File already exists",
+                    message=f"'{filename}' already exists in the gallery",
+                ).model_dump(),
+            )
+        shutil.copy(image_path, destination_path)
 
         return AddSingleImageResponse(
             success=True,
             message="Image copied to the gallery successfully",
             data={"destination_path": destination_path},
         )
-
-    except Exception as e:
-        raise HTTPException(
-            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
-            detail=ErrorResponse(
-                success=False, message="Internal server error", error=str(e)
-            ).model_dump(),
-        )
+    except HTTPException:
+        raise
+    except Exception as e:
+        raise HTTPException(
+            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+            detail=ErrorResponse(
+                success=False, message="Internal server error", error=str(e)
+            ).model_dump(),
+        )

Also applies to: 135-143, 145-153, 155-161

frontend/src/components/ui/scroll-area.tsx (1)

30-57: Incorrect Radix component identifiers (will not render).

Use ScrollAreaPrimitive.Scrollbar and ScrollAreaPrimitive.Thumb at runtime. The current ScrollAreaPrimitive.ScrollAreaScrollbar and ScrollAreaPrimitive.ScrollAreaThumb names are type-only in some examples and are not valid component identifiers.

Apply this fix:

-function ScrollBar({
+function ScrollBar({
   className,
   orientation = 'vertical',
   ...props
-}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
+}: React.ComponentProps<typeof ScrollAreaPrimitive.Scrollbar>) {
   return (
-    <ScrollAreaPrimitive.ScrollAreaScrollbar
+    <ScrollAreaPrimitive.Scrollbar
       data-slot="scroll-area-scrollbar"
       orientation={orientation}
       className={cn(
         'flex touch-none p-px transition-colors select-none',
         orientation === 'vertical' &&
           'h-full w-2.5 border-l border-l-transparent',
         orientation === 'horizontal' &&
           'h-2.5 flex-col border-t border-t-transparent',
         className,
       )}
       {...props}
     >
       {/* The draggable thumb inside scrollbar */}
-      <ScrollAreaPrimitive.ScrollAreaThumb
+      <ScrollAreaPrimitive.Thumb
         data-slot="scroll-area-thumb"
         className="bg-border relative flex-1 rounded-full"
       />
-    </ScrollAreaPrimitive.ScrollAreaScrollbar>
+    </ScrollAreaPrimitive.Scrollbar>
   );
 }
backend/app/database/folders.py (1)

99-106: Unclosed connection in get_all_folder_ids

get_all_folder_ids opens a connection but never closes it. Use a context manager or close explicitly.

Apply this diff:

-def get_all_folder_ids():
-    # Return list of all folder IDs
-    conn = sqlite3.connect(DATABASE_PATH)
-    cursor = conn.cursor()
-    cursor.execute("SELECT folder_id from folders")
-    rows = cursor.fetchall()
-    return [row[0] for row in rows] if rows else []
+def get_all_folder_ids():
+    # Return list of all folder IDs
+    with sqlite3.connect(DATABASE_PATH) as conn:
+        rows = conn.execute("SELECT folder_id FROM folders").fetchall()
+        return [row[0] for row in rows] if rows else []
frontend/src/components/ui/dropdown-menu.tsx (3)

64-86: Add ref forwarding and real styles; implement variant/inset support

Current wrapper doesn’t forward refs and uses placeholder classes. Also, the destructive variant is surfaced via data-variant but not styled.

Apply this diff:

-function DropdownMenuItem({
-  className,
-  inset,
-  variant = 'default',
-  ...props
-}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
-  inset?: boolean;
-  variant?: 'default' | 'destructive';
-}) {
-  return (
-    <DropdownMenuPrimitive.Item
-      data-slot="dropdown-menu-item"
-      data-inset={inset}
-      data-variant={variant}
-      className={cn(
-        'focus:bg-accent ...', // active, disabled, inset, icon styles
-        className,
-      )}
-      {...props}
-    />
-  );
-}
+const DropdownMenuItem = React.forwardRef<
+  React.ElementRef<typeof DropdownMenuPrimitive.Item>,
+  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
+    inset?: boolean;
+    variant?: 'default' | 'destructive';
+  }
+>(({ className, inset, variant = 'default', ...props }, ref) => (
+  <DropdownMenuPrimitive.Item
+    ref={ref}
+    data-slot="dropdown-menu-item"
+    data-inset={inset}
+    data-variant={variant}
+    className={cn(
+      'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none ' +
+        'focus:bg-accent focus:text-accent-foreground ' +
+        'data-[disabled]:pointer-events-none data-[disabled]:opacity-50 ' +
+        'data-[inset]:pl-8 ' +
+        'data-[variant=destructive]:text-destructive',
+      className,
+    )}
+    {...props}
+  />
+));
+DropdownMenuItem.displayName = 'DropdownMenuItem';

131-145: Fix radio item styling ("...") and padding for left indicator

Same issue as checkbox: ensure adequate padding and remove placeholder class.

-    <DropdownMenuPrimitive.RadioItem
+    <DropdownMenuPrimitive.RadioItem
       data-slot="dropdown-menu-radio-item"
-      className={cn('focus:bg-accent ...', className)}
+      className={cn(
+        'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none ' +
+          'focus:bg-accent focus:text-accent-foreground ' +
+          'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
+        className,
+      )}

207-226: SubTrigger styling still contains placeholder; add open-state and inset styles

Provide real classes and support for open state visuals.

-    <DropdownMenuPrimitive.SubTrigger
+    <DropdownMenuPrimitive.SubTrigger
       data-slot="dropdown-menu-sub-trigger"
       data-inset={inset}
-      className={cn('focus:bg-accent data-[inset]:pl-8 ...', className)}
+      className={cn(
+        'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none ' +
+          'focus:bg-accent data-[state=open]:bg-accent ' +
+          'data-[inset]:pl-8',
+        className,
+      )}
frontend/src/App.tsx (1)

3-3: Incorrect import: BrowserRouter must come from react-router-dom

Importing BrowserRouter from 'react-router' will fail. It’s provided by 'react-router-dom'.

Apply this diff:

-import { BrowserRouter } from 'react-router';
+import { BrowserRouter } from 'react-router-dom';
frontend/src/components/FolderPicker/DeleteSelectedImagePage.tsx (1)

70-91: Confirm handler re-opens the dialog; close it on confirm to avoid a stuck modal.

handleAddSelectedImages sets openDialog(true) even though it is the confirm handler. This can keep the dialog open unexpectedly and conflicts with user expectations.

Apply this diff to stop reopening and to close on success:

-  // Final delete function after dialog confirm
+  // Final delete function after dialog confirm
   const handleAddSelectedImages = async (isFromDevice: boolean) => {
-    setOpenDialog(true);
+    // Dialog is already open; do not reopen here
     console.log('Selected Images = ', selectedImages);
     if (isFromDevice) {
       console.log('Yes , Want to delete from this Device too');
     } else {
       console.log('Only want to delete from this Application');
     }
     if (selectedImages.length > 0) {
       try {
         await deleteMultipleImages({ paths: selectedImages, isFromDevice });
         console.log('Selected Images : ', selectedImages);
+        setOpenDialog(false);
         setSelectedImages([]);
         if (!isLoading) {
           setIsVisibleSelectedImage(true);
         }
       } catch (err) {
         onError('Error during deleting images', err);
       }
     }
   };
frontend/src/components/Album/AlbumForm.tsx (1)

42-57: Avoid duplicate form reset/close; rely on onSuccess or awaited result

With mutateAsync, await the call and let onSuccess handle cleanup. Remove the immediate resets/close to prevent double side-effects.

   const handleCreateAlbum = async () => {
     if (newAlbumName.trim()) {
       try {
-        createAlbum({
+        await createAlbum({
           name: newAlbumName.trim(),
           description: newAlbumDescription.trim(),
           is_hidden: isHidden,
           password: isHidden ? password : '', // Only send password if hidden
         });
-        // Reset form
-        setNewAlbumName('');
-        setNewAlbumDescription('');
-        setPassword('');
-        setIsHidden(false);
-        closeForm();
       } catch (err) {
         onError('Error Creating Album', err);
       }
     } else {
       onError('Invalid Album Name', new Error('Album name cannot be empty')); // Validation check
     }
   };
frontend/src/components/Album/Album.tsx (3)

99-105: Security concern: Password validation should be done server-side

Using prompt() for password input and comparing passwords client-side exposes the password in JavaScript. This is insecure as the password can be intercepted or viewed in browser dev tools.

The password validation should be performed server-side. Consider:

  1. Send the password to the backend for validation
  2. Backend returns an access token or session
  3. Use that token for subsequent requests to view the album
-    if (album?.is_hidden) {
-      const password = prompt('Enter the password for this hidden album:');
-      if (password === album.password) {
-        setCurrentAlbum(albumId);
-      } else {
-        alert('Incorrect password.');
-      }
+    if (album?.is_hidden) {
+      const password = prompt('Enter the password for this hidden album:');
+      // Call backend to verify password
+      try {
+        const response = await verifyAlbumAccess({ 
+          album_name: albumId, 
+          password 
+        });
+        if (response.success) {
+          setCurrentAlbum(albumId);
+        } else {
+          alert('Incorrect password.');
+        }
+      } catch (err) {
+        showErrorDialog('Authentication Failed', err);
+      }

100-100: Replace browser alerts with proper UI components

Using prompt() and alert() provides poor UX and looks unprofessional. Consider using proper dialog components that match your UI design.

Consider creating a password dialog component:

// PasswordDialog.tsx
interface PasswordDialogProps {
  isOpen: boolean;
  albumName: string;
  onSubmit: (password: string) => void;
  onCancel: () => void;
}

// Then use it:
{passwordDialogAlbum && (
  <PasswordDialog
    isOpen={!!passwordDialogAlbum}
    albumName={passwordDialogAlbum}
    onSubmit={handlePasswordSubmit}
    onCancel={() => setPasswordDialogAlbum(null)}
  />
)}

Also applies to: 104-104


112-118: Fix async/await usage in handleDeleteAlbum

The function is declared as async but uses await on a mutation function that doesn't return a promise in the expected way. The deleteAlbum mutation function from usePictoMutation should be called without await.

-  const handleDeleteAlbum = async (albumId: string) => {
-    try {
-      await deleteAlbum({ name: albumId });
-    } catch (err) {
-      showErrorDialog('Error Deleting Album', err);
-    }
+  const handleDeleteAlbum = (albumId: string) => {
+    deleteAlbum(
+      { name: albumId },
+      {
+        onError: (err) => {
+          showErrorDialog('Error Deleting Album', err);
+        }
+      }
+    );
frontend/src/components/Album/ImageManagementDialog.tsx (1)

49-58: Fix async/await usage with mutation

Similar to the issue in Album.tsx, the mutation is being awaited incorrectly. The mutate function from usePictoMutation doesn't return a promise by default.

-  const handleRemoveImage = async (imageUrl: string) => {
+  const handleRemoveImage = (imageUrl: string) => {
     if (albumName) {
-      try {
-        await removeImage({ album_name: albumName, path: imageUrl });
-        onSuccess();
-      } catch (err) {
-        onError('Error Removing Image', err);
-      }
+      removeImage(
+        { album_name: albumName, path: imageUrl },
+        {
+          onSuccess: () => onSuccess(),
+          onError: (err) => onError('Error Removing Image', err)
+        }
+      );
     }
   };
frontend/src/components/Media/MediaGallery.tsx (2)

166-181: MediaView receives a stale itemsPerPage (always 20) instead of the selected page size

You define and use pageNo as the effective page size across the component, but pass the constant itemsPerPage (20) to MediaView. This desynchronizes navigation within the viewer.

-            itemsPerPage={itemsPerPage}
+            itemsPerPage={pageNo}

127-161: Align DropdownMenu import with your UI wrapper

MediaGallery.tsx is importing Radix primitives directly, but the app uses the ShadCN wrapper in src/components/ui/dropdown-menu.tsx. Update the import at the top of the file:

  • File: frontend/src/components/Media/MediaGallery.tsx (around lines 15–19)

Replace:

import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuTrigger,
} from '@radix-ui/react-dropdown-menu';

With:

import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
frontend/src/components/AITagging/AIgallery.tsx (1)

7-8: Rename hook file and update imports to include missing “n”

The hook file is currently named useQueryExtensio.ts (missing the final “n”), so although the import in AIgallery.tsx resolves today, it’s clearly a typo that will confuse future maintainers and could break if the file gets renamed elsewhere.

• Rename:

  • frontend/src/hooks/useQueryExtensio.tsfrontend/src/hooks/useQueryExtension.ts
    • Update imports:
  • In frontend/src/components/AITagging/AIgallery.tsx, change
    - import { usePictoQuery } from '@/hooks/useQueryExtensio';
    + import { usePictoQuery } from '@/hooks/useQueryExtension';
  • Search and update any other references to @/hooks/useQueryExtensio across the codebase.
frontend/src/components/AITagging/FilterControls.tsx (1)

333-359: Using RadioGroup for multi-select is semantically wrong and breaks onValueChange

You’re preventing default selection on radio items to emulate multi-select; this means onValueChange won’t fire reliably, and accessibility is degraded. Use DropdownMenuCheckboxItem for multi-select.

-            <DropdownMenuRadioGroup
-              className="overflow-auto"
-              onValueChange={handleFilterFlag}
-            >
-              {selectedFlags.map((ele, index) => (
-                <DropdownMenuRadioItem
-                  key={ele.tag}
-                  value={ele.tag}
-                  onSelect={(event) => {
-                    selectedFlags[index].isChecked
-                      ? handleRemoveFlag(index)
-                      : handleAddFlag(index);
-                    event.preventDefault();
-                  }}
-                  className="cursor-pointer"
-                >
-                  <input
-                    type="checkbox"
-                    className="mr-2 cursor-pointer"
-                    value={ele.tag}
-                    checked={selectedFlags[index].isChecked}
-                  />
-                  {ele.tag}
-                </DropdownMenuRadioItem>
-              ))}
-            </DropdownMenuRadioGroup>
+            <div className="overflow-auto p-1">
+              {selectedFlags.map((ele, index) => (
+                <DropdownMenuCheckboxItem
+                  key={ele.tag}
+                  checked={ele.isChecked}
+                  onCheckedChange={(checked) => {
+                    checked ? handleAddFlag(index) : handleRemoveFlag(index);
+                    // Apply filters immediately after toggle
+                    handleFilterFlag();
+                  }}
+                  className="cursor-pointer"
+                >
+                  {ele.tag}
+                </DropdownMenuCheckboxItem>
+              ))}
+            </div>

Note: Make sure DropdownMenuCheckboxItem is exported from your ../ui/dropdown-menu wrapper.

@ssz2605
Copy link
Contributor Author

ssz2605 commented Aug 20, 2025

@rahulharpal1603 I will make the required changes.

@rahulharpal1603
Copy link
Contributor

@rahulharpal1603 I will make the required changes.

Hi,
what is the status?

@ssz2605
Copy link
Contributor Author

ssz2605 commented Aug 22, 2025

@rahulharpal1603 Sorry for the delay , will be completing it in the next 2-3 days at max .

@ssz2605 ssz2605 force-pushed the onboarding-layout branch from c97b429 to d42d220 Compare August 23, 2025 16:39
@ssz2605
Copy link
Contributor Author

ssz2605 commented Aug 23, 2025

@rahulharpal1603 Now can you please review the changes.

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

♻️ Duplicate comments (3)
frontend/src/components/OnboardingSteps/OnboardingStep.tsx (1)

27-35: Stop passing onNext/onBack to children to fix TS prop errors

AvatarSelectionStep, FolderSetupStep, and ThemeSelectionStep don’t declare onNext/onBack props. Passing them causes TypeScript errors at these call sites. Minimal safe fix: remove onNext/onBack from sharedProps.

   const sharedProps = {
     stepIndex,
     totalSteps: VISIBLE_STEPS.length,
-    onNext,
-    onBack,
   };

Optional cleanup (only if the parent doesn’t rely on these): also drop onNext/onBack from the component props and destructuring to avoid unused-prop lint warnings.

 interface OnboardingStepProps {
   stepIndex: number;
   stepName: string;
-  onNext: () => void;
-  onBack: () => void;
 }
 ...
 export const OnboardingStep: React.FC<OnboardingStepProps> = ({
   stepIndex,
   stepName,
-  onNext,
-  onBack,
 }) => {
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (2)

86-92: Replace alert() with inline validation for better UX and tests

Blocking alerts are jarring and hard to test. Use local state to show an inline error.

+  const [validationError, setValidationError] = useState<string>('');
   const handleNextClick = () => {
     if (name && selectedAvatar) {
       dispatch(markCompleted(stepIndex));
+      setValidationError('');
     } else {
-      alert('Please enter your name and select an avatar.');
+      setValidationError('Please enter your name and select an avatar.');
     }
   };

Add an inline message under the inputs:

@@
             {/* Name Input */}
             <div className="mb-5">
@@
             </div>
+            {validationError && (
+              <p className="text-destructive text-xs mb-3">{validationError}</p>
+            )}

Also clear the error on change:

-  const handleAvatarSelect = (avatar: string) => {
-    dispatch(setAvatar(avatar));
-  };
+  const handleAvatarSelect = (avatar: string) => {
+    dispatch(setAvatar(avatar));
+    setValidationError('');
+  };
@@
-  const handleNameChange = (value: string) => {
-    dispatch(setName(value));
-  };
+  const handleNameChange = (value: string) => {
+    dispatch(setName(value));
+    setValidationError('');
+  };

5-10: Fix incorrect store import path

RootState should come from '@/app/store' in this codebase. Current path likely fails module resolution.

-import { RootState } from '@/store';
+import { RootState } from '@/app/store';

Optional: also type dispatch for better inference.

-  const dispatch = useDispatch();
+  const dispatch = useDispatch<AppDispatch>();

(Requires: import { AppDispatch } from '@/app/store')

🧹 Nitpick comments (6)
frontend/src/components/OnboardingSteps/OnboardingStep.tsx (2)

50-53: Wrapper width conflicts with child layout (max-w-4xl vs. max-w-7xl)

Children render their own responsive two-panel layouts sized for max-w-7xl. Constraining them inside max-w-4xl can clip or squash the design. Let the step component own its layout.

-  return (
-    <div className="bg-background text-foreground flex min-h-screen w-full items-center justify-center p-10">
-      <div className="w-full max-w-4xl">{renderStepComponent()}</div>
-    </div>
-  );
+  return renderStepComponent();

Alternatively, bump the wrapper to max-w-7xl to match children.


45-47: Provide a meaningful fallback for unknown stepName

Returning an empty div hampers debugging. Render a lightweight fallback (or null) with a console.warn.

-      default:
-        return <div></div>;
+      default:
+        console.warn('Unknown onboarding step:', stepName);
+        return null;
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (2)

145-149: Missing base border utility; border-muted won’t render without border

Tailwind’s color utilities don’t add a border by themselves. Add the base border class so the unselected avatar has a visible outline.

-                      className={`bg-background relative inline-flex h-20 w-20 items-center justify-center rounded-full transition-all duration-300 ${
+                      className={`bg-background relative inline-flex h-20 w-20 items-center justify-center rounded-full transition-all duration-300 border ${
                         isSelected
                           ? 'border-primary ring-primary ring-offset-background ring-2 ring-offset-2'
                           : 'border-muted'
                       }`}

141-159: Improve keyboard and screen reader accessibility for avatar choices

These act like a single-select control. Consider RadioGroup semantics (you already ship a RadioGroup component) or add appropriate ARIA:

  • Wrap items in a role="radiogroup"
  • Each button: role="radio", aria-checked={isSelected}, aria-label={Avatar ${i+1}}
  • Support keyboard navigation (ArrowLeft/Right)

I can provide a patch if you want to adopt the RadioGroup version.

frontend/src/components/OnboardingSteps/FolderSetupStep.tsx (2)

126-147: Use stable keys and add accessible labels for remove buttons

Index keys can cause reconciliation bugs when items are removed. Use the folder path as the key. Also add an aria-label to the remove control.

-              {folders.map((folder, index) => (
+              {folders.map((folder) => (
                 <div
-                  key={index}
+                  key={folder}
                   className="bg-muted flex items-center justify-between rounded-md px-4 py-2 text-sm"
                 >
@@
                   <button
                     type="button"
                     onClick={() => handleRemoveFolder(folder)}
-                    className="text-destructive hover:text-red-600"
+                    className="text-destructive hover:text-red-600"
+                    aria-label={`Remove folder ${folder}`}
                   >

151-162: Disable “Next” until at least one folder is selected

Prevents accidental progression with an empty selection and aligns UX with validation in other steps.

-            <Button onClick={handleNext} className="px-6 py-3 text-base">
+            <Button
+              onClick={handleNext}
+              className="px-6 py-3 text-base"
+              disabled={folders.length === 0}
+            >
               Next
             </Button>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c97b429 and d42d220.

⛔ Files ignored due to path filters (9)
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • frontend/public/avatars/avatar1.png is excluded by !**/*.png
  • frontend/public/avatars/avatar2.png is excluded by !**/*.png
  • frontend/public/avatars/avatar3.png is excluded by !**/*.png
  • frontend/public/avatars/avatar4.png is excluded by !**/*.png
  • frontend/public/avatars/avatar5.png is excluded by !**/*.png
  • frontend/public/avatars/avatar6.png is excluded by !**/*.png
  • frontend/public/avatars/avatar7.png is excluded by !**/*.png
  • frontend/public/avatars/avatar8.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • frontend/package.json (1 hunks)
  • frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (1 hunks)
  • frontend/src/components/OnboardingSteps/FolderSetupStep.tsx (1 hunks)
  • frontend/src/components/OnboardingSteps/OnboardingStep.tsx (1 hunks)
  • frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx (1 hunks)
  • frontend/src/components/OnboardingSteps/UpdateStep.tsx (2 hunks)
  • frontend/src/components/ui/label.tsx (1 hunks)
  • frontend/src/components/ui/radio-group.tsx (1 hunks)
  • frontend/src/constants/steps.ts (1 hunks)
  • frontend/src/features/onboardingSlice.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • frontend/src/components/ui/radio-group.tsx
  • frontend/src/features/onboardingSlice.ts
  • frontend/src/constants/steps.ts
  • frontend/src/components/ui/label.tsx
  • frontend/package.json
  • frontend/src/components/OnboardingSteps/UpdateStep.tsx
  • frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx
🧰 Additional context used
🧬 Code graph analysis (3)
frontend/src/components/OnboardingSteps/FolderSetupStep.tsx (2)
frontend/src/app/store.ts (2)
  • AppDispatch (14-14)
  • RootState (12-12)
frontend/src/features/onboardingSlice.ts (4)
  • addFolder (38-42)
  • removeFolder (43-47)
  • markCompleted (48-59)
  • previousStep (60-67)
frontend/src/components/OnboardingSteps/OnboardingStep.tsx (4)
frontend/src/constants/steps.ts (1)
  • STEPS (1-5)
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (1)
  • AvatarSelectionStep (57-202)
frontend/src/components/OnboardingSteps/FolderSetupStep.tsx (1)
  • FolderSetupStep (52-196)
frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx (1)
  • ThemeSelectionStep (52-204)
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (2)
frontend/src/app/store.ts (1)
  • RootState (12-12)
frontend/src/features/onboardingSlice.ts (3)
  • setAvatar (29-31)
  • setName (32-34)
  • markCompleted (48-59)
🪛 GitHub Check: Linting
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx

[warning] 176-176:
Headings must have content and the content must be accessible by a screen reader

⏰ 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: Tauri Build Check (ubuntu-22.04)
  • GitHub Check: Tauri Tests
🔇 Additional comments (1)
frontend/src/components/OnboardingSteps/FolderSetupStep.tsx (1)

70-74: Confirm placeholder folder selection won’t ship

The mock path generation is fine for scaffolding, but ensure a real folder picker (or platform-native dialog) replaces this before release.

Would you like me to open a follow-up issue with acceptance criteria for the real folder picker (including multi-select, duplicates handling, and error states)?

@rahulharpal1603
Copy link
Contributor

@rahulharpal1603 Now can you please review the changes.

I have requested some small changes; please apply those changes.

@rahulharpal1603
Copy link
Contributor

@ssz2605 any updates? This was the final review, after the changes are made I will be merging the PR.

@ssz2605
Copy link
Contributor Author

ssz2605 commented Aug 25, 2025

@rahulharpal1603 I'm currently working on the changes and will update the PR soon. Apologies for the delay, I’ve been tied up with a hectic schedule.

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

♻️ Duplicate comments (4)
frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx (1)

5-5: Incorrect store import path

Import RootState/AppDispatch from '@/app/store' to match the codebase.

-import { AppDispatch, RootState } from '@/store';
+import { AppDispatch, RootState } from '@/app/store';
frontend/src/components/OnboardingSteps/OnboardingStep.tsx (1)

31-36: Stop passing unsupported onNext/onBack to children

Child steps don’t declare onNext/onBack props; spreading them causes TS errors. Keep them on the wrapper if needed, but don’t spread to steps.

   const sharedProps = {
     stepIndex,
     totalSteps: VISIBLE_STEPS.length,
-    onNext,
-    onBack,
   };
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (1)

5-5: Incorrect store import path

Use '@/app/store' for RootState.

-import { RootState } from '@/store';
+import { RootState } from '@/app/store';
frontend/src/components/OnboardingSteps/FolderSetupStep.tsx (1)

15-15: Fix incorrect store import path

RootState and AppDispatch should come from '@/app/store'.

-import { RootState, AppDispatch } from '@/store';
+import { RootState, AppDispatch } from '@/app/store';
🧹 Nitpick comments (7)
frontend/src/components/OnboardingSteps/appFeatures.tsx (1)

50-52: Fix empty heading to satisfy a11y lint rule

The self-closing h2 renders no accessible name and triggers the linter warning. Remove it or keep the CardHeader without a heading.

Apply this diff:

-      <CardHeader className="p-6 pb-4">
-        <h2 className="text-center text-xl font-semibold" />
-      </CardHeader>
+      <CardHeader className="p-6 pb-4" />
frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx (2)

39-39: Remove unused state

featureIndex/setFeatureIndex are not used; drop the state to silence lint.

-  const [featureIndex, setFeatureIndex] = useState(0);

56-69: “System” theme should react to OS changes

When selectedTheme === 'system', attach a matchMedia listener to update on OS theme changes. Optional but improves UX.

   useEffect(() => {
     if (selectedTheme === 'system') {
-      const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
-      document.documentElement.setAttribute(
-        'data-theme',
-        isDark ? 'dark' : 'light',
-      );
+      const mql = window.matchMedia('(prefers-color-scheme: dark)');
+      const apply = () =>
+        document.documentElement.setAttribute('data-theme', mql.matches ? 'dark' : 'light');
+      apply();
+      mql.addEventListener?.('change', apply);
+      return () => mql.removeEventListener?.('change', apply);
     } else if (selectedTheme) {
       document.documentElement.setAttribute('data-theme', selectedTheme);
     }
     if (selectedTheme) {
       localStorage.setItem('theme', selectedTheme);
     }
   }, [selectedTheme]);
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (2)

13-13: Drop unused CardContent import

It’s not used in this component.

-import { Card, CardHeader, CardContent } from '@/components/ui/card';
+import { Card, CardHeader } from '@/components/ui/card';

53-59: Replace alert() with inline validation for better UX

Toast or inline error beats a blocking alert. Minimal inline approach below.

-  const handleNextClick = () => {
+  const [validationError, setValidationError] = React.useState('');
+  const handleNextClick = () => {
     if (name && selectedAvatar) {
       dispatch(markCompleted(stepIndex));
+      setValidationError('');
     } else {
-      alert('Please enter your name and select an avatar.');
+      setValidationError('Please enter your name and select an avatar.');
     }
   };

Render under the inputs (e.g., after the avatar grid):

               </div>
             </div>
+            {validationError && (
+              <p className="text-destructive mt-2 text-sm" role="alert" aria-live="polite">
+                {validationError}
+              </p>
+            )}
frontend/src/components/OnboardingSteps/FolderSetupStep.tsx (2)

97-101: Use stable key for folder list items

Keys should be stable and unique; folder path is unique already.

-              {folders.map((folder, index) => (
+              {folders.map((folder) => (
                 <div
-                  key={index}
+                  key={folder}
                   className="bg-muted flex items-center justify-between rounded-md px-4 py-2 text-sm"
                 >

37-40: Follow-up: Replace mock folder selection

The mock path is fine for scaffolding, but wire this to the real folder picker (e.g., Tauri dialog) before shipping.

I can draft a small adapter around a Tauri/IPC folder picker and update this handler; want me to open a task and provide a patch?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d42d220 and dbb1438.

📒 Files selected for processing (6)
  • frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (1 hunks)
  • frontend/src/components/OnboardingSteps/FolderSetupStep.tsx (1 hunks)
  • frontend/src/components/OnboardingSteps/OnboardingStep.tsx (1 hunks)
  • frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx (1 hunks)
  • frontend/src/components/OnboardingSteps/appFeatures.tsx (1 hunks)
  • frontend/src/constants/steps.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/constants/steps.ts
🧰 Additional context used
🧬 Code graph analysis (5)
frontend/src/components/OnboardingSteps/appFeatures.tsx (1)
frontend/src/components/ui/card.tsx (3)
  • Card (85-85)
  • CardHeader (86-86)
  • CardContent (91-91)
frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx (3)
frontend/src/app/store.ts (2)
  • AppDispatch (14-14)
  • RootState (12-12)
frontend/src/features/onboardingSlice.ts (3)
  • setTheme (35-37)
  • markCompleted (48-59)
  • previousStep (60-67)
frontend/src/components/OnboardingSteps/appFeatures.tsx (1)
  • AppFeatures (36-76)
frontend/src/components/OnboardingSteps/FolderSetupStep.tsx (3)
frontend/src/app/store.ts (2)
  • AppDispatch (14-14)
  • RootState (12-12)
frontend/src/features/onboardingSlice.ts (4)
  • addFolder (38-42)
  • removeFolder (43-47)
  • markCompleted (48-59)
  • previousStep (60-67)
frontend/src/components/OnboardingSteps/appFeatures.tsx (1)
  • AppFeatures (36-76)
frontend/src/components/OnboardingSteps/OnboardingStep.tsx (5)
frontend/src/constants/steps.ts (1)
  • STEPS (1-6)
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (1)
  • AvatarSelectionStep (35-145)
frontend/src/components/OnboardingSteps/FolderSetupStep.tsx (1)
  • FolderSetupStep (30-137)
frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx (1)
  • ThemeSelectionStep (30-151)
frontend/src/components/OnboardingSteps/UpdateStep.tsx (1)
  • UpdateStep (12-57)
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (3)
frontend/src/app/store.ts (1)
  • RootState (12-12)
frontend/src/features/onboardingSlice.ts (3)
  • setAvatar (29-31)
  • setName (32-34)
  • markCompleted (48-59)
frontend/src/components/OnboardingSteps/appFeatures.tsx (1)
  • AppFeatures (36-76)
🪛 GitHub Check: Linting
frontend/src/components/OnboardingSteps/appFeatures.tsx

[warning] 51-51:
Headings must have content and the content must be accessible by a screen reader

frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx

[warning] 39-39:
'setFeatureIndex' is assigned a value but never used


[warning] 39-39:
'featureIndex' is assigned a value but never used

frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx

[warning] 13-13:
'CardContent' is defined but never used


[warning] 3-3:
'useState' is defined but never used

🪛 GitHub Actions: PR Check Build
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx

[error] 3-3: TS6133: 'useState' is declared but its value is never read. Step: npm run tauri build.

⏰ 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: Tauri Tests
🔇 Additional comments (2)
frontend/src/components/OnboardingSteps/appFeatures.tsx (1)

48-75: LGTM overall

Auto-rotating features with cleanup is correct; modulo logic prevents OOB access. Nice reuse across steps.

frontend/src/components/OnboardingSteps/OnboardingStep.tsx (1)

19-23: The script will print out the top ~200 lines of the OnboardingStep component so we can verify how progress (and totalSteps) are calculated and whether it uses the same STEP_NAMES list. Once we have that, we can confirm if the update step ordering or progress‐bar logic needs adjusting. Please share the script output so we can complete the verification.

@rahulharpal1603 rahulharpal1603 merged commit 9897c25 into AOSSIE-Org:main Aug 30, 2025
4 of 8 checks passed
@rahulharpal1603
Copy link
Contributor

@ssz2605 Thanks for the contribution!

@ssz2605
Copy link
Contributor Author

ssz2605 commented Aug 30, 2025

Thanks for your guidance in resolving this issue, @rahulharpal1603.

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.

New Onboarding page for PictoPy

2 participants