Skip to content

Comments

fix(profile): improve validation and fix padding error#66

Open
amankv1234 wants to merge 1 commit intoAOSSIE-Org:mainfrom
amankv1234:patch-2
Open

fix(profile): improve validation and fix padding error#66
amankv1234 wants to merge 1 commit intoAOSSIE-Org:mainfrom
amankv1234:patch-2

Conversation

@amankv1234
Copy link

@amankv1234 amankv1234 commented Sep 22, 2025

What

  • Fixed duplicate padding in Profile screen
  • Added proper validator for username (no '@', min 3 characters)
  • Disposed TextEditingController to prevent memory leaks
  • Improved loading state handling
  • Removed duplicate imports at end of file

Why

  • Duplicate padding caused compilation error
  • Validator was not working correctly
  • Without dispose(), memory leaks could occur
  • Cleaner code and better UX

How

  • Tested on emulator (Android)
  • Entered invalid name → error shown
  • Entered valid name → saved to SharedPreferences and navigated to HomeScreen

Summary by CodeRabbit

  • New Features
    • Added a Profile screen to set your display name and view a persistent user ID.
    • Live preview shows how your name appears with the ID.
    • Name validation: must be at least 4 characters, cannot contain “@”, and cannot be empty; clear error messages guide corrections.
    • Saves your name and ID on the device for future sessions.
    • After saving, returns to the previous screen or continues to Home when coming from login.
    • Shows a loading indicator while your saved info is retrieved.

@coderabbitai
Copy link

coderabbitai bot commented Sep 22, 2025

Walkthrough

Adds a new stateful Profile UI that loads/saves a username and persistent ID via SharedPreferences, validates input, previews the composite name+id, and navigates either to HomeScreen (replace) or back (pop) based on an onLogin flag. Uses nanoid for ID generation and updates Global.myName on navigation.

Changes

Cohort / File(s) Summary of Changes
Profile widget and persistence
…/profile.dart
Introduces Profile (StatefulWidget) with TextEditingController, form validation (non-empty, no '@', length > 3), loading state until SharedPreferences fetch completes, nanoid-generated ID with saved override, preview UI, Save button persisting p_name and p_id, navigation: replace to HomeScreen when onLogin, else pop; sets Global.myName; disposes controller.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant P as Profile Widget
  participant SP as SharedPreferences
  participant N as Navigator
  participant H as HomeScreen

  Note over P: Init
  P->>SP: read p_name, p_id
  SP-->>P: stored values or null
  P->>P: set state (name, id, loading=false)

  U->>P: edits name in TextField
  P->>P: validate (non-empty, no '@', len>3)
  U->>P: taps Save
  alt form valid
    P->>SP: set p_name, p_id
    SP-->>P: ack
    P->>P: update Global.myName
    alt onLogin == true
      P->>N: pushReplacement(HomeScreen)
      N->>H: build
    else onLogin == false
      P->>N: pop()
    end
  else invalid
    P-->>U: show validator error / snackbar
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I nibbled code and grew a name,
With nano-IDs to stake my claim.
I cached it snug where prefs abide,
Then hopped to Home with joyful pride.
If not from login, I bounce right back—
A tidy trail on every track. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "fix(profile): improve validation and fix padding error" concisely and accurately summarizes the primary changes in this PR by naming the validation improvements and the padding fix that caused a compile error, matching the PR objectives and file-level summary. It uses conventional commit style, is specific enough for a quick scan, and does not misrepresent the changeset even though the PR also includes smaller cleanups like controller disposal and loading-state tweaks. Overall the title is clear, relevant, and appropriately focused.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

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

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

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

Please see the documentation for more information.

Example:

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

Please share your feedback with us on this Discord post.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

@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

🧹 Nitpick comments (3)
solution (3)

74-76: Preview doesn’t update while typing

Text('${myName.text}...') won’t rebuild on controller changes. Use ValueListenableBuilder to make it reactive.

-                  // show what the final username will look like
-                  Text('Your username will be: ${myName.text}$customLengthId'),
+                  // show what the final username will look like
+                  ValueListenableBuilder<TextEditingValue>(
+                    valueListenable: myName,
+                    builder: (_, value, __) =>
+                        Text('Your username will be: ${value.text}$customLengthId'),
+                  ),

51-61: Navigation polish + trim before persisting to Global

Guard pop to avoid no‑route errors in edge cases and trim the value assigned to Global.myName.

