datalocal 2.0.0-dev.1 copy "datalocal: ^2.0.0-dev.1" to clipboard
datalocal: ^2.0.0-dev.1 copied to clipboard

Encrypted document-style local persistence for Flutter with queries, reactive snapshots, migration, and recoverable SharedPreferences storage.

example/lib/main.dart

import 'dart:async';

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

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const DataLocalExampleApp());
}

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

  @override
  Widget build(BuildContext context) => MaterialApp(
    title: 'DataLocal 2 Example',
    theme: ThemeData(
      colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
      useMaterial3: true,
    ),
    home: const NotesPage(),
  );
}

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

  @override
  State<NotesPage> createState() => _NotesPageState();
}

class _NotesPageState extends State<NotesPage> {
  final _controller = TextEditingController();
  DataLocalDatabase? _database;
  DataLocalCollection<Map<String, Object?>>? _notes;
  Object? _initializationError;

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

  Future<void> _initialize() async {
    try {
      const databaseName = 'datalocal-v2-example';
      final keys = DataLocalSecureStorageKeyProvider(
        databaseName: databaseName,
      );
      final database = await DataLocalDatabase.open(
        name: databaseName,
        storage: DataLocalSharedPreferencesAsyncStorage(),
        encryption: DataLocalAesGcmEncryptionProvider(keyProvider: keys),
      );
      if (!mounted) {
        await database.close();
        return;
      }
      setState(() {
        _database = database;
        _notes = database.mapCollection('notes');
      });
    } catch (error) {
      if (mounted) {
        setState(() => _initializationError = error);
      }
    }
  }

  Future<void> _addNote() async {
    final title = _controller.text.trim();
    if (title.isEmpty) return;
    await _notes!.insert(<String, Object?>{'title': title});
    _controller.clear();
  }

  @override
  void dispose() {
    _controller.dispose();
    final database = _database;
    if (database != null) {
      unawaited(database.close());
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final error = _initializationError;
    if (error != null) {
      return Scaffold(
        appBar: AppBar(title: const Text('DataLocal 2 Example')),
        body: Center(child: Text('Initialization failed: $error')),
      );
    }
    final notes = _notes;
    if (notes == null) {
      return const Scaffold(body: Center(child: CircularProgressIndicator()));
    }
    return Scaffold(
      appBar: AppBar(title: const Text('DataLocal 2 Example')),
      body: Column(
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(16),
            child: Row(
              children: <Widget>[
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: const InputDecoration(
                      labelText: 'Encrypted local note',
                    ),
                    onSubmitted: (_) => _addNote(),
                  ),
                ),
                IconButton(
                  tooltip: 'Add note',
                  onPressed: _addNote,
                  icon: const Icon(Icons.add),
                ),
              ],
            ),
          ),
          Expanded(
            child: StreamBuilder<DataLocalQuerySnapshot<Map<String, Object?>>>(
              stream: notes.query().orderBy('title').watch(),
              builder: (context, snapshot) {
                final documents =
                    snapshot.data?.documents ??
                    const <DataLocalDocument<Map<String, Object?>>>[];
                if (documents.isEmpty) {
                  return const Center(child: Text('No notes yet'));
                }
                return ListView.builder(
                  itemCount: documents.length,
                  itemBuilder: (context, index) {
                    final document = documents[index];
                    return ListTile(
                      title: Text(document.data['title']! as String),
                      subtitle: Text(
                        'revision ${document.revision} · ${document.id}',
                      ),
                      trailing: IconButton(
                        tooltip: 'Delete note',
                        onPressed: () => notes.delete(document.id),
                        icon: const Icon(Icons.delete_outline),
                      ),
                    );
                  },
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}
4
likes
0
points
474
downloads

Publisher

verified publisherlamun.my.id

Weekly Downloads

Encrypted document-style local persistence for Flutter with queries, reactive snapshots, migration, and recoverable SharedPreferences storage.

Repository (GitHub)
View/report issues

Topics

#database #encryption #local-storage #persistence #shared-preferences

License

unknown (license)

Dependencies

collection, flutter, flutter_secure_storage, intl, pointycastle, shared_preferences

More

Packages that depend on datalocal