Skip to content

Feature/admin only posts group#168

Open
rabble wants to merge 3 commits intomainfrom
feature/admin-only-posts-group
Open

Feature/admin only posts group#168
rabble wants to merge 3 commits intomainfrom
feature/admin-only-posts-group

Conversation

@rabble
Copy link
Copy Markdown
Collaborator

@rabble rabble commented Apr 11, 2025

Issues covered

Add reference(s) to a related issue in your repository.

Description

A description of the changes proposed in the pull request. Explain what it does to give the reviewer some context for what they're reviewing.

How to test

  1. Navigate to...
  2. Tap...

Screenshots/Video

Post screenshots or video showing your changes, ideally showing how the app worked before and after these changes. Delete this section if this PR contains no visual changes.

Before After
replaceme replaceme

@Chardot Please review these UI changes to be sure they match the design.

Summary by CodeRabbit

  • New Features

    • Introduced admin-only posting, enabling community managers to restrict posts to admins.
    • Redesigned the group invitation process for improved clarity and user guidance.
    • Enhanced the community creation workflow with clearer feedback and input blocking to prevent duplicate submissions.
  • Bug Fixes

    • Resolved an issue that allowed multiple submissions during community creation.
  • Documentation

    • Updated user-facing guidance and descriptions for community setup and management.

rabble added 3 commits April 12, 2025 02:14
Completely redesigned the invite dialog with better UX and implemented AbsorbPointer to block input during community creation, preventing duplicate submissions and improving error handling.
Added adminOnlyPosts property to GroupMetadata and updated NIP29 implementation to support admin-only posts. Modified the group edit UI with a toggle for this feature, and added permission checks to prevent non-admins from creating posts in admin-only groups.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 11, 2025

Walkthrough

This update introduces new community management features such as admin-only post permissions and a redesigned group invitation dialog. It also addresses issues around multiple community creation submissions and refines various UI components. Changes span from updated provider methods and SDK enhancements for status editing to improved localization and iOS build configurations with Sentry disabled at build time.

Changes

File(s) Change Summary
CHANGELOG.md, PR_UPDATE.md Added admin-only posts feature; redesigned group invitation dialog; fixed multiple submissions on community creation.
ios/Podfile, ios/Runner/Info.plist Simplified iOS pod installation using flutter_install_all_ios_pods; added preprocessor definition DISABLE_SENTRY=1 and new key DisableSentry in Info.plist.
lib/l10n/intl_en.arb Added new localization strings for admin-only posts and detailed instructions for community management.
lib/provider/group_provider.dart, packages/nostr_sdk/lib/nip29/nip29.dart Updated editStatus methods to accept an additional optional adminOnlyPosts parameter to manage post permissions.
packages/nostr_sdk/lib/nip29/group_metadata.dart Added an optional adminOnlyPosts property and updated the constructor and event loading logic accordingly.
lib/provider/list_provider.dart, lib/router/edit/editor_widget.dart, lib/router/group/create_community_dialog.dart, lib/router/group/create_community_widget.dart, lib/router/group/group_detail_widget.dart, lib/router/group/group_edit_widget.dart, lib/router/group/invite_people_widget.dart Various UI/UX updates: refactored widget state management, integrated role-based access control, improved loading state and error handling, and streamlined invite link generation.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant EW as EditorWidget
    participant GP as GroupProvider
    participant BT as BotToast
    U->>EW: Attempt to create a post
    EW->>GP: Retrieve group metadata and admin list
    GP-->>EW: Return metadata (adminOnlyPosts, admin list)
    Note over EW: Check if group restricts posts and user is not admin
    EW->>BT: Display "Access Denied" message
    EW-->>U: Block post submission
Loading
sequenceDiagram
    participant U as User
    participant CCD as CreateCommunityDialog
    participant CP as Community Processor
    participant Nav as Navigator
    U->>CCD: Enter community name & submit form
    CCD->>CP: Process community creation (_onCreateCommunity)
    Note over CCD,CP: UI is disabled (_isProcessing active)
    CP-->>CCD: Return success or failure
    alt Success
        CCD->>Nav: Close dialog & open Invite dialog
        Nav-->>U: Display Invite UI
    else Failure
        CCD->>U: Show SnackBar error message
    end
Loading

Poem

I'm a happy rabbit, hopping through new code,
Admin-only posts guard our secret node.
With dialogs refreshed and bugs put to bed,
Community creation now for us to tread.
Sentry is asleep—let's hop ahead! 🐰✨

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.

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.
    • Generate unit testing code for this file.
    • 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. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

  • 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
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🔭 Outside diff range comments (1)
lib/l10n/intl_en.arb (1)

1-422: 💡 Verification agent

🧩 Analysis chain

Verify consistency with other supported languages

The additions to the English localization file need corresponding entries in other language files to maintain consistency across all supported languages.

