Skip to content

feat: refactor profile screen to support public view mode#777

Open
Arunodoy18 wants to merge 1 commit intoAOSSIE-Org:masterfrom
Arunodoy18:feat/749-profile-view
Open

feat: refactor profile screen to support public view mode#777
Arunodoy18 wants to merge 1 commit intoAOSSIE-Org:masterfrom
Arunodoy18:feat/749-profile-view

Conversation

@Arunodoy18
Copy link

@Arunodoy18 Arunodoy18 commented Mar 1, 2026

Summary

Adds a public view mode to the Profile screen to allow users to see how their profile appears to others.

Changes

  • Introduced view mode flag
  • Conditionally hides owner-only UI elements
  • Reused existing layout and components
  • No duplication of Profile screen

This improves clarity and ensures consistent behavior when viewing other users’ profiles.

Summary by CodeRabbit

  • Refactor
    • Improved profile screen view logic to better distinguish between viewing your own profile and others' profiles, ensuring appropriate UI elements and interactions are displayed accordingly.

- Introduce isOwner boolean flag for clear semantic separation
- Hide owner-only UI elements in public view:
  * Edit Profile button
  * Settings access button
  * Email verification prompts
  * AppBar notifications and friends icons
  * Email verification badge
- Replace all widget.isCreatorProfile checks with isOwner flag
- Maintain consistent UI structure without screen duplication
- Preserve all navigation logic and business logic
- Improve code readability with semantic naming

Resolves AOSSIE-Org#749
Copilot AI review requested due to automatic review settings March 1, 2026 10:20
@Arunodoy18 Arunodoy18 requested a review from M4dhav as a code owner March 1, 2026 10:20
@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2026

🎉 Welcome @Arunodoy18!
Thank you for your pull request! Our team will review it soon. 🔍

  • Please ensure your PR follows the contribution guidelines. ✅
  • All automated tests should pass before merging. 🔄
  • If this PR fixes an issue, link it in the description. 🔗

We appreciate your contribution! 🚀

@coderabbitai
Copy link

coderabbitai bot commented Mar 1, 2026

📝 Walkthrough

Walkthrough

The profile screen is refactored to introduce an isOwner getter that consolidates ownership checking logic, replacing scattered widget.isCreatorProfile checks throughout the screen to control visibility and behavior of various UI elements.

Changes

Cohort / File(s) Summary
Profile View Mode Logic
lib/views/screens/profile_screen.dart
Introduces isOwner getter to centralize ownership checking. Refactors conditional rendering across app bar actions, header image selection, name/username display, ratings, followers, verification button, profile action buttons, settings UI, section headings, and story lists/empty states to use the new ownership check.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A getter so neat, so clean, so divine,
Replaces the checks that were tangled in line,
Now isOwner makes profiles shine bright,
With ownership logic centralized just right! ✨

🚥 Pre-merge checks | ✅ 3
✅ 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 accurately captures the main refactoring objective: introducing a public view mode for the profile screen and reorganizing ownership-based logic throughout the component.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • 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

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

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors ProfileScreen to support an “owner vs public view” mode so the same screen can be reused when viewing another user’s profile, hiding owner-only UI elements.

Changes:

  • Introduced an isOwner getter to centralize owner/public mode detection.
  • Updated conditional UI rendering (app bar actions, header, buttons, stories labels/data sources) to use isOwner.
  • Adjusted follow/edit/settings/friend-request button logic to switch behavior based on view mode.
Comments suppressed due to low confidence (1)

lib/views/screens/profile_screen.dart:352

  • In the follow/edit ElevatedButton, the button style sets foregroundColor to onSecondary when following, but the Icon and Text explicitly use colorScheme.onPrimary. This overrides the configured foreground color and can produce incorrect contrast (especially when backgroundColor is secondary). Consider removing the explicit color: / TextStyle(color:) so the foregroundColor takes effect, or compute the icon/text color from the same state as the style.
                  Icon(
                    !isOwner
                        ? userProfileController.isFollowingUser.value
                              ? Icons.done
                              : Icons.add
                        : Icons.edit,
                    color: colorScheme.onPrimary,
                  ),
                  const SizedBox(width: 8),
                  Text(
                    !isOwner
                        ? userProfileController.isFollowingUser.value
                              ? AppLocalizations.of(context)!.following
                              : AppLocalizations.of(context)!.follow
                        : AppLocalizations.of(context)!.editProfile,
                    style: TextStyle(color: colorScheme.onPrimary),
                  ),

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +44 to +46
/// Returns true if the current user is viewing their own profile (owner mode)
/// Returns false if viewing another user's profile (public view mode)
bool get isOwner => widget.isCreatorProfile == null;
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

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

