TF-358 Implement deferred for all pages
This commit is contained in:
@@ -1,22 +1,21 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_navigation/src/routes/get_route.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart'
|
||||
if (dart.library.html) 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart' deferred as composer;
|
||||
import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_view.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
|
||||
import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_view.dart' deferred as destination_picker;
|
||||
import 'package:tmail_ui_user/features/email/presentation/email_view.dart' deferred as email;
|
||||
import 'package:tmail_ui_user/features/home/presentation/home_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/home/presentation/home_view.dart';
|
||||
import 'package:tmail_ui_user/features/login/presentation/login_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/login/presentation/login_view.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_view.dart';
|
||||
import 'package:tmail_ui_user/features/login/presentation/login_view.dart' deferred as login;
|
||||
import 'package:tmail_ui_user/features/mailbox_creator/presentation/mailbox_creator_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_creator/presentation/mailbox_creator_view.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_creator/presentation/mailbox_creator_view.dart' deferred as mailbox_creator;
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_view.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_view.dart' deferred as mailbox_dashBoard;
|
||||
import 'package:tmail_ui_user/features/session/presentation/session_page_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/session/presentation/session_view.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';
|
||||
import 'package:tmail_ui_user/features/session/presentation/session_view.dart' deferred as session;
|
||||
import 'package:tmail_ui_user/main/pages/deferred_widget.dart';
|
||||
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||
|
||||
class AppPages {
|
||||
@@ -27,39 +26,33 @@ class AppPages {
|
||||
binding: HomeBindings()),
|
||||
GetPage(
|
||||
name: AppRoutes.LOGIN,
|
||||
page: () => LoginView(),
|
||||
page: () => DeferredWidget(login.loadLibrary, () => login.LoginView()),
|
||||
binding: LoginBindings()),
|
||||
GetPage(
|
||||
name: AppRoutes.SESSION,
|
||||
page: () => SessionView(),
|
||||
page: () => DeferredWidget(session.loadLibrary, () => session.SessionView()),
|
||||
binding: SessionPageBindings()),
|
||||
GetPage(
|
||||
name: AppRoutes.MAILBOX,
|
||||
page: () => MailboxView()),
|
||||
GetPage(
|
||||
name: AppRoutes.MAILBOX_DASHBOARD,
|
||||
page: () => MailboxDashBoardView(),
|
||||
page: () => DeferredWidget(mailbox_dashBoard.loadLibrary, () => mailbox_dashBoard.MailboxDashBoardView()),
|
||||
binding: MailboxDashBoardBindings()),
|
||||
GetPage(
|
||||
name: AppRoutes.THREAD,
|
||||
page: () => ThreadView()),
|
||||
GetPage(
|
||||
name: AppRoutes.EMAIL,
|
||||
page: () => EmailView()),
|
||||
page: () => DeferredWidget(email.loadLibrary, () => email.EmailView())),
|
||||
GetPage(
|
||||
name: AppRoutes.COMPOSER,
|
||||
opaque: false,
|
||||
page: () => ComposerView(),
|
||||
page: () => DeferredWidget(composer.loadLibrary, () => composer.ComposerView()),
|
||||
binding: ComposerBindings()),
|
||||
GetPage(
|
||||
name: AppRoutes.DESTINATION_PICKER,
|
||||
opaque: false,
|
||||
page: () => DestinationPickerView(),
|
||||
page: () => DeferredWidget(destination_picker.loadLibrary, () => destination_picker.DestinationPickerView()),
|
||||
binding: DestinationPickerBindings()),
|
||||
GetPage(
|
||||
name: AppRoutes.MAILBOX_CREATOR,
|
||||
opaque: false,
|
||||
page: () => MailboxCreatorView(),
|
||||
page: () => DeferredWidget(mailbox_creator.loadLibrary, () => mailbox_creator.MailboxCreatorView()),
|
||||
binding: MailboxCreatorBindings()),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
typedef LibraryLoader = Future<void> Function();
|
||||
typedef DeferredWidgetBuilder = Widget Function();
|
||||
|
||||
/// Wraps the child inside a deferred module loader.
|
||||
///
|
||||
/// The child is created and a single instance of the Widget is maintained in
|
||||
/// state as long as closure to create widget stays the same.
|
||||
///
|
||||
class DeferredWidget extends StatefulWidget {
|
||||
DeferredWidget(
|
||||
this.libraryLoader,
|
||||
this.createWidget,
|
||||
{Key? key, Widget? placeholder}
|
||||
) : placeholder = placeholder ?? Container(), super(key: key);
|
||||
|
||||
final LibraryLoader libraryLoader;
|
||||
final DeferredWidgetBuilder createWidget;
|
||||
final Widget placeholder;
|
||||
static final Map<LibraryLoader, Future<void>> _moduleLoaders = {};
|
||||
static final Set<LibraryLoader> _loadedModules = {};
|
||||
|
||||
static Future<void> preload(LibraryLoader loader) {
|
||||
if (!_moduleLoaders.containsKey(loader)) {
|
||||
_moduleLoaders[loader] = loader().then((dynamic _) {
|
||||
_loadedModules.add(loader);
|
||||
});
|
||||
}
|
||||
return _moduleLoaders[loader]!;
|
||||
}
|
||||
|
||||
@override
|
||||
State<DeferredWidget> createState() => _DeferredWidgetState();
|
||||
}
|
||||
|
||||
class _DeferredWidgetState extends State<DeferredWidget> {
|
||||
_DeferredWidgetState();
|
||||
|
||||
Widget? _loadedChild;
|
||||
DeferredWidgetBuilder? _loadedCreator;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
/// If module was already loaded immediately create widget instead of
|
||||
/// waiting for future or zone turn.
|
||||
if (DeferredWidget._loadedModules.contains(widget.libraryLoader)) {
|
||||
_onLibraryLoaded();
|
||||
} else {
|
||||
DeferredWidget.preload(widget.libraryLoader).then((dynamic _) => _onLibraryLoaded());
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void _onLibraryLoaded() {
|
||||
setState(() {
|
||||
_loadedCreator = widget.createWidget;
|
||||
_loadedChild = _loadedCreator!();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
/// If closure to create widget changed, create new instance, otherwise
|
||||
/// treat as const Widget.
|
||||
if (_loadedCreator != widget.createWidget && _loadedCreator != null) {
|
||||
_loadedCreator = widget.createWidget;
|
||||
_loadedChild = _loadedCreator!();
|
||||
}
|
||||
return _loadedChild ?? widget.placeholder;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user