Skip to content

Latest commit

 

History

History
478 lines (374 loc) · 16.8 KB

3.x migrate 4.0.md

File metadata and controls

478 lines (374 loc) · 16.8 KB

Preface

An open source library, with continuous iterative optimization, will inevitably encounter a very painful problem

  • The original design was not very reasonable: a lot of new features that I wanted to add were hindered by this

To make the library more powerful and robust, a refactoring must be done

  • Because the refactoring involves exposed APIs, everyone will encounter a more irritating problem: after updating the version, a large number of errors will be reported
  • I have been thinking about it for a long time. How can I help you to migrate quickly? Finally came up with a reasonable solution

For the changes of flutter_smart_dialog version 4.0, many of them are to solve the historical legacy that I have not considered before. The original intention of this library was mainly to solve the problem of loading and dialog penetration; now it is extended to: custom dialog, attach dialog, loading, toast , the initial design is really inadequate, the API in config is difficult to subdivide the functions of these four modules, and the design of some parameters is not reasonable based on the current functions and scenarios, etc.

I hope everyone can understand why I want to refactor 🥺, I am definitely not doing things 🥺

Quick Migration Guide

Compatible API (required) ⭐️

Description

  • show method is fast compatible
SmartDialog.compatible.show();
SmartDialog.compatible.showAttach();
SmartDialog.compatible.showLoading();
SmartDialog.compatible.showToast();
  • config fast compatibility
SmartDialog.compatible.config;

Add the compatible intermediate variable, which can quickly compatible with the changed parameters

Quick Actions

  • Quick migration using global replace function: SmartDialog.show ---> SmartDialog.compatible.show
    • Mac: command + shift + r
    • Windows: ctrl + shift + r

image-20220501230620406

  • Config: SmartDialog.config ---> SmartDialog.compatible.config
    • Mac: command + shift + r
    • Windows: ctrl + shift + r

image-20220501230830221

Parameter removal (required) ⭐️

  • Version 4.0 removed a few parameters
Method Description
showLoading(...) remove background parameter (not compatible with this parameter)
showToast(...) remove alignment parameter (compatible not compatible)
showAttach(...) remove highlight parameter (compatible with this parameter)
  • These parameters are removed, and a little adjustment is required when initializing custom loading and toast
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage,
      // here
      navigatorObservers: [FlutterSmartDialog.observer],
      // here
      builder: FlutterSmartDialog.init(
        //default toast widget
        toastBuilder: (String msg) => CustomToastWidget(msg: msg),
        //default loading widget
        loadingBuilder: (String msg) => CustomLoadingWidget(msg: msg),
      ),
    );
  }
}

Description

The two parameters background and alignment are really useless, the frequency of use is too low

Generally, the toast and loading styles are customized, and you can draw as you want; if you simply use toast and loading, these two parameters cannot achieve a strong custom effect, which is too cumbersome and simply deleted.

Parameter name change (optional)

Complete migration is possible through the above compatible API and parameter removal

Here I will write down the changed parameter names completely, you can compare them

Original parameter name Changed parameter name
widget builder: Align with the routing dialog parameter (see the builder parameter description below for details)
isLoading / isLoadingTemp animationType: It is convenient to expand various animation types later
isPenetrate / isPenetrateTemp usePenetrate: true (click events will penetrate the background), false (not penetrate)
isUseAnimation / isUseAnimationTemp useAnimation: true (use animation), false (do not use)
clickBgDismiss / clickBgDismissTemp clickMaskDismiss: true (dismiss the dialog after clicking on the mask), false (do not close)
animationDuration / animationDurationTemp animationTime: animation duration
alignmentTemp alignment: controls the position of the popup window
maskColorTemp maskColor: mask color
maskWidgetTemp maskWidget: Highly customizable mask
debounceTemp debounce: Anti-shake function
time(showToast) displayTime:time displayed by toast
type(showToast) displayType:multi types of toast display logic

builder parameter description (important)

Version 4.0 has made a lot of changes to custom control parameters

  • old version
SmartDialog.show(
  widget: Container(
    height: 80,
    width: 180,
    decoration: BoxDecoration(
      color: Colors.black,
      borderRadius: BorderRadius.circular(10),
    ),
    alignment: Alignment.center,
    child: Text(
      'easy custom dialog',
      style: TextStyle(color: Colors.white),
    ),
  ),
);
  • Version 4.0
