flutter_form_draft

Automatic form draft saving, restoration, versioning, and expiration for Flutter applications.

Support on Ko-fi

flutter_form_draft helps prevent data loss when users leave a form early, the app closes, or submission fails. It works with normal Flutter forms and does not require a specific state-management library.

Features

  • Automatic debounced draft saving
  • Draft restore workflows (automatic, askUser, manual, never)
  • Multiple drafts per form with user isolation
  • Draft expiration and cleanup
  • Schema migrations for evolving forms
  • Pluggable storage backends
  • Field adapters for TextEditingController and ValueNotifier
  • Built-in restore dialog, autosave indicator, and navigation protection
  • Checksum-based corruption detection

Installation

dependencies:
  flutter_form_draft: ^0.1.0

Quick start

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

final draftManager = DraftManager(
  storage: MemoryDraftStorage(),
);

final nameController = TextEditingController();
final emailController = TextEditingController();

final draftController = FormDraftController(
  fields: [
    TextControllerDraftField(key: 'name', controller: nameController),
    TextControllerDraftField(key: 'email', controller: emailController),
  ],
);

FormDraft<Map<String, dynamic>>(
  identity: const DraftIdentity(formId: 'contact_form'),
  manager: draftManager,
  controller: draftController,
  serializer: const MapDraftSerializer(),
  config: const DraftConfig(
    restoreMode: DraftRestoreMode.askUser,
    debounce: Duration(seconds: 1),
  ),
  child: Form(
    child: Column(
      children: [
        TextField(controller: nameController),
        TextField(controller: emailController),
      ],
    ),
  ),
);

Storage adapters

Adapter Best for Platforms
MemoryDraftStorage Tests, demos, temporary sessions All
SharedPreferencesDraftStorage Small non-sensitive drafts Mobile, web, desktop

SharedPreferences is not suitable for large payloads or sensitive data.

Restore strategies

const DraftConfig(
  restoreMode: DraftRestoreMode.askUser,
);

Use DraftRestoreDialog or provide your own onRestoreAvailable callback.

Multiple drafts

const identity = DraftIdentity(
  formId: 'invoice_form',
  draftId: 'invoice_123',
  userId: 'user_45',
);

Schema migrations

class PropertyDraftV1ToV2 extends DraftMigration {
  @override
  int get fromVersion => 1;

  @override
  int get toVersion => 2;

  @override
  Map<String, dynamic> migrate(Map<String, dynamic> oldData) {
    return {
      ...oldData,
      'propertyType': oldData['type'],
    }..remove('type');
  }
}

final manager = DraftManager(
  storage: MemoryDraftStorage(),
  migrationRegistry: DraftMigrationRegistry([
    PropertyDraftV1ToV2(),
  ]),
);

Example app

Run the bundled example:

cd example
flutter run

Security considerations

  • Do not store passwords or secrets in drafts unless excluded or encrypted
  • SharedPreferences is not secure storage
  • Encryption support is planned for 0.2.0

Roadmap

  • 0.2.0: File storage, encryption, lifecycle auto-save
  • 0.3.0: Retention policies, advanced diagnostics
  • 1.0.0: Stable public API

License

MIT — see LICENSE.

Libraries

flutter_form_draft
Automatic form draft saving, restoration, versioning, and expiration.