diff --git a/lib/providers/websocket.dart b/lib/providers/websocket.dart
index 7758577..69418da 100644
--- a/lib/providers/websocket.dart
+++ b/lib/providers/websocket.dart
@@ -42,22 +42,22 @@ class WebSocketProvider extends ChangeNotifier {
       _connectCompleter = null;
     }
 
-    _connectCompleter = Completer<void>();
-
     if (!_ua.isAuthorized) return;
     if (isConnected || conn != null) {
       disconnect();
     }
 
-    final atk = await _sn.getFreshAtk();
-    final uri = Uri.parse(
-      '${_sn.client.options.baseUrl.replaceFirst('http', 'ws')}/ws?tk=$atk',
-    );
-
-    isBusy = true;
-    notifyListeners();
-
     try {
+      _connectCompleter = Completer<void>();
+
+      final atk = await _sn.getFreshAtk();
+      final uri = Uri.parse(
+        '${_sn.client.options.baseUrl.replaceFirst('http', 'ws')}/ws?tk=$atk',
+      );
+
+      isBusy = true;
+      notifyListeners();
+
       conn = WebSocketChannel.connect(uri);
       await conn!.ready;
       _wsStream = conn!.stream.asBroadcastStream();
@@ -82,6 +82,7 @@ class WebSocketProvider extends ChangeNotifier {
       isBusy = false;
       notifyListeners();
       _connectCompleter!.complete();
+      _connectCompleter = null;
     }
   }
 
diff --git a/lib/screens/post/post_editor.dart b/lib/screens/post/post_editor.dart
index ca32033..fd55915 100644
--- a/lib/screens/post/post_editor.dart
+++ b/lib/screens/post/post_editor.dart
@@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_context_menu/flutter_context_menu.dart';
 import 'package:gap/gap.dart';
+import 'package:go_router/go_router.dart';
 import 'package:hotkey_manager/hotkey_manager.dart';
 import 'package:material_symbols_icons/symbols.dart';
 import 'package:pasteboard/pasteboard.dart';
@@ -90,8 +91,9 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
         resp.data?.map((e) => SnPublisher.fromJson(e)) ?? [],
       );
       final beforeId = config.prefs.getInt('int_last_publisher_id');
-      _writeController
-          .setPublisher(_publishers?.where((ele) => ele.id == beforeId).firstOrNull ?? _publishers?.firstOrNull);
+      _writeController.setPublisher(
+          _publishers?.where((ele) => ele.id == beforeId).firstOrNull ??
+              _publishers?.firstOrNull);
     } catch (err) {
       if (!mounted) return;
       context.showErrorDialog(err);
@@ -110,7 +112,9 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
 
   final HotKey _pasteHotKey = HotKey(
     key: PhysicalKeyboardKey.keyV,
-    modifiers: [Platform.isMacOS ? HotKeyModifier.meta : HotKeyModifier.control],
+    modifiers: [
+      Platform.isMacOS ? HotKeyModifier.meta : HotKeyModifier.control
+    ],
     scope: HotKeyScope.inapp,
   );
 
@@ -160,7 +164,8 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
   @override
   void dispose() {
     _writeController.dispose();
-    if (!kIsWeb && !(Platform.isAndroid || Platform.isIOS)) hotKeyManager.unregister(_pasteHotKey);
+    if (!kIsWeb && !(Platform.isAndroid || Platform.isIOS))
+      hotKeyManager.unregister(_pasteHotKey);
     super.dispose();
   }
 
@@ -184,7 +189,8 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
     if (widget.extraProps != null) {
       _writeController.contentController.text = widget.extraProps!.text ?? '';
       _writeController.titleController.text = widget.extraProps!.title ?? '';
-      _writeController.descriptionController.text = widget.extraProps!.description ?? '';
+      _writeController.descriptionController.text =
+          widget.extraProps!.description ?? '';
       _writeController.addAttachments(widget.extraProps!.attachments ?? []);
     }
   }