isOwner is derived from widget.isCreatorProfile == null, but the widget API uses a nullable bool where only true is constrained by the constructor assert. If a caller ever passes isCreatorProfile: false (allowed by the assert), isOwner becomes false and the screen will dereference widget.creator! in multiple places and crash. Consider defining owner mode as widget.isCreatorProfile != true (or make the flag non-nullable with a default) and update the doc comment to match the actual semantics.

Suggested change
/// Returns true if the current user is viewing their own profile (owner mode)
/// Returns false if viewing another user's profile (public view mode)
bool get isOwner => widget.isCreatorProfile == null;
/// Returns true if the current user is viewing their own profile (owner mode).
/// Returns false only when explicitly in creator profile mode (`isCreatorProfile == true`).
bool get isOwner => widget.isCreatorProfile != true;

Copilot uses AI. Check for mistakes.
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: 1

Caution

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

⚠️ Outside diff range comments (2)
lib/views/screens/profile_screen.dart (2)

150-155: ⚠️ Potential issue | 🟠 Major

Avoid empty URL fallback in public avatar image.

Line 151 can construct NetworkImage('') when profileImageUrl is null/empty, which is unsafe for image loading. Use the placeholder URL fallback in public mode too.

🔧 Proposed fix
-            backgroundImage: !isOwner
-                ? NetworkImage(widget.creator!.profileImageUrl ?? '')
+            backgroundImage: !isOwner
+                ? NetworkImage(
+                    (widget.creator?.profileImageUrl?.isNotEmpty ?? false)
+                        ? widget.creator!.profileImageUrl!
+                        : themeController.userProfileImagePlaceholderUrl,
+                  )
                 : controller.profileImageUrl == null ||
                       controller.profileImageUrl!.isEmpty
                 ? NetworkImage(themeController.userProfileImagePlaceholderUrl)
                 : NetworkImage(controller.profileImageUrl ?? ''),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/views/screens/profile_screen.dart` around lines 150 - 155, The avatar
backgroundImage can create NetworkImage('') when widget.creator!.profileImageUrl
is null/empty; update the ternary so both public (not owner) and owner branches
validate strings and fall back to themeController.userProfileImagePlaceholderUrl
when the URL is null or empty. Specifically check
widget.creator!.profileImageUrl for null or empty (similar to
controller.profileImageUrl checks) and use
themeController.userProfileImagePlaceholderUrl as the NetworkImage fallback to
avoid constructing NetworkImage with an empty URL.

210-214: ⚠️ Potential issue | 🟠 Major

Guard rating computation when count is zero.

Line 211 divides by authController.ratingCount without a zero check. For new users this can produce invalid rating output or a crash path in formatting.

🔧 Proposed fix
-                          isOwner
-                              ? (authController.ratingTotal /
-                                        authController.ratingCount)
-                                    .toStringAsFixed(1)
-                              : widget.creator!.userRating!.toStringAsFixed(1),
+                          isOwner
+                              ? (authController.ratingCount > 0
+                                    ? (authController.ratingTotal /
+                                              authController.ratingCount)
+                                          .toStringAsFixed(1)
+                                    : '0.0')
+                              : (widget.creator?.userRating?.toStringAsFixed(1) ??
+                                    '0.0'),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/views/screens/profile_screen.dart` around lines 210 - 214, The
owner-rated display divides authController.ratingTotal by
authController.ratingCount without checking for zero; update the isOwner branch
in profile_screen.dart so it first checks authController.ratingCount > 0 and
only then computes (authController.ratingTotal /
authController.ratingCount).toStringAsFixed(1); otherwise return a safe fallback
(e.g., "0.0" or another default) to avoid division by zero or formatting errors;
keep the non-owner branch using widget.creator!.userRating!.toStringAsFixed(1)
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/views/screens/profile_screen.dart`:
- Around line 44-47: Constructor allows isCreatorProfile == false without
creator, which later leads to widget.creator! dereferences; update the
ProfileScreen constructor to assert that whenever isCreatorProfile is explicitly
false (public view) then creator is non-null (e.g. add assert(isCreatorProfile
!= false || creator != null, 'creator must be provided when viewing another
user\'s profile')), and keep the existing isOwner getter logic unchanged or
clarify it to match the invariant so all uses of widget.creator! are safe.

---

Outside diff comments:
In `@lib/views/screens/profile_screen.dart`:
- Around line 150-155: The avatar backgroundImage can create NetworkImage('')
when widget.creator!.profileImageUrl is null/empty; update the ternary so both
public (not owner) and owner branches validate strings and fall back to
themeController.userProfileImagePlaceholderUrl when the URL is null or empty.
Specifically check widget.creator!.profileImageUrl for null or empty (similar to
controller.profileImageUrl checks) and use
themeController.userProfileImagePlaceholderUrl as the NetworkImage fallback to
avoid constructing NetworkImage with an empty URL.
- Around line 210-214: The owner-rated display divides
authController.ratingTotal by authController.ratingCount without checking for
zero; update the isOwner branch in profile_screen.dart so it first checks
authController.ratingCount > 0 and only then computes
(authController.ratingTotal / authController.ratingCount).toStringAsFixed(1);
otherwise return a safe fallback (e.g., "0.0" or another default) to avoid
division by zero or formatting errors; keep the non-owner branch using
widget.creator!.userRating!.toStringAsFixed(1) unchanged.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf1dbe2 and b614a05.

📒 Files selected for processing (1)
  • lib/views/screens/profile_screen.dart

Comment on lines +44 to +47
/// Returns true if the current user is viewing their own profile (owner mode)
/// Returns false if viewing another user's profile (public view mode)
bool get isOwner => widget.isCreatorProfile == 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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Step 1: Examine the ProfileScreen constructor and isOwner getter
sed -n '30,50p' lib/views/screens/profile_screen.dart

Repository: AOSSIE-Org/Resonate

Length of output: 743


🏁 Script executed:

# Step 2: Find all ProfileScreen instantiations
rg -n 'ProfileScreen\s*\(' lib/ --type=dart -B2 -A4

Repository: AOSSIE-Org/Resonate

Length of output: 3572


🏁 Script executed:

# Step 3: Find specific patterns of isCreatorProfile usage
rg -n 'isCreatorProfile\s*:\s*(true|false|)' lib/ --type=dart -B2 -A2

Repository: AOSSIE-Org/Resonate

Length of output: 921


🏁 Script executed:

# Step 4: Check widget.creator! dereferences in the file
sed -n '140,220p' lib/views/screens/profile_screen.dart

Repository: AOSSIE-Org/Resonate

Length of output: 3386


Strengthen constructor assertion to prevent null-crash states in public mode.

The constructor allows isCreatorProfile: false without requiring creator, but the logic treats any non-null isCreatorProfile as public mode, which dereferences widget.creator! (lines 150, 183, 193, 214). While no current call sites exploit this, the assertion should enforce the invariant that creator is required whenever viewing another user's profile.

🔧 Proposed fix
-  ProfileScreen({super.key, this.creator, this.isCreatorProfile})
-    : assert(
-        isCreatorProfile != true || (creator != null && creator.uid != null),
-        'creator and creator.uid are required when isCreatorProfile is true',
-      );
+  ProfileScreen({super.key, this.creator, this.isCreatorProfile})
+    : assert(
+        isCreatorProfile == null || (creator != null && creator.uid != null),
+        'creator and creator.uid are required when viewing another user profile',
+      );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/views/screens/profile_screen.dart` around lines 44 - 47, Constructor
allows isCreatorProfile == false without creator, which later leads to
widget.creator! dereferences; update the ProfileScreen constructor to assert
that whenever isCreatorProfile is explicitly false (public view) then creator is
non-null (e.g. add assert(isCreatorProfile != false || creator != null, 'creator
must be provided when viewing another user\'s profile')), and keep the existing
isOwner getter logic unchanged or clarify it to match the invariant so all uses
of widget.creator! are safe.

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