remote_cache_sync 0.2.1 copy "remote_cache_sync: ^0.2.1" to clipboard
remote_cache_sync: ^0.2.1 copied to clipboard

Remote cache synchronization toolkit for Flutter with Appwrite, PocketBase, and Supabase adapters.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:remote_cache_sync/remote_cache_sync.dart';
import 'backend_config.dart';

void main() => runApp(const MyApp());

// Model `Record` is defined in backend_config.dart

class MyApp extends StatefulWidget {
  const MyApp({super.key});
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late final DriftLocalStore<Record, String> local;
  late final LocalDriftDatabase db;
  late final RemoteStore<Record, String> remote;
  late final SimpleSyncOrchestrator<Record, String> orchestrator;

  final scope = const SyncScope('records', {'userId': 'u1'});
  List<Record> items = const [];
  int _cacheSize = 0; // in bytes
  int? _cacheLimit; // null means unlimited

  @override
  void initState() {
    super.initState();
    // Initialize persistent Drift-backed local store
    db = LocalDriftDatabase();
    local = DriftLocalStore<Record, String>(
      db: db,
      idOf: (r) => r.id,
      idToString: (s) => s,
      idFromString: (s) => s,
      toJson: (r) => {
        'id': r.id,
        'title': r.title,
        'updatedAt': r.updatedAt.toIso8601String(),
      },
      fromJson: (m) => Record(
        id: m['id'] as String,
        title: m['title'] as String,
        updatedAt: DateTime.parse(m['updatedAt'] as String).toUtc(),
      ),
    );
    remote = createRemoteStore();
    orchestrator = SimpleSyncOrchestrator<Record, String>(
      local: local,
      remote: remote,
      resolver: const LastWriteWinsResolver<Record>(),
      idOf: (r) => r.id,
    );
    _refresh();
    _refreshCacheMeta();
  }

  Future<void> _refresh() async {
    final list = await local.query(scope);
    setState(() => items = list);
  }

  Future<void> _add() async {
    final now = DateTime.now().toUtc();
    final id = 'r_${now.microsecondsSinceEpoch}';
    final rec = Record(
      id: id,
      title: 'Item ${items.length + 1}',
      updatedAt: now,
    );
    await orchestrator.enqueueCreate(scope, id, rec);
    await _refresh();
    await _refreshCacheMeta();
  }

  Future<void> _updateFirst() async {
    if (items.isEmpty) return;
    final first = items.first;
    final rec = Record(
      id: first.id,
      title: '${first.title}*',
      updatedAt: DateTime.now().toUtc(),
    );
    await orchestrator.enqueueUpdate(scope, first.id, rec);
    await _refresh();
    await _refreshCacheMeta();
  }

  Future<void> _deleteFirst() async {
    if (items.isEmpty) return;
    await orchestrator.enqueueDelete(scope, items.first.id);
    await _refresh();
    await _refreshCacheMeta();
  }

  Future<void> _sync() async {
    await orchestrator.synchronize(scope);
    await _refresh();
    await _refreshCacheMeta();
  }

  // Cache management helpers
  Future<void> _refreshCacheMeta() async {
    final size = await local.approxCacheSizeBytes();
    final limit = await local.getCacheSizeLimitBytes();
    if (mounted) {
      setState(() {
        _cacheSize = size;
        _cacheLimit = limit;
      });
    }
  }

  Future<void> _setLimit(int? bytes) async {
    await local.setCacheSizeLimitBytes(bytes);
    await _refresh();
    await _refreshCacheMeta();
  }

  Future<void> _clearScope() async {
    await local.clearCache(scope: scope);
    await _refresh();
    await _refreshCacheMeta();
  }

  Future<void> _clearAll() async {
    await local.clearCache();
    await _refresh();
    await _refreshCacheMeta();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Remote Cache Sync Demo')),
        body: Column(
          children: [
            OverflowBar(
              alignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(onPressed: _add, child: const Text('Add')),
                ElevatedButton(
                  onPressed: _updateFirst,
                  child: const Text('Update First'),
                ),
                ElevatedButton(
                  onPressed: _deleteFirst,
                  child: const Text('Delete First'),
                ),
                ElevatedButton(onPressed: _sync, child: const Text('Sync')),
              ],
            ),
            const Divider(),
            Padding(
              padding: const EdgeInsets.symmetric(
                horizontal: 12.0,
                vertical: 8.0,
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('Cache size: \\${_cacheSize} B'),
                  Text('Limit: \\${_cacheLimit?.toString() ?? 'unlimited'}'),
                  const SizedBox(height: 8),
                  OverflowBar(
                    alignment: MainAxisAlignment.start,
                    spacing: 8,
                    children: [
                      ElevatedButton(
                        onPressed: () => _setLimit(200 * 1024),
                        child: const Text('Set 200KB Limit'),
                      ),
                      ElevatedButton(
                        onPressed: () => _setLimit(null),
                        child: const Text('Remove Limit'),
                      ),
                      ElevatedButton(
                        onPressed: _clearScope,
                        child: const Text('Clear Scope'),
                      ),
                      ElevatedButton(
                        onPressed: _clearAll,
                        child: const Text('Clear All'),
                      ),
                    ],
                  ),
                ],
              ),
            ),
            Expanded(
              child: ListView.builder(
                itemCount: items.length,
                itemBuilder: (context, index) {
                  final r = items[index];
                  return ListTile(
                    title: Text(r.title),
                    subtitle: Text(
                      '${r.id} | ${r.updatedAt.toIso8601String()}',
                    ),
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}
1
likes
150
points
345
downloads

Publisher

unverified uploader

Weekly Downloads

Remote cache synchronization toolkit for Flutter with Appwrite, PocketBase, and Supabase adapters.

Homepage
Repository (GitHub)
View/report issues

Topics

#cache #sync #drift #wasm #flutter-web

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

appwrite, drift, drift_flutter, flutter, path_provider, plugin_platform_interface, pocketbase, supabase_flutter

More

Packages that depend on remote_cache_sync