-    Global.myName = myName.text;
-    if (!widget.onLogin) {
-      Navigator.pop(context);
-    } else {
+    Global.myName = myName.text.trim();
+    if (!widget.onLogin) {
+      if (Navigator.of(context).canPop()) {
+        Navigator.of(context).pop();
+      } else {
+        Navigator.pushReplacement(
+          context,
+          MaterialPageRoute(builder: (context) => const HomeScreen()),
+        );
+      }
+    } else {
       Navigator.pushReplacement(
         context,
         MaterialPageRoute(builder: (context) => const HomeScreen()),
       );
     }

79-94: Prevent typing “@” at the source with an input formatter (keeps validator too)

Optional, but improves UX and reduces error toasts.

   TextFormField(
     controller: myName,
+    inputFormatters: [FilteringTextInputFormatter.deny(RegExp(r'@'))],
     decoration: const InputDecoration(

Add import:

 import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30427d8 and d4d9962.

📒 Files selected for processing (1)
  • solution (1 hunks)
🔇 Additional comments (1)
solution (1)

51-61: Confirm: should Global.myName include the ID suffix?

Preview shows "name+id" but profile.dart assigns Global.myName = name (no id); Global.myName is used as the P2P deviceName and as message sender/receiver — a mismatch will cause routing/peer-match failures if peers use "name+id".

  • lib/pages/profile.dart — getString('p_name') at :50, getString('p_id') at :51; prefs.setString('p_name')/:p_id at :79–:80; Global.myName = name at :61 and :81.
  • lib/p2p/adhoc_housekeeping.dart — "sender": Global.myName at :211 and :241; compare decodedMessage['receiver'] == Global.myName at :366; nearby init deviceName: Global.myName at :386.
  • lib/components/message_panel.dart — message payloads use Global.myName as sender and in Payload constructors (e.g., :176, :185, :206, :322, :329).
  • lib/classes/global.dart — static String myName = '' at :27.

Decide canonical identifier: if canonical ID is "name+id", set Global.myName to include the id before navigation (and persist the same string); otherwise ensure peers/preview use only the plain name so comparisons remain consistent.

Comment on lines +34 to +49
Future<void> getDetails() async {
final prefs = await SharedPreferences.getInstance();
final name = prefs.getString('p_name') ?? '';
final id = prefs.getString('p_id') ?? '';

setState(() {
myName.text = name;
if (id.isNotEmpty) customLengthId = id;
loading = false;
});

// If profile already exists and we arrived here from login flow, go home
if (name.isNotEmpty && id.isNotEmpty && widget.onLogin) {
navigateToHomeScreen();
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix: avoid setState/navigation after dispose; schedule post‑frame navigation

getDetails awaits then calls setState and may navigate immediately. If the widget unmounts meanwhile, this will throw. Add mounted checks and schedule navigation with addPostFrameCallback.

   Future<void> getDetails() async {
-    final prefs = await SharedPreferences.getInstance();
-    final name = prefs.getString('p_name') ?? '';
-    final id = prefs.getString('p_id') ?? '';
+    final prefs = await SharedPreferences.getInstance();
+    if (!mounted) return;
+    final name = prefs.getString('p_name') ?? '';
+    final id = prefs.getString('p_id') ?? '';

-    setState(() {
-      myName.text = name;
-      if (id.isNotEmpty) customLengthId = id;
-      loading = false;
-    });
+    if (!mounted) return;
+    setState(() {
+      myName.text = name;
+      if (id.isNotEmpty) customLengthId = id;
+      loading = false;
+    });

     // If profile already exists and we arrived here from login flow, go home
-    if (name.isNotEmpty && id.isNotEmpty && widget.onLogin) {
-      navigateToHomeScreen();
-    }
+    if (name.isNotEmpty && id.isNotEmpty && widget.onLogin) {
+      WidgetsBinding.instance.addPostFrameCallback((_) {
+        if (!mounted) return;
+        navigateToHomeScreen();
+      });
+    }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Future<void> getDetails() async {
final prefs = await SharedPreferences.getInstance();
final name = prefs.getString('p_name') ?? '';
final id = prefs.getString('p_id') ?? '';
setState(() {
myName.text = name;
if (id.isNotEmpty) customLengthId = id;
loading = false;
});
// If profile already exists and we arrived here from login flow, go home
if (name.isNotEmpty && id.isNotEmpty && widget.onLogin) {
navigateToHomeScreen();
}
}
Future<void> getDetails() async {
final prefs = await SharedPreferences.getInstance();
if (!mounted) return;
final name = prefs.getString('p_name') ?? '';
final id = prefs.getString('p_id') ?? '';
if (!mounted) return;
setState(() {
myName.text = name;
if (id.isNotEmpty) customLengthId = id;
loading = false;
});
// If profile already exists and we arrived here from login flow, go home
if (name.isNotEmpty && id.isNotEmpty && widget.onLogin) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
navigateToHomeScreen();
});
}
}
🤖 Prompt for AI Agents
In solution around lines 34 to 49, getDetails awaits async work then calls
setState and may immediately navigate; if the widget was disposed in the
meantime this will throw. Fix by checking mounted before calling setState (skip
updating state if not mounted), and when deciding to navigate schedule the
navigation in a post-frame callback
(WidgetsBinding.instance.addPostFrameCallback) and re-check mounted before
calling navigateToHomeScreen; ensure no setState or navigation runs when mounted
is false.

Comment on lines +88 to +92
final v = value?.trim() ?? '';
if (v.isEmpty) return 'Please enter a name';
if (v.contains('@')) return 'Do not use the @ character';
if (v.length <= 3) return 'Name should be greater than 3 characters';
return null;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Validation off‑by‑one vs PR objective (“minimum of 3 characters”)

Current rule enforces 4+. Adjust to 3+ and fix the message.

-                        if (v.length <= 3) return 'Name should be greater than 3 characters';
+                        if (v.length < 3) return 'Name must be at least 3 characters';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
final v = value?.trim() ?? '';
if (v.isEmpty) return 'Please enter a name';
if (v.contains('@')) return 'Do not use the @ character';
if (v.length <= 3) return 'Name should be greater than 3 characters';
return null;
final v = value?.trim() ?? '';
if (v.isEmpty) return 'Please enter a name';
if (v.contains('@')) return 'Do not use the @ character';
if (v.length < 3) return 'Name must be at least 3 characters';
return null;
🤖 Prompt for AI Agents
In solution around lines 88 to 92, the validator currently rejects names of
length 3 (using v.length <= 3) and the message says "greater than 3 characters"
which conflicts with the PR objective of a minimum of 3; change the length check
to v.length < 3 and update the message to something like "Name should be at
least 3 characters" (keep existing trim and other checks unchanged).

@amankv1234
Copy link
Author

add my code to solve your first issue

@amankv1234
Copy link
Author

@amankv1234 amankv1234 closed this Sep 23, 2025
@amankv1234 amankv1234 deleted the patch-2 branch December 17, 2025 17:44
@amankv1234 amankv1234 restored the patch-2 branch December 17, 2025 17:44
@amankv1234 amankv1234 reopened this Dec 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant