store_it 1.0.0 copy "store_it: ^1.0.0" to clipboard
store_it: ^1.0.0 copied to clipboard

A high-performance, SQLite-backed key-value store for Flutter with native TTL and background maintenance.

example/lib/main.dart

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

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

  // Initialize StoreIT with a 5-second background purge interval for demo purposes.
  // In a real app, 30-60 seconds is usually sufficient.
  await StoreIT.init(purgeIntervalSeconds: 5);

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'StoreIT Advanced Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo, brightness: Brightness.light),
        useMaterial3: true,
      ),
      home: const AdvancedStoreITDemo(),
    );
  }
}

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

  @override
  State<AdvancedStoreITDemo> createState() => _AdvancedStoreITDemoState();
}

class _AdvancedStoreITDemoState extends State<AdvancedStoreITDemo> {
  String _lastEvent = 'System Ready';
  int _purgeCount = 0;

  @override
  void initState() {
    super.initState();
    // Monitor background maintenance
    StoreIT.onPurge = (count) {
      if (mounted) {
        setState(() {
          _purgeCount += count;
          _lastEvent = 'Evicted $count expired items';
        });
      }
    };
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('StoreIT Advanced'),
          bottom: const TabBar(
            tabs: [
              Tab(icon: Icon(Icons.timer), text: 'TTL Cache'),
              Tab(icon: Icon(Icons.person), text: 'JSON Profiles'),
              Tab(icon: Icon(Icons.list), text: 'Lists/Logs'),
            ],
          ),
        ),
        body: const TabBarView(
          children: [
            TTLCacheView(),
            JsonProfileView(),
            ActivityLogView(),
          ],
        ),
        bottomNavigationBar: Container(
          color: Theme.of(context).colorScheme.surfaceVariant,
          padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
          child: Row(
            children: [
              const Icon(Icons.analytics_outlined, size: 16),
              const SizedBox(width: 8),
              Expanded(
                child: Text(
                  'Event: $_lastEvent | Total Purged: $_purgeCount',
                  style: Theme.of(context).textTheme.bodySmall,
                ),
              ),
              TextButton(
                onPressed: () => StoreIT.flush().then((_) => setState(() {})),
                child: const Text('FLUSH ALL', style: TextStyle(color: Colors.red, fontSize: 10)),
              )
            ],
          ),
        ),
      ),
    );
  }
}

// ─── 1. TTL CACHE VIEW ───────────────────────────────────────────────────────

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

  @override
  State<TTLCacheView> createState() => _TTLCacheViewState();
}

class _TTLCacheViewState extends State<TTLCacheView> {
  final _keyCtrl = TextEditingController();
  final _valCtrl = TextEditingController();
  List<String> _keys = [];

  void _refresh() async {
    final k = await StoreIT.keys(prefix: 'cache:');
    if (mounted) setState(() => _keys = k);
  }

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

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16),
      child: Column(
        children: [
          TextField(controller: _keyCtrl, decoration: const InputDecoration(labelText: 'Key (without prefix)')),
          TextField(controller: _valCtrl, decoration: const InputDecoration(labelText: 'Value')),
          const SizedBox(height: 10),
          Row(
            children: [
              Expanded(
                child: ElevatedButton(
                  onPressed: () async {
                    if (_keyCtrl.text.isEmpty) return;
                    await StoreIT.set('cache:${_keyCtrl.text}', _valCtrl.text, ttlSeconds: 1500);
                    _keyCtrl.clear(); _valCtrl.clear();
                    _refresh();
                  },
                  child: const Text('Set with 1500s TTL'),
                ),
              ),
            ],
          ),
          const Divider(height: 32),
          Expanded(
            child: ListView.builder(
              itemCount: _keys.length,
              itemBuilder: (context, i) {
                final k = _keys[i];
                return FutureBuilder<List<dynamic>>(
                  future: Future.wait([StoreIT.ttl(k), StoreIT.get(k)]),
                  builder: (context, snap) {
                    final ttl = snap.data?[0];
                    final val = snap.data?[1];
                    return ListTile(
                      title: Text(k, style: const TextStyle(fontWeight: FontWeight.bold)),
                      subtitle: Text('Value: ${val ?? "N/A"}\nTTL: ${ttl ?? "∞"}s'),
                      isThreeLine: true,
                      trailing: IconButton(icon: const Icon(Icons.refresh), onPressed: _refresh),
                    );
                  },
                );
              },
            ),
          )
        ],
      ),
    );
  }
}

