zeytin_state 0.0.1 copy "zeytin_state: ^0.0.1" to clipboard
zeytin_state: ^0.0.1 copied to clipboard

A lightning-fast, reactive state management solution built strictly for ZeytinX.

Zeytin State ๐Ÿซ’โšก #

Developed with love by JeaFriday!๐Ÿ’š๐Ÿซ’

Support me

GitHub Pub.dev LinkedIn Telegram

A lightning-fast, reactive state management solution built strictly for ZeytinX.

Say goodbye to manual setState, Riverpod, or GetX if your app heavily relies on local storage. Zeytin State bridges the gap between your ZeytinX database and your Flutter UI.

When your database changes, your UI changes. Automatically. Instantly.

๐ŸŒŸ Why Zeytin State? #

  • Zero Manual Updates: You never have to manually update your UI state. Just write to your database (coreDB.update()), and ZeytinSync will automatically catch the background stream and rebuild the exact widget listening to that specific tag.
  • Smart Rebuilds: It compares the old and new data. If the data hasn't actually changed, it aborts the rebuild, saving you precious FPS.
  • Auto Garbage Collection: Built-in safeguards against memory leaks. If a widget dies, Zeytin State safely ignores it.
  • Custom Model Mappers: Directly map raw database JSON (Map<String, dynamic>) to your complex Dart models effortlessly.

๐Ÿ“ฆ Installation #

Add it to your pubspec.yaml:

dependencies:
  zeytinx: ^??? # You already know the latest version!!
  zeytin_state: ^1.0.0

๐Ÿš€ Quick Start #

Here is a complete example of how to make a truly reactive UI.

1. Initialize the Engine #

Put this in your main.dart or your dependency injection setup (like GetIt).

import 'package:zeytinx/zeytinx.dart';
import 'package:zeytin_state/zeytin_state.dart';

late final ZeytinX coreDB;
late final ZeytinSync zeytinSync;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 1. Boot up the DB
  coreDB = ZeytinX("my_app_namespace", "main_truck");
  await coreDB.initialize("./my_local_db");

  // 2. Start the State Manager and let it listen to DB changes
  zeytinSync = ZeytinSync(coreDB);
  zeytinSync.init();

  runApp(const MyApp());
}

2. Bind and Listen in Your UI #

Use ZM<T> to declare your reactive variables, bind them in initState, and wrap your UI with ZMListener.

class ProfileScreen extends StatefulWidget {
  const ProfileScreen({super.key});

  @override
  State<ProfileScreen> createState() => _ProfileScreenState();
}

class _ProfileScreenState extends State<ProfileScreen> {
  // Define your reactive Zeytin Manager (ZM) variables
  late ZM<ZeytinXUserModel> myUser;
  late ZM<int> userScore;

  final String _userTag = "user_jea_123";

  @override
  void initState() {
    super.initState();

    // Bind a complex model using a mapper
    myUser = zeytinSync.bind<ZeytinXUserModel>(
      "users", // The Box
      _userTag, // The Tag
      ZeytinXUserModel.empty(), // Default loading value
      mapper: (dynamic data) {
        if (data == null) return ZeytinXUserModel.empty();
        return ZeytinXUserModel.fromJson(Map<String, dynamic>.from(data));
      },
    );

    // Bind a primitive type
    userScore = zeytinSync.bind<int>(
      "scores",
      _userTag,
      0,
      mapper: (dynamic data) => data?['score'] ?? 0,
    );
  }

  @override
  void dispose() {
    // CRITICAL: Always unbind and dispose to prevent memory leaks!
    zeytinSync.unbind("users", _userTag, myUser);
    zeytinSync.unbind("scores", _userTag, userScore);
    myUser.dispose();
    userScore.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Reactive Profile")),
      body: Center(
        // Wrap the part of your UI that needs to react
        child: ZMListener(
          listenables: [myUser, userScore],
          childBuilder: () {
            final user = myUser.value;
            final score = userScore.value;

            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text("Username: ${user.username}"),
                Text("Score: $score"),
              ],
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          // WE ONLY UPDATE THE DATABASE!
          // No setState(), no manual ZM updates.
          // ZeytinSync will instantly catch this and rebuild the ZMListener.
          await coreDB.update(
            box: "scores",
            tag: _userTag,
            value: (current) async {
              current["score"] = (current["score"] ?? 0) + 10;
              return current;
            },
          );
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

๐Ÿง  Core Concepts #

ZeytinSync #

The brain of the operation. It attaches itself to ZeytinX's observer stream. Whenever a PUT, UPDATE, BATCH, or DELETE operation happens, it looks up its registry and triggers the matching UI components.

ZM<T> (Zeytin Manager) #

This is your reactive container. It holds the current value of type T. It natively extends Flutter's ChangeNotifier.

bind<T>(box, tag, defaultValue, {mapper}) #

Tells the sync engine: "Hey, keep an eye on this Box and Tag. If it changes in the DB, fetch the new data, run it through my mapper, and update my ZM variable." It also performs an initial fetch so your UI populates immediately if the data already exists.

ZMListener #

A smart widget builder. Pass it a list of ZM variables, and it will only rebuild its childBuilder when those specific variables receive a change notification.

๐Ÿงน Memory Management #

Reactivity is powerful but can lead to memory leaks if neglected. Always unbind your ZM variables in your widget's dispose method.

Note: Even if you forget, Zeytin State has an internal garbage collector that sweeps disposed ZMs, but explicitly unbinding is the best practice for performance.


Developed with love by JeaFriday. Support Zeytin! ๐Ÿ’š

ZeytinState #

1
likes
150
points
0
downloads

Publisher

verified publisherjeafriday.com

Weekly Downloads

A lightning-fast, reactive state management solution built strictly for ZeytinX.

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

flutter, zeytinx

More

Packages that depend on zeytin_state