diff --git a/lib/common.dart b/lib/common.dart
index 359844f24..75dd6efb6 100644
--- a/lib/common.dart
+++ b/lib/common.dart
@@ -39,8 +39,13 @@ void showLoading(String text) {
   EasyLoading.show(status: text, maskType: EasyLoadingMaskType.black);
 }
 
+backToHome() {
+  // use [popUntil()] to make sure pop action can't close the current MaterialApp context
+  Navigator.popUntil(globalKey.currentContext!, ModalRoute.withName("/"));
+}
+
 typedef DialogBuilder = CustomAlertDialog Function(
-    BuildContext context, StateSetter setState);
+    StateSetter setState, VoidCallback close);
 
 class DialogManager {
   static BuildContext? _dialogContext;
@@ -70,7 +75,8 @@ class DialogManager {
         barrierDismissible: barrierDismissible,
         builder: (context) {
           DialogManager.register(context);
-          return StatefulBuilder(builder: builder);
+          return StatefulBuilder(
+              builder: (_, setState) => builder(setState, DialogManager.reset));
         });
     DialogManager.drop();
     return res;
@@ -121,12 +127,11 @@ void msgBox(String type, String title, String text, {bool? hasCancel}) {
 
   EasyLoading.dismiss();
   DialogManager.reset();
-  if (globalKey.currentContext == null) return;
   final buttons = [
     Expanded(child: Container()),
     wrap(Translator.call('OK'), () {
       EasyLoading.dismiss();
-      Navigator.pop(globalKey.currentContext!);
+      backToHome();
     })
   ];
   if (hasCancel == null) {
diff --git a/lib/main.dart b/lib/main.dart
index 66477062b..ccf6705fc 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -39,9 +39,6 @@ class App extends StatelessWidget {
           visualDensity: VisualDensity.adaptivePlatformDensity,
         ),
         home: HomePage(),
-        routes: {
-          "server_page": (context) => ServerPage(),
-        },
         navigatorObservers: [
           FirebaseAnalyticsObserver(analytics: analytics),
         ],
diff --git a/lib/models/file_model.dart b/lib/models/file_model.dart
index 4112f793a..6478ef588 100644
--- a/lib/models/file_model.dart
+++ b/lib/models/file_model.dart
@@ -104,7 +104,7 @@ class FileModel extends ChangeNotifier {
       } else {
         _currentRemoteDir = fileDir;
       }
-      notifyListeners();
+      notifyListeners(); // TODO use too early, error occur:setState() or markNeedsBuild() called during build.
     } catch (e) {
       debugPrint("Failed to tryUpdateDir :$fd");
     }
@@ -156,7 +156,8 @@ class FileModel extends ChangeNotifier {
     }
     items.items.forEach((entry) {
       _jobId++;
-      if (entry.isFile) { // TODO dir
+      if (entry.isFile) {
+        // TODO dir
         final msg = {
           "id": _jobId.toString(),
           "path": entry.path,
@@ -170,9 +171,7 @@ class FileModel extends ChangeNotifier {
     });
   }
 
-  createDir(String path){
-
-  }
+  createDir(String path) {}
 
   changeSortStyle(SortBy sort) {
     _sortStyle = sort;
diff --git a/lib/pages/remote_page.dart b/lib/pages/remote_page.dart
index 6da22b0ec..ae9e79d72 100644
--- a/lib/pages/remote_page.dart
+++ b/lib/pages/remote_page.dart
@@ -310,7 +310,7 @@ class _RemotePageState extends State<RemotePage> {
                     IconButton(
                       color: Colors.white,
                       icon: Icon(Icons.message),
-                      onPressed:toggleChatOverlay,
+                      onPressed: toggleChatOverlay,
                     ),
                     IconButton(
                       color: Colors.white,
@@ -778,8 +778,6 @@ class ImagePainter extends CustomPainter {
   }
 }
 
-
-
 CheckboxListTile getToggle(
     void Function(void Function()) setState, option, name) {
   return CheckboxListTile(
@@ -848,7 +846,7 @@ void showOptions() {
   }
   final perms = FFI.ffiModel.permissions;
 
-  DialogManager.show((context, setState) {
+  DialogManager.show((setState, close) {
     final more = <Widget>[];
     if (perms['audio'] != false) {
       more.add(getToggle(setState, 'disable-audio', 'Mute'));
@@ -879,34 +877,31 @@ void showOptions() {
       });
     };
     return CustomAlertDialog(
-        title: SizedBox.shrink(),
-        content: Column(
-            mainAxisSize: MainAxisSize.min,
-            children: displays +
-                (isDesktop
-                    ? <Widget>[
-                  getRadio(
-                      'Original', 'original', viewStyle, setViewStyle),
-                  getRadio('Shrink', 'shrink', viewStyle, setViewStyle),
-                  getRadio('Stretch', 'stretch', viewStyle, setViewStyle),
-                  Divider(color: MyTheme.border),
-                ]
-                    : []) +
-                <Widget>[
-                  getRadio('Good image quality', 'best', quality, setQuality),
-                  getRadio('Balanced', 'balanced', quality, setQuality),
-                  getRadio(
-                      'Optimize reaction time', 'low', quality, setQuality),
-                  Divider(color: MyTheme.border),
-                  getToggle(
-                      setState, 'show-remote-cursor', 'Show remote cursor'),
-                ] +
-                more),
-        actions: [],
-        onWillPop: () async => true,
-        contentPadding: 0,
+      title: SizedBox.shrink(),
+      content: Column(
+          mainAxisSize: MainAxisSize.min,
+          children: displays +
+              (isDesktop
+                  ? <Widget>[
+                      getRadio('Original', 'original', viewStyle, setViewStyle),
+                      getRadio('Shrink', 'shrink', viewStyle, setViewStyle),
+                      getRadio('Stretch', 'stretch', viewStyle, setViewStyle),
+                      Divider(color: MyTheme.border),
+                    ]
+                  : []) +
+              <Widget>[
+                getRadio('Good image quality', 'best', quality, setQuality),
+                getRadio('Balanced', 'balanced', quality, setQuality),
+                getRadio('Optimize reaction time', 'low', quality, setQuality),
+                Divider(color: MyTheme.border),
+                getToggle(setState, 'show-remote-cursor', 'Show remote cursor'),
+              ] +
+              more),
+      actions: [],
+      onWillPop: () async => true,
+      contentPadding: 0,
     );
-  },barrierDismissible: true);
+  }, barrierDismissible: true);
 }
 
 void showSetOSPassword(bool login) {
@@ -914,7 +909,7 @@ void showSetOSPassword(bool login) {
   var password = FFI.getByName('peer_option', "os-password");
   var autoLogin = FFI.getByName('peer_option', "auto-login") != "";
   controller.text = password;
-  DialogManager.show((context, setState) {
+  DialogManager.show((setState, close) {
     return CustomAlertDialog(
         title: Text(translate('OS Password')),
         content: Column(mainAxisSize: MainAxisSize.min, children: [
@@ -937,7 +932,7 @@ void showSetOSPassword(bool login) {
           TextButton(
             style: flatButtonStyle,
             onPressed: () {
-              Navigator.pop(context);
+              close();
             },
             child: Text(translate('Cancel')),
           ),
@@ -952,7 +947,7 @@ void showSetOSPassword(bool login) {
               if (text != "" && login) {
                 FFI.setByName('input_os_password', text);
               }
-              Navigator.pop(context);
+              close();
             },
             child: Text(translate('OK')),
           ),
diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart
index 327e0b1c1..90692a2ca 100644
--- a/lib/pages/settings_page.dart
+++ b/lib/pages/settings_page.dart
@@ -69,7 +69,7 @@ void showServer() {
   var id = '';
   var relay = '';
   var key = '';
-  DialogManager.show((context, setState) {
+  DialogManager.show((setState, close) {
     return CustomAlertDialog(
         title: Text(translate('ID Server')),
         content: Form(
@@ -112,7 +112,7 @@ void showServer() {
           TextButton(
             style: flatButtonStyle,
             onPressed: () {
-              DialogManager.reset();
+              close();
             },
             child: Text(translate('Cancel')),
           ),
@@ -130,7 +130,7 @@ void showServer() {
                       'option', '{"name": "relay-server", "value": "$relay"}');
                 if (key != key0)
                   FFI.setByName('option', '{"name": "key", "value": "$key"}');
-                DialogManager.reset();
+                close();
               }
             },
             child: Text(translate('OK')),
diff --git a/lib/widgets/dialog.dart b/lib/widgets/dialog.dart
index 352dd33a4..03479f5a6 100644
--- a/lib/widgets/dialog.dart
+++ b/lib/widgets/dialog.dart
@@ -9,7 +9,7 @@ void clientClose() {
 void enterPasswordDialog(String id) {
   final controller = TextEditingController();
   var remember = FFI.getByName('remember', id) == 'true';
-  DialogManager.show((context, setState) {
+  DialogManager.show((setState, close) {
     return CustomAlertDialog(
       title: Text(translate('Password Required')),
       content: Column(mainAxisSize: MainAxisSize.min, children: [
@@ -34,8 +34,8 @@ void enterPasswordDialog(String id) {
         TextButton(
           style: flatButtonStyle,
           onPressed: () {
-            DialogManager.reset();
-            Navigator.pop(globalKey.currentContext!);
+            close();
+            backToHome();
           },
           child: Text(translate('Cancel')),
         ),
@@ -45,7 +45,7 @@ void enterPasswordDialog(String id) {
             var text = controller.text.trim();
             if (text == '') return;
             FFI.login(text, remember);
-            DialogManager.reset();
+            close();
             showLoading(translate('Logging in...'));
           },
           child: Text(translate('OK')),
@@ -56,15 +56,15 @@ void enterPasswordDialog(String id) {
 }
 
 void wrongPasswordDialog(String id) {
-  DialogManager.show((context, setState) => CustomAlertDialog(
+  DialogManager.show((setState, close) => CustomAlertDialog(
           title: Text(translate('Wrong Password')),
           content: Text(translate('Do you want to enter again?')),
           actions: [
             TextButton(
               style: flatButtonStyle,
               onPressed: () {
-                DialogManager.reset();
-                Navigator.pop(globalKey.currentContext!);
+                close();
+                backToHome();
               },
               child: Text(translate('Cancel')),
             ),