rate_popup

A Flutter package that provides a beautiful, customizable rating dialog to collect user feedback for your application. Each rating includes a score (1-5 stars), a comment, and an optional rater name.

Features

  • ✨ Beautiful, modern UI with RTL (Right-to-Left) support
  • ⭐ Interactive 5-star rating system
  • 💬 Text feedback with validation
  • 👤 Optional user name field
  • 📱 Responsive design (portrait and landscape support)
  • 🎨 Customizable theme integration
  • 🔄 Returns a structured Rating object
  • 📦 Easy integration with ObjectBox or any database

Installation

Add rate_popup to your pubspec.yaml:

dependencies:
  rate_popup:
    path: ../rate_popup  # For local package
    # OR for published package:
    # rate_popup: ^1.0.9

Then run:

flutter pub get

Basic Usage

1. Import the package

import 'package:flutter/material.dart';
import 'package:rate_popup/rate_popup.dart';

2. Show the rating dialog

void showRatingDialog(BuildContext context) async {
  final Rating? rating = await showDialog<Rating>(
    context: context,
    builder: (BuildContext context) {
      return RatingDialog(
        appName: 'YourAppName',
        primaryColor: Colors.blue,
        textFieldColor: Colors.grey[200]!,
        textColor: Colors.black,
        popupBackgroudColor: Colors.white,
        buttonTextColor: Colors.white,
      );
    },
  );

  if (rating != null) {
    print('Score: ${rating.score}');
    print('Comment: ${rating.comment}');
    print('Rater: ${rating.rater}');
    // Save to database or send to server
  }
}

3. Complete Example

import 'package:flutter/material.dart';
import 'package:rate_popup/rate_popup.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  void _showRatingDialog(BuildContext context) async {
    final Rating? rating = await showDialog<Rating>(
      context: context,
      barrierDismissible: false, // User must tap button to close
      builder: (BuildContext context) {
        return RatingDialog(
          appName: 'MyAwesomeApp',
          primaryColor: Colors.blue,
          textFieldColor: Colors.grey[200]!,
          textColor: Colors.black,
          popupBackgroudColor: Colors.white,
          buttonTextColor: Colors.white,
        );
      },
    );

    if (rating != null) {
      // Handle the rating (save to DB, send to server, etc.)
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(
            'Thanks for rating! Score: ${rating.score}',
          ),
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Rate Popup Demo')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => _showRatingDialog(context),
          child: Text('Rate App'),
        ),
      ),
    );
  }
}

Customization

You can customize the appearance of the rating dialog by changing the color parameters:

RatingDialog(
  appName: 'MyApp',
  primaryColor: Colors.purple,              // Button color and focused borders
  textFieldColor: Colors.grey[100]!,        // Text field background
  textColor: Colors.black87,                // Text color
  popupBackgroudColor: Colors.white,        // Dialog background
  buttonTextColor: Colors.white,            // Button text color
);

Example: Dark Theme

RatingDialog(
  appName: 'MyApp',
  primaryColor: Colors.deepPurple,
  textFieldColor: Colors.grey[800]!,
  textColor: Colors.white,
  popupBackgroudColor: Colors.grey[900]!,
  buttonTextColor: Colors.white,
);

API Reference

RatingDialog

The main widget for displaying the rating dialog.

Constructor Parameters:

  • appName (String, required): The name of your application to display in the dialog
  • primaryColor (Color, required): Primary color for buttons and focused borders
  • textFieldColor (Color, required): Background color for text input fields
  • textColor (Color, required): Color for text in the dialog
  • popupBackgroudColor (Color, required): Background color for the entire dialog
  • buttonTextColor (Color, required): Color for button text

Returns:

  • Rating?: A Rating object when the user submits, or null if the dialog is dismissed

Rating Class

The data model returned by the rating dialog.

Properties:

  • score (double): The star rating from 1.0 to 5.0
  • comment (String): The user's feedback text (required, max 500 characters)
  • rater (String): The name of the person rating (defaults to 'ללא שם' if not provided)

Saving to ObjectBox Database

Here's a complete guide to save ratings in an ObjectBox database in your project.

Step 1: Add ObjectBox Dependencies

Add to your project's pubspec.yaml:

dependencies:
  objectbox: ^4.0.3
  objectbox_flutter_libs: ^4.0.3

dev_dependencies:
  build_runner: ^2.4.13
  objectbox_generator: ^4.0.3

Step 2: Create ObjectBox Entity

Create a file lib/models/rating_entity.dart:

import 'package:objectbox/objectbox.dart';

