scaffold 1.1.0 copy "scaffold: ^1.1.0" to clipboard
scaffold: ^1.1.0 copied to clipboard

Provides a reusable development scaffold for common features.

example/lib/main.dart

import 'dart:io';

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

void main() {
  runApp(const MyApp());
}

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends BaseState<MyApp, _MyAppViewModel> {
  Uri? _treeUri;
  Uri? _subTreeUri;
  final _documents = <File>[];

  @override
  _MyAppViewModel newViewModel() => _MyAppViewModel(this);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      themeMode: ThemeMode.system,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: FutureWidget<void>(
          future: asyncInitializeFuture,
          waitingBuilder: (context) => const Center(child: CircularProgressIndicator()),
          builder: (context, _) => ListView(
            children: <Widget>[
              _buildHeader("DocumentManagerPlugin"),
              EasyListTile(
                nameText: "openDocumentTree()",
                descriptionText: _treeUri?.toString(),
                onTap: () {
                  DocumentManagerPlugin.openDocumentTree(initialLocation: _treeUri).then((value) {
                    setState(() {
                      _treeUri = value;
                    });
                  });
                },
              ),
              EasyListTile(
                nameText: "createSubTreeUri()",
                descriptionText: _subTreeUri?.toString(),
                onTap: () {
                  final treeUri = _treeUri;
                  if (treeUri == null) {
                    Toast.showShort(context, "First open a document tree");
                    return;
                  }
                  DocumentManagerPlugin.createSubTreeUri(treeUri: treeUri, displayName: "TEST").then((value) {
                    setState(() {
                      _subTreeUri = value;
                    });
                  });
                },
              ),
              EasyListTile(
                nameText: "import()",
                onTap: () {
                  DocumentManagerPlugin.import(
                    allowsMultipleSelection: true,
                  ).then((files) {
                    _documents.clear();
                    _documents.addAll(files);
                    setStateIfMounted();
                  }, onError: (e, s) {
                    DefaultLogger.error("import() > failed", e, s);
                    Toast.showLong(context, "import() > $e");
                  });
                },
              ),
              if (_documents.isNotEmpty) _buildDivider(),
              if (_documents.isNotEmpty)
                EasyListTile(
                  nameText: "export()",
                  onTap: () {
                    DocumentManagerPlugin.export(
                      files: _documents,
                    ).then((value) {
                      _documents.clear();
                      Toast.showLong(context, "export() > $value");
                      setStateIfMounted();
                    }, onError: (e, s) {
                      DefaultLogger.error("export() > failed", e, s);
                      Toast.showLong(context, "export() > $e");
                    });
                  },
                ),
              if (_documents.isNotEmpty) _buildDivider(),
              for (var i = 0; i < _documents.length; i++)
                EasyListTile(
                  leading: Text(
                    "${i + 1}",
                    style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                  ),
                  nameText: _documents[i].path,
                ),
              _buildHeader("GallerySavePlugin"),
              EasyListTile(
                nameText: "saveImage()",
                onTap: () {
                  GallerySavePlugin.requestSavePermission().then((value) {
                    if (value) {
                      GallerySavePlugin.saveImage(_documents.first).then((_) {
                        Toast.showLong(context, "saveImage() > success");
                        setStateIfMounted();
                      }, onError: (e, s) {
                        DefaultLogger.error("saveImage() > failed", e, s);
                        Toast.showLong(context, "saveImage() > $e");
                      });
                    } else {
                      Toast.showLong(context, "no permission");
                    }
                  }, onError: (e, s) {
                    DefaultLogger.error("saveImage() > failed", e, s);
                    Toast.showLong(context, "saveImage() > $e");
                  });
                },
              ),
              EasyListTile(
                nameText: "saveVideo()",
                onTap: () {
                  GallerySavePlugin.requestSavePermission().then((value) {
                    if (value) {
                      GallerySavePlugin.saveVideo(_documents.first).then((_) {
                        Toast.showLong(context, "saveVideo() > success");
                        setStateIfMounted();
                      }, onError: (e, s) {
                        DefaultLogger.error("saveVideo() > failed", e, s);
                        Toast.showLong(context, "saveVideo() > $e");
                      });
                    } else {
                      Toast.showLong(context, "no permission");
                    }
                  }, onError: (e, s) {
                    DefaultLogger.error("saveVideo() > failed", e, s);
                    Toast.showLong(context, "saveVideo() > $e");
                  });
                },
              ),
              _buildHeader("SystemClockPlugin"),
              EasyListTile(
                nameText: "elapsedRealtime()",
                descriptionText: "Returns duration since boot, including time spent in sleep.",
                onTap: () {
                  SystemClockPlugin.elapsedRealtime().then((value) {
                    DefaultLogger.info("elapsedRealtime() > ${value.inHours}h${value.inMinutes % 60}m${value.inSeconds % 60}s");
                    Toast.showLong(context, "elapsedRealtime() > ${value.inHours}h${value.inMinutes % 60}m${value.inSeconds % 60}s");
                  }, onError: (e, s) {
                    DefaultLogger.error("elapsedRealtime() > failed", e, s);
                    Toast.showLong(context, "elapsedRealtime() > $e");
                  });
                },
              ),
              _buildDivider(),
              EasyListTile(
                nameText: "uptime()",
                descriptionText: "Returns duration since boot, not counting time spent in deep sleep.",
                onTap: () {
                  SystemClockPlugin.uptime().then((value) {
                    DefaultLogger.info("uptime() > ${value.inHours}h${value.inMinutes % 60}m${value.inSeconds % 60}s");
                    Toast.showLong(context, "uptime() > ${value.inHours}h${value.inMinutes % 60}m${value.inSeconds % 60}s");
                  }, onError: (e, s) {
                    DefaultLogger.error("uptime() > failed", e, s);
                    Toast.showLong(context, "uptime() > $e");
                  });
                },
              ),
              if (Platform.isAndroid)
                Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    _buildHeader("AndroidDomainVerificationPlugin"),
                    EasyListTile(
                      nameText: "isLinkHandlingAllowed()",
                      onTap: () {
                        AndroidDomainVerificationPlugin.isLinkHandlingAllowed().then((value) {
                          DefaultLogger.info("isLinkHandlingAllowed() > $value");
                          Toast.showLong(context, "isLinkHandlingAllowed() > $value");
                        }, onError: (e, s) {
                          DefaultLogger.error("isLinkHandlingAllowed() > failed", e, s);
                          Toast.showLong(context, "isLinkHandlingAllowed() > $e");
                        });
                      },
                    ),
                    _buildDivider(),
                    EasyListTile(
                      nameText: "getHostToStateMap()",
                      onTap: () {
                        AndroidDomainVerificationPlugin.getHostToStateMap().then((value) {
                          DefaultLogger.info("getHostToStateMap() > $value");
                          Toast.showLong(context, "getHostToStateMap() > $value");
                        }, onError: (e, s) {
                          DefaultLogger.error("getHostToStateMap() > failed", e, s);
                          Toast.showLong(context, "getHostToStateMap() > $e");
                        });
                      },
                    ),
                    _buildDivider(),
                    EasyListTile(
                      nameText: "toSettings()",
                      onTap: () {
                        AndroidDomainVerificationPlugin.toSettings().then((_) {
                          Toast.showLong(context, "toSettings() > success");
                        }, onError: (e, s) {
                          DefaultLogger.error("toSettings() > failed", e, s);
                          Toast.showLong(context, "toSettings() > $e");
                        });
                      },
                    ),
                  ],
                ),
              _buildHeader("AndroidDownloadPlugin"),
              EasyListTile(
                nameText: "download()",
                onTap: () {
                  defaultLoadingDialog.resetMetadata();
                  defaultLoadingDialog.show(context);
                  AndroidDownloadPlugin.enqueue(
                    uri: Uri.parse("https://www.pexels.com/download/video/27935830/"),
                    destination: AndroidDownloadPlugin.kDestinationExternalPublicDir,
                    filename: "example.mp4",
                    description: "Test file download",
                  ).then((downloadId) {
                    int i = 0;
                    AndroidDownloadPlugin.waitDownload(downloadId, interval: const Duration(milliseconds: 256), onProgress: (downloadInfo) {
                      final totalSize = downloadInfo.totalSize;
                      final bytesSoFar = downloadInfo.bytesSoFar;
                      if (totalSize != null && totalSize > 0 && bytesSoFar != null && bytesSoFar > 0) {
                        defaultLoadingDialog.progress = bytesSoFar / totalSize;
                      }
                      defaultLoadingDialog.message = "${++i} -> $downloadInfo";
                    }).then((value) {
                      defaultLoadingDialog.dismiss();
                      DefaultLogger.info("download() > $value");
                      Toast.showLong(context, "download() > $value");
                    }, onError: (e) {
                      defaultLoadingDialog.dismiss();
                    });
                  }, onError: (e) {
                    defaultLoadingDialog.dismiss();
                  });
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildHeader(String name) => Container(
        width: double.infinity,
        color: Theme.of(context).colorScheme.surfaceVariant,
        padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16),
        alignment: AlignmentDirectional.centerStart,
        child: Text(
          name,
          style: TextStyle(
            fontSize: 16,
            fontWeight: FontWeight.bold,
            color: Theme.of(context).colorScheme.onSurfaceVariant,
          ),
        ),
      );

  Widget _buildDivider() => const Divider(height: 1);
}

class _MyAppViewModel extends BaseViewModel<MyApp> {
  _MyAppViewModel(super.state);
}