SmartDialog.show(builder: (context) {
  return Container(
    height: 80,
    width: 180,
    decoration: BoxDecoration(
      color: Colors.black,
      borderRadius: BorderRadius.circular(10),
    ),
    alignment: Alignment.center,
    child: Text(
      'easy custom dialog',
      style: TextStyle(color: Colors.white),
    ),
  );
});

Although this change will make it a little more troublesome to use, it is very important.

  • The first is to align with the api of the routing dialog, and the custom control parameters of the routing dialog are also builder
  • Then solve the problem of dynamic refresh of the custom dialog itself: the custom layout has TextField, when the keyboard pops up, the custom dialog layout can dynamically adjust the distance (need to use the corresponding widget)

New features in version 4.0

Powerful Config

  • You can use config to get whether the dialog exists
// Customize dialog, attach or loading, whether it exists on the interface
SmartDialog.config.isExist;
// Whether the custom dialog or attach exists on the interface
SmartDialog.config.isExistDialog;
// Whether loading exists on the interface
SmartDialog.config.isExistLoading;
// Whether toast exists on the interface
SmartDialog.config.isExistToast;
  • config can control show, showAttach, showLoading, showToast and other pop-up windows in more detail
    • The default parameters of SmartConfigXxx() are all set by me after deep thinking, no additional settings are required without special requirements
    • If you do not need to customize the config value, the initialization code below does not need to be written
SmartDialog.config
  ..custom = SmartConfigCustom()
  ..attach = SmartConfigAttach()
  ..loading = SmartConfigLoading()
  ..toast = SmartConfigToast();
  • You can customize the values in any config to meet the corresponding needs
    • The code below is to demonstrate custom parameters
    • You can set as needed
SmartDialog.config
  ..custom = SmartConfigCustom(
    maskColor: Colors.black.withOpacity(0.35),
    useAnimation: true,
  )
  ..attach = SmartConfigAttach(
    animationType: SmartAnimationType.scale,
    usePenetrate: false,
  )
  ..loading = SmartConfigLoading(
    clickMaskDismiss: false,
    leastLoadingTime: const Duration(milliseconds: 0),
  )
  ..toast = SmartConfigToast(
    intervalTime: const Duration(milliseconds: 100),
    displayTime: const Duration(milliseconds: 2000),
  );

bindPage

Description

The meaning of this parameter is to bind the SmartDialog to the page: if the page is jumped on the SmartDialog

  • Binding SmartDialog with the current page will automatically hide
  • When returning to the binding page, the SmartDialog will be displayed

Regarding the problem of jumping pages on the Dialog, the version before 4.0 can be solved by using the useSystem parameter

  • When using the useSystem parameter, the essence is to use the built-in dialog as a carrier, so that you can interact with the page reasonably
  • But due to various limitations of the built-in dialog, when using useSystem: usePenetrate, tag, KeepSingle, permanent are all forbidden to use

The logic of bindPage introduced in version 4.0 can avoid various restrictions when using useSystem

bindPage is enabled by default (can be configured in config), and can also be manually disabled or enabled when using show and showAttach; in special business scenarios, bindPage and useSystem can be used as needed

Use effects

  • Write a demo, this is the normal operation of jumping pages on the pop-up window
void _dialogBindPage() async {
  var index = 0;
  Function()? showDialog;

  toNewPage(bool useSystem) async {
    Get.to(
      () {
        return Scaffold(
          appBar: AppBar(title: Text('New Page ${++index}')),
          body: Container(
            color: randomColor(),
            alignment: Alignment.center,
            child: ElevatedButton(
              onPressed: () => showDialog?.call(),
              child: Text('test bindPage $index'),
            ),
          ),
        );
      },
      preventDuplicates: false,
    );
  }

  showDialog = () {
    SmartDialog.show(builder: (_) {
      return Container(
        width: 300,
        height: 170,
        alignment: Alignment.center,
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(20),
        ),
        child: ElevatedButton(
          onPressed: () => toNewPage(false),
          child: Text('test bindPage $index'),
        ),
      );
    });
  };

  showDialog();
}
  • to see the effect
    • Honestly, the effect is silky without the useSystem function
    • But bindPage also solves the problem of jumping pages on the pop-up window, while retaining the functions of usePenetrate, tag, KeepSingle, permanent and so on
    • Everyone needs to use

bindPage

Carry result when closing the dialog

This function is closed with flutter routing, and the function of carrying return data is aligned

  • Take a look at the demo: Click the show result button to close the popup and return the data in the input box