// ─── 2. JSON PROFILE VIEW (MERGE DEMO) ──────────────────────────────────────

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

  @override
  State<JsonProfileView> createState() => _JsonProfileViewState();
}

class _JsonProfileViewState extends State<JsonProfileView> {
  final String _userKey = 'user:profile:101';
  Map<String, dynamic> _data = {};

  void _load() async {
    final d = await StoreIT.jsonGet(_userKey);
    if (mounted) setState(() => _data = (d as Map?)?.cast<String, dynamic>() ?? {});
  }

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

  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: const EdgeInsets.all(16),
      children: [
        const Text('Atomic JSON Merge Demo', style: TextStyle(fontWeight: FontWeight.bold)),
        const Text('Update specific fields without reading the whole object.', style: TextStyle(fontSize: 12)),
        const SizedBox(height: 20),
        Card(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('User Profile (ID: 101)', style: Theme.of(context).textTheme.titleMedium),
                const Divider(),
                Text('Name: ${_data['name'] ?? 'N/A'}'),
                Text('Role: ${_data['role'] ?? 'N/A'}'),
                Text('Status: ${_data['status'] ?? 'N/A'}'),
                Text('Theme: ${_data['settings']?['theme'] ?? 'N/A'}'),
              ],
            ),
          ),
        ),
        const SizedBox(height: 20),
        Wrap(
          spacing: 8,
          children: [
            ActionChip(
              label: const Text('Set Initial'),
              onPressed: () async {
                await StoreIT.jsonSet(_userKey, {
                  'name': 'John Doe',
                  'role': 'Admin',
                  'status': 'Online',
                  'settings': {'theme': 'dark'}
                });
                _load();
              },
            ),
            ActionChip(
              label: const Text('Promote to Manager'),
              onPressed: () async {
                await StoreIT.jsonMerge(_userKey, {'role': 'Manager'});
                _load();
              },
            ),
            ActionChip(
              label: const Text('Go Offline'),
              onPressed: () async {
                await StoreIT.jsonMerge(_userKey, {'status': 'Offline'});
                _load();
              },
            ),
          ],
        )
      ],
    );
  }
}

// ─── 3. ACTIVITY LOG VIEW (LIST DEMO) ───────────────────────────────────────

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

  @override
  State<ActivityLogView> createState() => _ActivityLogViewState();
}

class _ActivityLogViewState extends State<ActivityLogView> {
  final String _logKey = 'logs:activity';
  List<String> _logs = [];

  void _load() async {
    final l = await StoreIT.listGet(_logKey);
    if (mounted) setState(() => _logs = l ?? []);
  }

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(16),
          child: Row(
            children: [
              Expanded(
                child: ElevatedButton.icon(
                  onPressed: () async {
                    final timestamp = DateTime.now().toIso8601String().split('T').last.substring(0, 8);
                    await StoreIT.listAppend(_logKey, ['Action at $timestamp']);
                    _load();
                  },
                  icon: const Icon(Icons.add),
                  label: const Text('Append Log Entry'),
                ),
              ),
              const SizedBox(width: 8),
              IconButton(
                onPressed: () async {
                  await StoreIT.delete(_logKey);
                  _load();
                },
                icon: const Icon(Icons.clear_all, color: Colors.red),
              )
            ],
          ),
        ),
        const Divider(height: 1),
        Expanded(
          child: ListView.separated(
            itemCount: _logs.length,
            separatorBuilder: (_, __) => const Divider(height: 1),
            itemBuilder: (context, i) => ListTile(
              leading: CircleAvatar(child: Text('${i+1}', style: const TextStyle(fontSize: 10))),
              title: Text(_logs[i]),
              dense: true,
            ),
          ),
        )
      ],
    );
  }
}
0
likes
160
points
89
downloads

Documentation

API reference

Publisher

verified publishernahid.info.bd

Weekly Downloads

A high-performance, SQLite-backed key-value store for Flutter with native TTL and background maintenance.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, path, sqflite

More

Packages that depend on store_it