content: import 'package:flutter/foundation.dart';
  import 'package:flutter_riverpod/legacy.dart';
  
  /* SNIPPET START */
  
  // The state of our StateNotifier should be immutable.
  // We could also use packages like Freezed to help with the implementation.
  @immutable
  class Todo {
    const Todo({
      required this.id,
      required this.description,
      required this.completed,
    });
  
    // All properties should be `final` on our class.
    final String id;
    final String description;
    final bool completed;
  
    // Since Todo is immutable, we implement a method that allows cloning the
    // Todo with slightly different content.
    Todo copyWith({String? id, String? description, bool? completed}) {
      return Todo(
        id: id ?? this.id,
        description: description ?? this.description,
        completed: completed ?? this.completed,
      );
    }
  }
  
  // The StateNotifier class that will be passed to our StateNotifierProvider.
  // This class should not expose state outside of its "state" property, which means
  // no public getters/properties!
  // The public methods on this class will be what allow the UI to modify the state.
  class TodosNotifier extends StateNotifier<List<Todo>> {
    // We initialize the list of todos to an empty list
    TodosNotifier() : super([]);
  
    // Let's allow the UI to add todos.
    void addTodo(Todo todo) {
      // Since our state is immutable, we are not allowed to do `state.add(todo)`.
      // Instead, we should create a new list of todos which contains the previous
      // items and the new one.
      // Using Dart's spread operator here is helpful!
      state = [...state, todo];
      // No need to call "notifyListeners" or anything similar. Calling "state ="
      // will automatically rebuild the UI when necessary.
    }
  
    // Let's allow removing todos
    void removeTodo(String todoId) {
      // Again, our state is immutable. So we're making a new list instead of
      // changing the existing list.
      state = [
        for (final todo in state)
          if (todo.id != todoId) todo,
      ];
    }
  
    // Let's mark a todo as completed
    void toggle(String todoId) {
      state = [
        for (final todo in state)
          // we're marking only the matching todo as completed
          if (todo.id == todoId)
            // Once more, since our state is immutable, we need to make a copy
            // of the todo. We're using our `copyWith` method implemented before
            // to help with that.
            todo.copyWith(completed: !todo.completed)
          else
            // other todos are not modified
            todo,
      ];
    }
  }
  
  // Finally, we are using StateNotifierProvider to allow the UI to interact with
  // our TodosNotifier class.
  final todosProvider = StateNotifierProvider<TodosNotifier, List<Todo>>((ref) {
    return TodosNotifier();
  });
  