Run the following script to check if all the new strings exist in other language files:


🏁 Script executed:

#!/bin/bash
# Find all supported language files
LANG_FILES=$(find lib/l10n -name "intl_*.arb" | grep -v "intl_en.arb")

# New keys added in this PR
NEW_KEYS=(
  "admin_only_posts"
  "Group_AdminOnly_Description"
  "Group_AllMembers_Description"
  "community_created"
  "next_steps"
  "add_guidelines"
  "guidelines_description"
  "customize_community"
  "customize_description"
  "invite_people"
  "share_invite_link"
  "invitation_link"
  "link_copied"
  "go_to_community"
)

echo "Checking for missing translations in language files..."
for file in $LANG_FILES; do
  echo "Checking $file"
  for key in "${NEW_KEYS[@]}"; do
    if ! grep -q "\"$key\":" "$file"; then
      echo "  Missing key: $key"
    fi
  done
done

Length of output: 59618


Translation Consistency Issue: Missing Keys in Other Language Files

The new keys added in the English localization file (intl_en.arb) are missing from all the other supported language files. Please update each of the following language files (e.g., intl_ar.arb, intl_bg.arb, intl_cs.arb, etc.) to include the new keys:

  • admin_only_posts
  • Group_AdminOnly_Description
  • Group_AllMembers_Description
  • community_created
  • next_steps
  • add_guidelines
  • guidelines_description
  • customize_community
  • customize_description
  • invite_people
  • share_invite_link
  • invitation_link
  • link_copied
  • go_to_community

Ensuring these keys are present (with appropriate translations or placeholder values) will maintain consistency across all supported languages.

🧰 Tools
🪛 RuboCop (1.73)

[warning] 374-374: Duplicated key in hash literal.

(Lint/DuplicateHashKey)

🧹 Nitpick comments (2)
lib/provider/group_provider.dart (1)

36-38: Updated editStatus method to support admin-only posts.

The method signature has been properly extended to include the optional adminOnlyPosts parameter, which is then passed through to the underlying NIP29 implementation. Using an optional parameter maintains backward compatibility with existing call sites.

It would be helpful to add dartdoc comments to explain the purpose of this parameter for other developers.