@Entity()
class RatingEntity {
  @Id()
int id = 0;

double score;
String comment;
String rater;
  
  @Property(type: PropertyType.date)
  DateTime dateCreated;


RatingEntity({
required this.score,
required this.comment,
    required this.rater,
    required this.dateCreated,
  });

  // Factory constructor to create from rate_popup Rating object
  factory RatingEntity.fromRating(Rating rating) {
    return RatingEntity(
      score: rating.score,
      comment: rating.comment,
      rater: rating.rater,
      dateCreated: DateTime.now(),
    );
  }
}

Step 3: Generate ObjectBox Code

Run the build runner to generate ObjectBox code:

flutter pub run build_runner build

This will create the objectbox.g.dart file with all necessary code.

Note: Make sure you also have path_provider in your dependencies (for accessing the documents directory):

dependencies:
  path_provider: ^2.1.4

Step 4: Initialize ObjectBox Store

Create lib/services/database_service.dart:

import 'package:objectbox/objectbox.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import '../models/rating_entity.dart';
import '../objectbox.g.dart'; // Generated file

class DatabaseService {
  static DatabaseService? _instance;
  late final Store _store;
  late final Box<RatingEntity> _ratingBox;

  DatabaseService._create(this._store) {
    _ratingBox = _store.box<RatingEntity>();
  }

  static Future<DatabaseService> create() async {
    if (_instance != null) return _instance!;

    final docsDir = await getApplicationDocumentsDirectory();
    final store = await openStore(
      directory: path.join(docsDir.path, 'objectbox'),
    );

    _instance = DatabaseService._create(store);
    return _instance!;
  }

  // Save a rating to the database
  int saveRating(RatingEntity rating) {
    try {
      return _ratingBox.put(rating);
    } catch (e) {
      // Log error or handle it appropriately
      print('Error saving rating: $e');
      rethrow; // Re-throw to let caller handle it
    }
  }

  // Close the store when done
  void close() {
    _store.close();
  }
}

Step 5: Save Rating to Database

Here's how to use it in your app:

import 'package:flutter/material.dart';
import 'package:rate_popup/rate_popup.dart';
import 'services/database_service.dart';
import 'models/rating_entity.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Initialize database
  await DatabaseService.create();
  
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  Future<void> _showAndSaveRating(BuildContext context) async {
    // Show the rating dialog
    final Rating? rating = await showDialog<Rating>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return RatingDialog(
          appName: 'MyAwesomeApp',
          primaryColor: Colors.blue,
          textFieldColor: Colors.grey[200]!,
          textColor: Colors.black,
          popupBackgroudColor: Colors.white,
          buttonTextColor: Colors.white,
        );
      },
    );

    // If user submitted a rating, save it to database
    if (rating != null) {
      try {
        // Get database instance
        final dbService = await DatabaseService.create();
        
        // Convert Rating to RatingEntity
        final ratingEntity = RatingEntity.fromRating(rating);
        
        // Save to database
        final savedId = dbService.saveRating(ratingEntity);
        
        // Show confirmation
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Rating saved with ID: $savedId'),
            backgroundColor: Colors.green,
          ),
        );
      } catch (e) {
        // Show error message
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Failed to save rating: $e'),
            backgroundColor: Colors.red,
          ),
        );
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Rate Popup Demo')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => _showAndSaveRating(context),
          child: Text('Rate App'),
        ),
      ),
    );
  }
}

That's it!

The Rating object from the dialog is now saved in your ObjectBox database. The key steps are:

  1. Convert: Use RatingEntity.fromRating(rating) to convert the Rating object
  2. Save: Call dbService.saveRating(ratingEntity) to persist it
  3. Done: The rating is stored with an auto-generated ID and timestamp

Additional Features

Requirements

  • Flutter SDK: ^3.8.1
  • Dart SDK: ^3.8.1

Package Dependencies

  • cupertino_icons: ^1.0.8
  • material_design_icons_flutter: ^7.0.7296
  • path_provider: ^2.1.4
  • flat_buffers: ^23.5.26

Troubleshooting

Images not showing

Make sure the package assets are properly referenced. If using locally, the package should handle asset references automatically.

RTL text issues

The dialog automatically detects text direction. Hebrew and Arabic text will display RTL, while English displays LTR.

Dialog doesn't return value

Ensure you're using await showDialog<Rating>() and returning the rating with Navigator.of(context).pop(rating).

License

This package is provided under the MIT License. See LICENSE file for details.


Made with ❤️ for Flutter developers

Libraries

main
rate_popup