void _dialogCarryResult() async {
  var result = await SmartDialog.show(
    builder: (_) {
      var message = '';
      return Container(
        width: 300,
        height: 170,
        alignment: Alignment.center,
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(20),
        ),
        child: Column(mainAxisSize: MainAxisSize.min, children: [
          Container(
            width: 100,
            margin: EdgeInsets.only(bottom: 30),
            child: TextField(onChanged: (msg) => message = msg),
          ),
          ElevatedButton(
            onPressed: () => SmartDialog.dismiss(result: message),
            child: Text('show result'),
          )
        ]),
      );
    },
  );

  SmartDialog.showToast("$result");
}
  • Effect

carryResult

Permanent Dialog

Set the permanent parameter to true, the opened dialog will become a permanent dialog, and all closing operations (returning events, routing pops, clicking masks, etc.) inside the framework will be invalid and can only be closed manually

Please use this function in combination with actual business scenarios and do not abuse it

  • open a permanent dialog
SmartDialog.show(
  permanent: true,
  usePenetrate: true,
  builder: (_) => Container(width: 150, height: 150, color: Colors.black),
);
  • Turn off permanent dialog
SmartDialog.dismiss(force: true);
  • Take a look at the demo
void _dialogPermanent() async {
  openPermanentDialog() {
    SmartDialog.show(
      permanent: true,
      alignment: Alignment.centerRight,
      usePenetrate: true,
      clickMaskDismiss: false,
      builder: (_) {
        return Container(
          width: 150,
          height: double.infinity,
          alignment: Alignment.center,
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(20),
              bottomLeft: Radius.circular(20),
            ),
            boxShadow: [
              BoxShadow(color: Colors.grey, blurRadius: 8, spreadRadius: 0.2)
            ],
          ),
          child: Text('permanent dialog'),
        );
      },
    );
  }

  SmartDialog.show(builder: (_) {
    return Container(
      width: 300,
      height: 170,
      alignment: Alignment.center,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(20),
      ),
      child: Wrap(spacing: 20, children: [
        ElevatedButton(
          onPressed: () => openPermanentDialog(),
          child: Text('open'),
        ),
        ElevatedButton(
          onPressed: () => SmartDialog.dismiss(force: true),
          child: Text('close'),
        )
      ]),
    );
  });
}
  • Effect: You can see the pop route, click on the mask and return events, but you cannot close the permanent dialog

permanentDialog

Least loading time

There is a leastLoadingTime parameter in loading in config, which can control the minimum loading time

This function is to solve the problem that the interface request is too fast, causing the loading pop-up window to flash by.

  • Use: Please set appropriate data for this parameter according to the actual business scenario. The default value of leastLoadingTime is 0 seconds.
    • This is only for demonstration, and config.loading is reassigned here. Generally, it is recommended to set the parameters in the app initialization position
    • Call dismiss immediately after showLoading(), and loading will flash by
    • Set the leastLoadingTime to 2 seconds, the loading will be forced to wait for two seconds before the dismiss will take effect
void _loadingLeastTime() async {
  SmartDialog.config.loading = SmartConfigLoading(
    leastLoadingTime: const Duration(seconds: 2),
  );
  SmartDialog.showLoading();
  SmartDialog.dismiss();
  SmartDialog.config.loading = SmartConfigLoading();
}
  • Effect

leastTime

Continuous toast display interval time

When multiple toasts are displayed continuously, the previous toast and the next toast display no interval time, which looks a bit awkward

Here an intervalTime parameter is added to SmartConfigToast to control the interval time

The default intervalTime is already a reasonable parameter, if not necessary, it is best not to change

  • Take a look at the effect, just for demonstration, the value of intervalTime is set slightly larger
void _toastIntervalTime() async {
  SmartDialog.config.toast = SmartConfigToast(
    intervalTime: const Duration(milliseconds: 800),
  );
  for (var i = 0; i < 3; i++) {
    SmartDialog.showToast("toast $i").then((value) {
      if (!SmartDialog.config.isExistToast) {
        SmartDialog.config.toast = SmartConfigToast();
      }
    });
  }
}
  • renderings

intervalTime

Summarize

SmartDialog 4.0 version is a very important version, marking SmartDialog bid farewell to shyness and become mature

After this reconstruction, I also have the confidence to face more complex business scenarios and carry out various expansions.

I have done a lot of thinking about this refactoring, and I am very grateful to everyone for giving me various issues, you have inspired me!

img