@@ -205,7 +211,9 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
               textAlign: TextAlign.center,
               text: TextSpan(children: [
                 TextSpan(
-                  text: _writeController.title.isNotEmpty ? _writeController.title : 'untitled'.tr(),
+                  text: _writeController.title.isNotEmpty
+                      ? _writeController.title
+                      : 'untitled'.tr(),
                   style: Theme.of(context).textTheme.titleLarge!.copyWith(
                         color: Theme.of(context).appBarTheme.foregroundColor!,
                       ),
@@ -232,7 +240,8 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
             children: [
               if (_writeController.editingPost != null)
                 Container(
-                  padding: const EdgeInsets.only(top: 4, bottom: 4, left: 20, right: 20),
+                  padding: const EdgeInsets.only(
+                      top: 4, bottom: 4, left: 20, right: 20),
                   decoration: BoxDecoration(
                     border: Border(
                       bottom: BorderSide(
@@ -246,7 +255,9 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
                     children: [
                       const Icon(Icons.edit, size: 16),
                       const Gap(10),
-                      Text('postEditingNotice').tr(args: ['@${_writeController.editingPost!.publisher.name}']),
+                      Text('postEditingNotice').tr(args: [
+                        '@${_writeController.editingPost!.publisher.name}'
+                      ]),
                     ],
                   ),
                 ),
@@ -276,7 +287,8 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
                       })
                           .padding(top: 8),
                     ),
-                    if (_writeController.attachments.isNotEmpty || _writeController.thumbnail != null)
+                    if (_writeController.attachments.isNotEmpty ||
+                        _writeController.thumbnail != null)
                       Positioned(
                         bottom: 0,
                         left: 0,
@@ -286,7 +298,8 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
                           attachments: _writeController.attachments,
                           isBusy: _writeController.isBusy,
                           onUpload: (int idx) async {
-                            await _writeController.uploadSingleAttachment(context, idx);
+                            await _writeController.uploadSingleAttachment(
+                                context, idx);
                           },
                           onPostSetThumbnail: (int? idx) {
                             _writeController.setThumbnail(idx);
@@ -295,10 +308,12 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
                             _writeController.contentController.text +=
                                 '\n![](solink://attachments/${_writeController.attachments[idx].attachment!.rid})';
                           },
-                          onUpdate: (int idx, PostWriteMedia updatedMedia) async {
+                          onUpdate:
+                              (int idx, PostWriteMedia updatedMedia) async {
                             _writeController.setIsBusy(true);
                             try {
-                              _writeController.setAttachmentAt(idx, updatedMedia);
+                              _writeController.setAttachmentAt(
+                                  idx, updatedMedia);
                             } finally {
                               _writeController.setIsBusy(false);
                             }
@@ -311,7 +326,8 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
                               _writeController.setIsBusy(false);
                             }
                           },
-                          onUpdateBusy: (state) => _writeController.setIsBusy(state),
+                          onUpdateBusy: (state) =>
+                              _writeController.setIsBusy(state),
                         ).padding(bottom: 8),
                       ),
                   ],
@@ -322,11 +338,13 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
                 child: Column(
                   crossAxisAlignment: CrossAxisAlignment.start,
                   children: [
-                    if (_writeController.isBusy && _writeController.progress != null)
+                    if (_writeController.isBusy &&
+                        _writeController.progress != null)
                       TweenAnimationBuilder<double>(
                         tween: Tween(begin: 0, end: _writeController.progress),
                         duration: Duration(milliseconds: 300),
-                        builder: (context, value, _) => LinearProgressIndicator(value: value, minHeight: 2),
+                        builder: (context, value, _) =>
+                            LinearProgressIndicator(value: value, minHeight: 2),
                       )
                     else if (_writeController.isBusy)
                       const LinearProgressIndicator(value: null, minHeight: 2),
@@ -335,12 +353,14 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
                     Container(
                       child: _writeController.temporaryRestored
                           ? Container(
-                              padding: const EdgeInsets.only(top: 4, bottom: 4, left: 28, right: 22),
+                              padding: const EdgeInsets.only(
+                                  top: 4, bottom: 4, left: 28, right: 22),
                               decoration: BoxDecoration(
                                 border: Border(
                                   bottom: BorderSide(
                                     color: Theme.of(context).dividerColor,
-                                    width: 1 / MediaQuery.of(context).devicePixelRatio,
+                                    width: 1 /
+                                        MediaQuery.of(context).devicePixelRatio,
                                   ),
                                 ),
                               ),
@@ -349,7 +369,9 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
                                 children: [
                                   const Icon(Icons.restore, size: 20),
                                   const Gap(8),
-                                  Expanded(child: Text('postLocalDraftRestored').tr()),
+                                  Expanded(
+                                      child:
+                                          Text('postLocalDraftRestored').tr()),
                                   InkWell(
                                     child: Text('dialogDismiss').tr(),
                                     onTap: () {
@@ -360,8 +382,10 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
                               ))
                           : const SizedBox.shrink(),
                     )
-                        .height(_writeController.temporaryRestored ? 32 : 0, animate: true)
-                        .animate(const Duration(milliseconds: 300), Curves.fastLinearToSlowEaseIn),
+                        .height(_writeController.temporaryRestored ? 32 : 0,
+                            animate: true)
+                        .animate(const Duration(milliseconds: 300),
+                            Curves.fastLinearToSlowEaseIn),
                     Row(
                       mainAxisAlignment: MainAxisAlignment.spaceBetween,
                       children: [
@@ -381,11 +405,18 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
                                   ),
                                   if (_writeController.mode == 'stories')
                                     IconButton(
-                                      icon: Icon(Symbols.poll, color: Theme.of(context).colorScheme.primary),
+                                      icon: Icon(Symbols.poll,
+                                          color: Theme.of(context)
+                                              .colorScheme
+                                              .primary),
                                       style: ButtonStyle(
-                                        backgroundColor: _writeController.poll == null
-                                            ? null
-                                            : WidgetStatePropertyAll(Theme.of(context).colorScheme.surfaceContainer),
+                                        backgroundColor:
+                                            _writeController.poll == null
+                                                ? null
+                                                : WidgetStatePropertyAll(
+                                                    Theme.of(context)
+                                                        .colorScheme
+                                                        .surfaceContainer),
                                       ),
                                       onPressed: () {
                                         _showPollEditorDialog();
@@ -397,7 +428,8 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
                           ),
                         ),
                         TextButton.icon(
-                          onPressed: (_writeController.isBusy || _writeController.publisher == null)
+                          onPressed: (_writeController.isBusy ||
+                                  _writeController.publisher == null)
                               ? null
                               : () {
                                   _writeController.sendPost(context).then((_) {
@@ -447,9 +479,21 @@ class _PostPublisherPopup extends StatelessWidget {
           children: [
             const Icon(Symbols.face, size: 24),
             const Gap(16),
-            Text('accountPublishers', style: Theme.of(context).textTheme.titleLarge).tr(),
+            Text('accountPublishers',
+                    style: Theme.of(context).textTheme.titleLarge)
+                .tr(),
           ],
         ).padding(horizontal: 20, top: 16, bottom: 12),
+        ListTile(
+          leading: const Icon(Symbols.add),
+          title: Text('publishersNew').tr(),
+          subtitle: Text('publisherNewSubtitle').tr(),
+          contentPadding: const EdgeInsets.symmetric(horizontal: 24),
+          onTap: () {
+            GoRouter.of(context).pushNamed('accountPublisherNew');
+          },
+        ),
+        const Divider(height: 1),
         Expanded(
           child: ListView.builder(
             itemCount: publishers?.length ?? 0,
@@ -509,7 +553,8 @@ class _PostStoryEditor extends StatelessWidget {
                     border: InputBorder.none,
                   ),
                   style: Theme.of(context).textTheme.titleLarge,
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ).padding(horizontal: 16),
                 const Gap(8),
                 TextField(
@@ -524,7 +569,8 @@ class _PostStoryEditor extends StatelessWidget {
                     ),
                     border: InputBorder.none,
                   ),
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ),
               ],
             ),
@@ -614,7 +660,8 @@ class _PostArticleEditor extends StatelessWidget {
                       ),
                       border: InputBorder.none,
                     ),
-                    onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                    onTapOutside: (_) =>
+                        FocusManager.instance.primaryFocus?.unfocus(),
                   ),
                 ),
                 const Gap(8),
@@ -693,7 +740,8 @@ class _PostQuestionEditor extends StatelessWidget {
                     border: InputBorder.none,
                   ),
                   style: Theme.of(context).textTheme.titleLarge,
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ).padding(horizontal: 16),
                 const Gap(8),
                 TextField(
@@ -704,7 +752,8 @@ class _PostQuestionEditor extends StatelessWidget {
                     border: InputBorder.none,
                     isCollapsed: true,
                   ),
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ).padding(horizontal: 16),
                 const Gap(8),
                 TextField(
@@ -719,7 +768,8 @@ class _PostQuestionEditor extends StatelessWidget {
                     ),
                     border: InputBorder.none,
                   ),
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ),
               ],
             ),
@@ -755,7 +805,8 @@ class _PostVideoEditor extends StatelessWidget {
 
     final result = await showDialog<SnAttachment?>(
       context: context,
-      builder: (context) => PendingAttachmentAltDialog(media: PostWriteMedia(controller.videoAttachment)),
+      builder: (context) => PendingAttachmentAltDialog(
+          media: PostWriteMedia(controller.videoAttachment)),
     );
     if (result == null) return;
 
@@ -767,7 +818,8 @@ class _PostVideoEditor extends StatelessWidget {
 
     final result = await showDialog<SnAttachmentBoost?>(
       context: context,
-      builder: (context) => PendingAttachmentBoostDialog(media: PostWriteMedia(controller.videoAttachment)),
+      builder: (context) => PendingAttachmentBoostDialog(
+          media: PostWriteMedia(controller.videoAttachment)),
     );
     if (result == null) return;
 
@@ -810,7 +862,8 @@ class _PostVideoEditor extends StatelessWidget {
 
     try {
       final sn = context.read<SnNetworkProvider>();
-      await sn.client.delete('/cgi/uc/attachments/${controller.videoAttachment!.id}');
+      await sn.client
+          .delete('/cgi/uc/attachments/${controller.videoAttachment!.id}');
       controller.setVideoAttachment(null);
     } catch (err) {
       if (!context.mounted) return;
@@ -902,7 +955,8 @@ class _PostVideoEditor extends StatelessWidget {
                   label: 'attachmentCopyRandomId'.tr(),
                   icon: Symbols.content_copy,
                   onSelected: () {
-                    Clipboard.setData(ClipboardData(text: controller.videoAttachment!.rid));
+                    Clipboard.setData(
+                        ClipboardData(text: controller.videoAttachment!.rid));
                   },
                 ),
                 MenuItem(
@@ -921,7 +975,9 @@ class _PostVideoEditor extends StatelessWidget {
             ),
             child: InkWell(
               borderRadius: BorderRadius.circular(16),
-              onTap: controller.videoAttachment == null ? () => _selectVideo(context) : null,
+              onTap: controller.videoAttachment == null
+                  ? () => _selectVideo(context)
+                  : null,
               child: AspectRatio(
                 aspectRatio: 16 / 9,
                 child: controller.videoAttachment == null
diff --git a/pubspec.lock b/pubspec.lock
index 569a582..06b6faa 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -498,10 +498,10 @@ packages:
     dependency: "direct main"
     description:
       name: file_picker
-      sha256: "3d57312a53746ed4eb8c843dc50372454bbda37dd0c01a4d40fedc83e2ce4921"
+      sha256: ab13ae8ef5580a411c458d6207b6774a6c237d77ac37011b13994879f68a8810
       url: "https://pub.dev"
     source: hosted
-    version: "8.3.5"
+    version: "8.3.7"
   file_saver:
     dependency: "direct main"
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 1bf4295..a44dea3 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 # In Windows, build-name is used as the major, minor, and patch parts
 # of the product and file versions while build-number is used as the build suffix.
-version: 2.3.2+67
+version: 2.3.2+68
 
 environment:
   sdk: ^3.5.4