-void editStatus(GroupIdentifier groupIdentifier, bool? public, bool? open, [bool? adminOnlyPosts]) {
+/// Updates the status of a group.
+/// 
+/// @param groupIdentifier The identifier of the group to update
+/// @param public Whether the group is public
+/// @param open Whether the group is open
+/// @param adminOnlyPosts Whether only admins can create posts in the group
+void editStatus(GroupIdentifier groupIdentifier, bool? public, bool? open, [bool? adminOnlyPosts]) {
lib/router/group/invite_people_widget.dart (1)

25-57: Consider fully utilizing the localization system

The _getText method provides good fallbacks, but it mixes direct string retrieval from S.of(context) with hardcoded strings. For better internationalization support:

Consider replacing hardcoded strings with proper entries in the localization files and retrieving them all via S.of(context):

-  return 'Next steps';
+  return S.of(context).next_steps;
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d0d5195 and fb71c69.

⛔ Files ignored due to path filters (3)
  • ios/Podfile.lock is excluded by !**/*.lock
  • lib/generated/intl/messages_en.dart is excluded by !**/generated/**
  • lib/generated/l10n.dart is excluded by !**/generated/**
📒 Files selected for processing (15)
  • CHANGELOG.md (1 hunks)
  • PR_UPDATE.md (1 hunks)
  • ios/Podfile (1 hunks)
  • ios/Runner/Info.plist (1 hunks)
  • lib/l10n/intl_en.arb (1 hunks)
  • lib/provider/group_provider.dart (1 hunks)
  • lib/provider/list_provider.dart (10 hunks)
  • lib/router/edit/editor_widget.dart (1 hunks)
  • lib/router/group/create_community_dialog.dart (6 hunks)
  • lib/router/group/create_community_widget.dart (2 hunks)
  • lib/router/group/group_detail_widget.dart (1 hunks)
  • lib/router/group/group_edit_widget.dart (4 hunks)
  • lib/router/group/invite_people_widget.dart (2 hunks)
  • packages/nostr_sdk/lib/nip29/group_metadata.dart (5 hunks)
  • packages/nostr_sdk/lib/nip29/nip29.dart (2 hunks)
🧰 Additional context used
🪛 LanguageTool
CHANGELOG.md

[style] ~36-~36: Consider using a different verb for a more formal wording.
Context: ...g with better UX and clear next steps - Fixed issue with community creation button al...

(FIX_RESOLVE)

🔇 Additional comments (42)
PR_UPDATE.md (6)

1-4: The PR title and summary clearly communicate the key features.

The title "Admin-Only Posts Feature and UI Improvements" accurately captures the main additions in this PR. The changes are well-structured with a clear high-level summary.


15-20: LGTM! Comprehensive feature description for admin-only posts.

The description clearly outlines what the admin-only posts feature does and its limitations. This provides good context for reviewers and future reference.


21-26: Well-structured explanation of the invite dialog redesign.

The documentation effectively highlights both the UX improvements and technical fixes in the invitation dialog redesign.


27-31: Good explanation of community creation improvements.

These changes directly address the issue mentioned in the CHANGELOG about preventing multiple submissions during community creation.


37-43: Technical implementation details provide helpful context.

The technical details clearly link to implementation specifics like the adminOnlyPosts property in GroupMetadata class and how permission checks were modified. This will be valuable for code reviewers.


46-50: Testing section covers all key functionality.

The testing section verifies each of the main features and fixes, which is good practice for ensuring quality.

ios/Runner/Info.plist (1)

40-41: iOS Sentry configuration properly implemented.

Adding the DisableSentry key with a value of true is the correct approach to disable Sentry at the Info.plist level. This works alongside the build-time configuration mentioned in PR_UPDATE.md.

CHANGELOG.md (1)

34-36: LGTM! Changelog entries align with PR features.

The three new entries in the changelog clearly describe the features and fixes implemented in this PR, matching the descriptions in PR_UPDATE.md.

Note that line 36 could be rephrased slightly for better formality, but the current wording is clear and understandable.

🧰 Tools
🪛 LanguageTool

[style] ~36-~36: Consider using a different verb for a more formal wording.
Context: ...g with better UX and clear next steps - Fixed issue with community creation button al...

(FIX_RESOLVE)

lib/router/group/create_community_widget.dart (3)

42-42: Good UI feedback: Disabling text input during loading state.

Disabling the TextField when loading is in progress prevents users from attempting to modify data during submission, which improves the user experience.


52-68: Well-implemented loading state to prevent multiple submissions.

The conditional rendering approach effectively addresses the issue of multiple community creation submissions:

  1. Shows a loading indicator when the request is in progress
  2. Disables the button during loading
  3. Maintains all original button properties when not loading

This implementation aligns with the fix mentioned in the CHANGELOG.


75-84: Check if additional error handling could be improved.

The _createCommunity method correctly prevents duplicate submissions with the loading state, but there's no error handling to reset the loading state if the community creation fails.

Consider updating the callback to handle potential errors and reset the loading state:

void _createCommunity() {
  if (_isLoading) return;

  setState(() {
    _isLoading = true;
  });

-  widget.onCreateCommunity(_communityNameController.text);
+  try {
+    widget.onCreateCommunity(_communityNameController.text);
+    // Navigation to next screen happens in the callback
+  } catch (e) {
+    // Reset loading state if an error occurs
+    setState(() {
+      _isLoading = false;
+    });
+    // Show error to user
+  }
}

Please verify if error handling is implemented in the parent component that provides the onCreateCommunity callback.

lib/provider/list_provider.dart (3)

564-629: Improved code cleanliness by removing debug print statements.

The removal of multiple debug print statements throughout the createGroupAndGenerateInvite method is good for cleaning up the codebase. Debug statements should typically be removed or replaced with proper logging before shipping to production.

For future reference, consider using a proper logging framework with configurable log levels instead of print statements for debugging. This would allow you to easily enable/disable logs without commenting/uncommenting code.


638-663: Removed debug print statements from _editMetadata method.

Similar to the changes in createGroupAndGenerateInvite, this is a good cleanup of debug statements in the _editMetadata method.


792-941: Improved queryPublicGroups method by removing debug logs.

The code cleanup in the queryPublicGroups method properly removes unnecessary debug logging statements.

lib/router/edit/editor_widget.dart (1)

78-92: Implemented admin-only posts feature check.

This new block correctly implements the admin-only posts permission check, preventing non-admin users from creating posts in admin-restricted groups. The implementation properly retrieves group metadata and admin information, verifies the user's admin status, and provides a clear user feedback message.

The early return pattern with Future.value(null) is a clean approach for permission-based flow control.

lib/router/group/group_detail_widget.dart (1)

324-341: Implemented UI logic for admin-only posts feature.

This change correctly integrates with the admin-only posts feature by conditionally displaying the "Add Post" floating action button based on user permissions. The implementation properly checks if:

  1. The current tab is the Posts tab
  2. The group has admin-only posts enabled
  3. The current user has admin privileges

This ensures that only users with appropriate permissions can see the action button, which aligns well with the permission model implemented in editor_widget.dart.

packages/nostr_sdk/lib/nip29/group_metadata.dart (5)

19-20: Well-documented new feature!

The comment clearly explains the purpose of the adminOnlyPosts property - restricting announcements to admins while still allowing all members to chat.


33-33: Good constructor parameter addition.

Parameter is properly added to the constructor, maintaining consistency with other boolean properties.


45-45: Consistent state variable declaration.

The local variable follows the same pattern as other boolean properties in the method.


60-63: Well-implemented tag handling.

The logic for handling the adminOnlyPosts and memberPosts tags follows the same pattern as other boolean properties, maintaining consistency throughout the codebase.


99-99: Proper parameter passing.

The adminOnlyPosts property is correctly included in the constructor call, completing the implementation.

ios/Podfile (2)

36-37: Simplified dependency management approach.

Replacing custom filtering with flutter_install_all_ios_pods is a cleaner approach that leverages Flutter's built-in dependency management.


41-47:

Details

✅ Verification successful

Better approach to disabling Sentry.

Using preprocessor definitions to disable Sentry at build time is more maintainable than filtering out dependencies during installation.


🏁 Script executed:

#!/bin/bash
# Verify that Info.plist also has the DisableSentry flag set to align with this change

grep -A 1 "DisableSentry" ios/Runner/Info.plist

Length of output: 82


Sentry disabling is consistently implemented

The Podfile update correctly adds the DISABLE_SENTRY=1 preprocessor definition, and our verification confirms that the Info.plist file already includes <key>DisableSentry</key> with a corresponding <true/> value. This approach effectively disables Sentry at build time and is more maintainable compared to filtering out dependencies during installation.

packages/nostr_sdk/lib/nip29/nip29.dart (2)

22-23: Properly extended method signature.

The adminOnlyPosts parameter is correctly added as an optional parameter, and the null check is appropriately updated to include it.


43-49: Consistent implementation for new feature.

The handling of the adminOnlyPosts parameter follows the same pattern as the existing boolean parameters, adding appropriate tags based on the value. This maintains code consistency.

lib/router/group/group_edit_widget.dart (5)

35-35: Good state variable initialization.

The adminOnlyPostsValue is properly initialized to false as a default value, consistent with other boolean properties.


67-69: Proper state variable update from metadata.

The implementation correctly initializes the state variable from the group metadata if available, following the same pattern as other boolean properties.


217-232: Well-designed UI component for the new feature.

The switch tile for admin-only posts follows the same design pattern as other toggle options, providing a clear title and contextual description based on the current state.


647-649: Complete implementation for status updates.

The code correctly checks if the adminOnlyPosts value has changed before updating the status, which prevents unnecessary API calls.


652-652: Proper method call with new parameter.

The editStatus method is called with all three parameters, ensuring the admin-only posts setting is saved along with other group settings.

lib/router/group/create_community_dialog.dart (6)

131-137: Improved state management prevents multiple submissions

The introduction of the _isProcessing flag and class-level _communityNameController is a great improvement for preventing race conditions and managing widget state properly.


142-152: Well-implemented processing state with AbsorbPointer

Using AbsorbPointer is an excellent way to prevent user interactions during processing while still showing the UI. This provides better feedback than disabling individual controls.


197-248: Good separation of concerns with dedicated view builder

Extracting the community creation UI into a dedicated method improves code organization and maintainability. The method has a clear structure with proper spacing and component organization.


363-409: Robust implementation of community creation with proper error handling

The updated method includes several important improvements:

  • Multiple submission prevention with the _isProcessing flag
  • Input validation for empty community names
  • Improved error handling with meaningful feedback via SnackBar
  • Better navigation flow after community creation

412-428: Consistent state management in join community method

The join method follows the same pattern as the create method, preventing multiple submissions and properly managing state on failure. This consistency helps prevent race conditions.


438-442: Proper resource management with controller disposal

Adding the dispose() method to clean up the TextEditingController is critical to prevent memory leaks. This is an important best practice in Flutter.

lib/router/group/invite_people_widget.dart (4)

12-12: Appropriate refactoring to StatelessWidget

Converting this widget from StatefulWidget to StatelessWidget is appropriate since the component no longer needs to manage internal state changes after initial build.


69-81: Robust invite link generation with appropriate error handling

The synchronous approach to link generation with fallback handling is cleaner than the previous asynchronous pattern. The empty check provides additional safety.


130-147: Good visual feedback with success indicator

The addition of a visual success indicator enhances the user experience by providing clear feedback about the successful community creation.


252-302: Excellent component extraction for reusability

The _buildSetupStep method creates a reusable UI component that maintains consistency across the different setup steps. This follows good DRY principles and improves maintainability.

lib/l10n/intl_en.arb (2)

405-407: Well-labeled strings for admin-only posts feature

The new localization strings clearly explain the admin-only posts feature, which aligns with the PR objective of implementing this functionality.


411-421: Comprehensive localization for the community creation flow

The new strings provide good coverage for the redesigned community creation and invitation process, ensuring a consistent user experience across different languages.

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