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

Page controllers, shells, and loading for Lemsa Flutter apps. Riverpod-free PageData mixins; AsyncView via a secondary export.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_page_kit/flutter_page_kit.dart';
import 'package:lemsa_core_kit/lemsa_core_kit.dart';

void main() {
  runApp(
    MaterialApp(
      scaffoldMessengerKey: _messengerKey,
      home: DemoPage(
        repo: FakeTaskRepo(),
        notices: ExampleNotices(_messengerKey),
        nav: ExampleNavigator(),
      ),
    ),
  );
}

final GlobalKey<ScaffoldMessengerState> _messengerKey =
    GlobalKey<ScaffoldMessengerState>();

/// Tiny ScaffoldMessenger stub (production impl → flutter_app_kit).
class ExampleNotices implements Notices {
  ExampleNotices(this._key);

  final GlobalKey<ScaffoldMessengerState> _key;

  void _show(String message) {
    if (message.isEmpty) {
      return;
    }
    _key.currentState
      ?..hideCurrentSnackBar()
      ..showSnackBar(SnackBar(content: Text(message)));
  }

  @override
  void info(String message) => _show(message);

  @override
  void warn(String message) => _show(message);

  @override
  void error(String message) => _show(message);

  @override
  void success(String message) => _show(message);

  @override
  void showFailure(AppFailure? failure) {
    if (failure == null || failure is CancelledFailure) {
      return;
    }
    // App would localize via failureText(failure); example shows type only.
    error(failure.runtimeType.toString());
  }
}

class ExampleNavigator implements PageNavigator {
  @override
  Future<R?> push<R>(Object route) async => null;

  @override
  void pop<R>([R? result]) {}

  @override
  void replaceAll(List<Object> routes) {}

  @override
  void replaceNamed(String path) {}

  @override
  bool get canPop => false;
}

class FakeTaskRepo {
  Future<void> save(String title) async {
    await Future<void>.delayed(const Duration(milliseconds: 200));
    if (title == 'fail') {
      throw const NetworkFailure();
    }
  }
}

class DemoPage extends StatefulWidget {
  const DemoPage({
    required this.repo,
    required this.notices,
    required this.nav,
    super.key,
  });

  final FakeTaskRepo repo;
  final Notices notices;
  final PageNavigator nav;

  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage>
    with PageData<DemoPage>, _DemoData {
  @override
  FakeTaskRepo get repo => widget.repo;

  @override
  Notices get notices => widget.notices;

  @override
  PageNavigator get nav => widget.nav;

  @override
  Widget build(BuildContext context) {
    return PageScope(
      data: this,
      child: FormPage(
        title: 'Demo task',
        actions: actions,
        failure: failure,
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: TextField(
            controller: title.controller,
            enabled: !busy.of('save'),
            decoration: InputDecoration(
              labelText: 'Title',
              helperText: 'Try "fail" to toast a NetworkFailure',
              errorText: showFieldErrors ? title.errorCode : null,
            ),
          ),
        ),
      ),
    );
  }
}

mixin _DemoData on State<DemoPage>, PageData<DemoPage> {
  FakeTaskRepo get repo;
  Notices get notices;
  PageNavigator get nav;

  late final FieldText title = text();

  @override
  List<Validatable> get validated => [title];

  List<PageAction> get actions => [
        PageAction(
          id: 'save',
          label: 'Save',
          busyKey: 'save',
          isPrimary: true,
          onPressed: submit,
        ),
      ];

  Future<void> submit() => run(
        key: 'save',
        action: () async {
          // Inline only — never notices.warn for invalid form.
          if (!await validateForm()) {
            return;
          }
          try {
            await repo.save(title.value);
            notices.success('Saved');
            nav.pop<void>();
          } on AppFailure catch (f) {
            notices.showFailure(f);
            rethrow;
          }
        },
      );
}
0
likes
160
points
48
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

Page controllers, shells, and loading for Lemsa Flutter apps. Riverpod-free PageData mixins; AsyncView via a secondary export.

Repository (GitHub)
View/report issues

Topics

#flutter #form #page #controllers

License

MIT (license)

Dependencies

flutter, flutter_riverpod, lemsa_core_kit, loading_indicator

More

Packages that depend on flutter_page_kit