diff --git a/.changes/2060-spanish-and-arabic.md b/.changes/2060-spanish-and-arabic.md
new file mode 100644
index 000000000000..4d6ee2ea0605
--- /dev/null
+++ b/.changes/2060-spanish-and-arabic.md
@@ -0,0 +1 @@
+- Acter is now available in Spanish (thanks to Sandra) and in Arabic (thanks, Omar!)
diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml
index e207c55f3164..f8026e538063 100644
--- a/.github/workflows/build-docs.yml
+++ b/.github/workflows/build-docs.yml
@@ -49,7 +49,7 @@ jobs:
         run: ls -ltas packages/rust_sdk/lib/
 
       - name: Build Dart SDK
-        run: flutter pub global run dartdoc --output ../../../docs/api/main/dart-sdk/
+        run: flutter pub global run dartdoc --output ../../docs/api/main/dart-sdk/
         working-directory: packages/rust_sdk
 
       - name: Upload artifact
diff --git a/.github/workflows/deploy-nightly.yml b/.github/workflows/deploy-nightly.yml
index 796774537507..f245c325afdd 100644
--- a/.github/workflows/deploy-nightly.yml
+++ b/.github/workflows/deploy-nightly.yml
@@ -8,6 +8,9 @@ on:
   schedule:
    - cron: 0 1 * * 0-3,5-6
 
+permissions:
+  contents: write
+
 jobs:
   run_checker:
     runs-on: ubuntu-latest
@@ -277,7 +280,7 @@ jobs:
  ######   ####    ##    ##     ##  #######  ########     ##         #######  ########  ######## ####  ######  ##     ## 
 
   publish:
-    environment: nightly
+    environment: release
     runs-on: ubuntu-latest
     name: Publish
     if: ${{ github.event.schedule }}
@@ -288,7 +291,7 @@ jobs:
     steps:
       - uses: actions/checkout@v4
         with:
-          token: ${{ secrets.PAT }}
+          token: ${{ secrets.GITHUB_TOKEN }}
 
       - uses: actions/download-artifact@v3
         with:
diff --git a/.github/workflows/deploy-release.yml b/.github/workflows/deploy-release.yml
index 94690f19af35..b1accb0d0d59 100644
--- a/.github/workflows/deploy-release.yml
+++ b/.github/workflows/deploy-release.yml
@@ -4,6 +4,9 @@ concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.target || 'all' }}
   cancel-in-progress: true
 
+permissions:
+  contents: write
+
 on:
   workflow_dispatch:
     inputs:
@@ -66,9 +69,8 @@ jobs:
       tag: v${{ inputs.new_version || steps.version.outputs.version }}
       version: ${{ inputs.new_version || steps.version.outputs.version }}
       build_num: ${{ steps.build_num.outputs.build_num }}
-      prev_tag: ${{ inputs.prev_tag || 'release-latest' }}
       targets: ${{ inputs.target || 'all' }}
-      release_title: ${{ inputs.custom_title || 'Release'}}
+      release_title_prefix: ${{ inputs.custom_title || 'Release'}}
     steps:
       - id: version
         # the suffix 0 allows us to provide up to 9 more hotfixes on the same day
@@ -83,7 +85,7 @@ jobs:
     with:
       build_num: ${{ needs.tags.outputs.build_num }}
       version: ${{ needs.tags.outputs.version }}
-      release_title: ${{ needs.tags.outputs.release_title }} ${{ needs.tags.outputs.tag }}
+      release_title: "${{ needs.tags.outputs.release_title_prefix }} ${{ needs.tags.outputs.tag }}"
       release_tag: ${{ needs.tags.outputs.tag }}
       targets: ${{ needs.tags.outputs.targets }}
       release: true
@@ -354,7 +356,7 @@ jobs:
  ######   ####    ##    ##     ##  #######  ########     ##         #######  ########  ######## ####  ######  ##     ## 
 
   publish:
-    environment: nightly
+    environment: release
     runs-on: ubuntu-latest
     name: Publish
     # if: ${{ github.event.schedule }}
@@ -365,7 +367,7 @@ jobs:
     steps:
       - uses: actions/checkout@v4
         with:
-          token: ${{ secrets.PAT }}
+          token: ${{ secrets.GITHUB_TOKEN }}
 
       - uses: actions/download-artifact@v3
         with:
@@ -413,7 +415,7 @@ jobs:
           # publish this full release now
           draft: true
           generate_release_notes: false
-          name: ${{ needs.tags.outputs.release_title }} ${{ needs.tags.outputs.tag }}
+          name: "${{ needs.tags.outputs.release_title_prefix }} ${{ needs.tags.outputs.tag }}"
           tag_name: ${{ needs.tags.outputs.tag }}
           body_path: CHANGELOG.md
           prerelease: false
diff --git a/app/lib/common/actions/close_room.dart b/app/lib/common/actions/close_room.dart
index da24196bdd6e..7a280816cc32 100644
--- a/app/lib/common/actions/close_room.dart
+++ b/app/lib/common/actions/close_room.dart
@@ -4,7 +4,6 @@ import 'package:acter/common/providers/sdk_provider.dart';
 import 'package:acter/common/providers/space_providers.dart';
 import 'package:acter/common/toolkit/buttons/danger_action_button.dart';
 import 'package:acter/common/utils/routes.dart';
-
 import 'package:acter/common/widgets/room/room_profile_header.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
diff --git a/app/lib/common/actions/report_content.dart b/app/lib/common/actions/report_content.dart
index 4254a01e4bf5..784fb3809b0b 100644
--- a/app/lib/common/actions/report_content.dart
+++ b/app/lib/common/actions/report_content.dart
@@ -1,7 +1,6 @@
 import 'package:acter/common/providers/chat_providers.dart';
 import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/common/providers/space_providers.dart';
-
 import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
 import 'package:acter/common/widgets/default_dialog.dart';
 import 'package:acter/common/widgets/input_text_field.dart';
diff --git a/app/lib/common/providers/common_providers.dart b/app/lib/common/providers/common_providers.dart
index 6427fad5e0f7..851242f836e7 100644
--- a/app/lib/common/providers/common_providers.dart
+++ b/app/lib/common/providers/common_providers.dart
@@ -10,7 +10,7 @@ import 'package:flutter/material.dart';
 import 'package:logging/logging.dart';
 import 'package:riverpod/riverpod.dart';
 
-final _log = Logger('a3::common::providers');
+final _log = Logger('a3::common::common_providers');
 
 // Loading Providers
 final loadingProvider = StateProvider<bool>((ref) => false);
diff --git a/app/lib/common/providers/notifiers/chat_notifiers.dart b/app/lib/common/providers/notifiers/chat_notifiers.dart
index 394290dbb2ed..3980c822ec25 100644
--- a/app/lib/common/providers/notifiers/chat_notifiers.dart
+++ b/app/lib/common/providers/notifiers/chat_notifiers.dart
@@ -8,7 +8,7 @@ import 'package:flutter/widgets.dart';
 import 'package:logging/logging.dart';
 import 'package:riverpod/riverpod.dart';
 
-final _log = Logger('a3::common::chat');
+final _log = Logger('a3::common::chat_notifiers');
 
 class AsyncConvoNotifier extends FamilyAsyncNotifier<Convo?, String> {
   late Stream<bool> _listener;
diff --git a/app/lib/common/providers/notifiers/notification_settings_notifier.dart b/app/lib/common/providers/notifiers/notification_settings_notifier.dart
index b56bb9b6bf4b..9b678cf064b5 100644
--- a/app/lib/common/providers/notifiers/notification_settings_notifier.dart
+++ b/app/lib/common/providers/notifiers/notification_settings_notifier.dart
@@ -5,7 +5,7 @@ import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:logging/logging.dart';
 import 'package:riverpod/riverpod.dart';
 
-final _log = Logger('a3::common::notification_settings');
+final _log = Logger('a3::common::notification_settings_notifier');
 
 class AsyncNotificationSettingsNotifier
     extends AsyncNotifier<NotificationSettings> {
diff --git a/app/lib/common/providers/notifiers/reactions_notifiers.dart b/app/lib/common/providers/notifiers/reactions_notifiers.dart
index 44c8156c8e62..11e6d9000a54 100644
--- a/app/lib/common/providers/notifiers/reactions_notifiers.dart
+++ b/app/lib/common/providers/notifiers/reactions_notifiers.dart
@@ -4,7 +4,7 @@ import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:logging/logging.dart';
 import 'package:riverpod/riverpod.dart';
 
-final _log = Logger('a3::common::reactions');
+final _log = Logger('a3::common::reactions_notifiers');
 
 class ReactionManagerNotifier
     extends FamilyNotifier<ReactionManager, ReactionManager> {
diff --git a/app/lib/common/providers/notifiers/room_notifiers.dart b/app/lib/common/providers/notifiers/room_notifiers.dart
index 8628bc2e619a..a2143d35ef74 100644
--- a/app/lib/common/providers/notifiers/room_notifiers.dart
+++ b/app/lib/common/providers/notifiers/room_notifiers.dart
@@ -5,10 +5,10 @@ import 'package:acter/features/home/providers/client_providers.dart';
 import 'package:acter_avatar/acter_avatar.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
-import 'package:riverpod/riverpod.dart';
 import 'package:logging/logging.dart';
+import 'package:riverpod/riverpod.dart';
 
-final _log = Logger('a3::common::room');
+final _log = Logger('a3::common::room_notifiers');
 
 class AsyncMaybeRoomNotifier extends FamilyAsyncNotifier<Room?, String> {
   late Stream<bool> _listener;
diff --git a/app/lib/common/providers/notifiers/space_notifiers.dart b/app/lib/common/providers/notifiers/space_notifiers.dart
index 151584940e11..56aa9ee4cfb7 100644
--- a/app/lib/common/providers/notifiers/space_notifiers.dart
+++ b/app/lib/common/providers/notifiers/space_notifiers.dart
@@ -2,10 +2,10 @@ import 'dart:async';
 
 import 'package:acter/features/home/providers/client_providers.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
-import 'package:riverpod/riverpod.dart';
 import 'package:logging/logging.dart';
+import 'package:riverpod/riverpod.dart';
 
-final _log = Logger('a3::common::space');
+final _log = Logger('a3::common::space_notifiers');
 
 class AsyncMaybeSpaceNotifier extends FamilyAsyncNotifier<Space?, String> {
   late Stream<bool> _listener;
diff --git a/app/lib/common/utils/utils.dart b/app/lib/common/utils/utils.dart
index 644a494af46c..5e8560479a53 100644
--- a/app/lib/common/utils/utils.dart
+++ b/app/lib/common/utils/utils.dart
@@ -3,6 +3,7 @@
 import 'dart:async';
 import 'dart:convert';
 import 'dart:math';
+
 import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/common/utils/routes.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk.dart';
@@ -13,9 +14,9 @@ import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
 import 'package:flutter_easyloading/flutter_easyloading.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:go_router/go_router.dart';
 import 'package:intl/intl.dart';
 import 'package:jiffy/jiffy.dart';
-import 'package:go_router/go_router.dart';
 import 'package:logging/logging.dart';
 import 'package:url_launcher/url_launcher.dart';
 
diff --git a/app/lib/common/widgets/chat/edit_room_description_sheet.dart b/app/lib/common/widgets/chat/edit_room_description_sheet.dart
index ec0220707b37..2be3680842ef 100644
--- a/app/lib/common/widgets/chat/edit_room_description_sheet.dart
+++ b/app/lib/common/widgets/chat/edit_room_description_sheet.dart
@@ -3,11 +3,11 @@ import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 
-final _log = Logger('a3::chat::room_description_edit_sheet');
+final _log = Logger('a3::common::chat::room_description');
 
 void showEditRoomDescriptionBottomSheet({
   required BuildContext context,
diff --git a/app/lib/common/widgets/download_button.dart b/app/lib/common/widgets/download_button.dart
deleted file mode 100644
index 6ef4c7a839ed..000000000000
--- a/app/lib/common/widgets/download_button.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-import 'dart:io';
-import 'package:path/path.dart';
-
-import 'package:file_picker/file_picker.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
-import 'package:flutter_easyloading/flutter_easyloading.dart';
-
-Future<void> downloadFile(BuildContext context, File file) async {
-  final lang = L10n.of(context);
-  final filename = basename(file.path);
-  String? outputFile = await FilePicker.platform.saveFile(
-    dialogTitle: lang.downloadFileDialogTitle,
-    fileName: filename,
-  );
-
-  if (outputFile != null) {
-    await file.copy(outputFile);
-    EasyLoading.showToast(lang.downloadFileSuccess(outputFile));
-  }
-}
-
-class DownloadButton extends StatelessWidget {
-  final File file;
-
-  const DownloadButton({super.key, required this.file});
-
-  @override
-  Widget build(BuildContext context) {
-    if (Platform.isAndroid) {
-      // Saving unfortunately crashes on Android at the moment
-      // FIXME: https://github.com/acterglobal/a3/issues/1803
-      return const SizedBox.shrink();
-    }
-    return IconButton(
-      onPressed: () => downloadFile(context, file),
-      icon: const Icon(Icons.download_rounded),
-    );
-  }
-}
diff --git a/app/lib/common/widgets/event/event_selector_drawer.dart b/app/lib/common/widgets/event/event_selector_drawer.dart
index d140b4e2ed06..854c4883d337 100644
--- a/app/lib/common/widgets/event/event_selector_drawer.dart
+++ b/app/lib/common/widgets/event/event_selector_drawer.dart
@@ -3,7 +3,11 @@ import 'package:acter/features/events/widgets/event_item.dart';
 import 'package:acter/features/events/widgets/skeletons/event_list_skeleton_widget.dart';
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::common::cal_event::select_drawer');
 
 const Key selectEventDrawerKey = Key('event-widgets-select-event-drawer');
 
@@ -56,28 +60,28 @@ Future<String?> selectEventDrawer({
                       : ListView.builder(
                           padding: const EdgeInsets.all(8),
                           itemCount: eventsList.length,
-                          itemBuilder: (context, index) {
-                            final event = eventsList[index];
-                            return EventItem(
-                              event: event,
-                              isShowRsvp: false,
-                              onTapEventItem: (event) {
-                                Navigator.pop(context, event);
-                              },
-                            );
-                          },
+                          itemBuilder: (context, index) => EventItem(
+                            event: eventsList[index],
+                            isShowRsvp: false,
+                            onTapEventItem: (event) {
+                              Navigator.pop(context, event);
+                            },
+                          ),
                         ),
                 ),
               ],
             );
           },
           error: (error, stack) {
+            _log.severe('Failed to load all cal events', error, stack);
             return Center(
-              child: Text('Failed to load: $error'),
+              child: Text(L10n.of(context).failedToLoadEventsDueTo(error)),
             );
           },
-          loading: () =>
-              const SizedBox(height: 500, child: EventListSkeleton()),
+          loading: () => const SizedBox(
+            height: 500,
+            child: EventListSkeleton(),
+          ),
         );
       },
     ),
diff --git a/app/lib/common/widgets/image_dialog.dart b/app/lib/common/widgets/image_dialog.dart
index be4985c12a18..9dd4ddd99963 100644
--- a/app/lib/common/widgets/image_dialog.dart
+++ b/app/lib/common/widgets/image_dialog.dart
@@ -1,10 +1,8 @@
 import 'dart:io';
-import 'package:acter/common/themes/app_theme.dart';
-import 'package:acter/common/widgets/download_button.dart';
+import 'package:acter/features/files/widgets/share_file_button.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:share_plus/share_plus.dart';
 import 'package:zoom_hover_pinch_image/zoom_hover_pinch_image.dart';
 
 class ImageDialog extends ConsumerWidget {
@@ -19,7 +17,6 @@ class ImageDialog extends ConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    final canShare = !isDesktop;
     return Dialog(
       insetPadding: EdgeInsets.zero,
       child: Scaffold(
@@ -32,14 +29,7 @@ class ImageDialog extends ConsumerWidget {
             overflow: TextOverflow.ellipsis,
           ),
           actions: [
-            if (canShare)
-              IconButton(
-                onPressed: () {
-                  Share.shareXFiles([XFile(imageFile.path)]);
-                },
-                icon: const Icon(Icons.share),
-              ),
-            DownloadButton(file: imageFile),
+            ShareFileButton(file: imageFile),
             IconButton(
               onPressed: () => Navigator.pop(context),
               icon: const Icon(Icons.close),
diff --git a/app/lib/common/widgets/room/select_room_drawer.dart b/app/lib/common/widgets/room/select_room_drawer.dart
index 6b55dceb705a..6789735a2eb5 100644
--- a/app/lib/common/widgets/room/select_room_drawer.dart
+++ b/app/lib/common/widgets/room/select_room_drawer.dart
@@ -1,14 +1,16 @@
 import 'package:acter/common/providers/chat_providers.dart';
 import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/common/providers/space_providers.dart';
-
 import 'package:acter/common/widgets/room/brief_room_list_entry.dart';
 import 'package:acter_avatar/acter_avatar.dart';
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:path/path.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
+
+final _log = Logger('a3::common::room::select_drawer');
 
 // ChildRoomType configures the sub child type of the `Spaces`
 enum RoomType {
@@ -143,14 +145,14 @@ class _SelectRoomDrawerState extends ConsumerState<SelectRoomDrawer> {
 
 //Show space list based on the search term
   Widget searchedRoomsList(BuildContext context) {
-    final searchedrooms = ref.watch(
+    final searched = ref.watch(
       switch (widget.roomType) {
         RoomType.space => searchedSpacesProvider,
         RoomType.groupChat => roomSearchedChatsProvider,
       },
     );
 
-    return searchedrooms.when(
+    return searched.when(
       data: (rooms) {
         if (rooms.isEmpty) {
           return Center(
@@ -164,7 +166,12 @@ class _SelectRoomDrawerState extends ConsumerState<SelectRoomDrawer> {
         heightFactor: 10,
         child: CircularProgressIndicator(),
       ),
-      error: (e, s) => Center(child: Text(L10n.of(context).searchingFailed(e))),
+      error: (e, s) {
+        _log.severe('Failed to search space or convo', e, s);
+        return Center(
+          child: Text(L10n.of(context).searchingFailed(e)),
+        );
+      },
     );
   }
 
diff --git a/app/lib/common/widgets/spaces/has_space_permission.dart b/app/lib/common/widgets/spaces/has_space_permission.dart
index f99b38c03087..a8f29140c15e 100644
--- a/app/lib/common/widgets/spaces/has_space_permission.dart
+++ b/app/lib/common/widgets/spaces/has_space_permission.dart
@@ -1,6 +1,9 @@
 import 'package:acter/common/providers/room_providers.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::common::spaces::has_permission');
 
 class HasSpacePermission extends ConsumerWidget {
   final String spaceId;
@@ -22,7 +25,10 @@ class HasSpacePermission extends ConsumerWidget {
     return ref.watch(roomMembershipProvider(spaceId)).when(
           data: (membership) =>
               membership?.canString(permission) == true ? child : otherwise,
-          error: (e, s) => otherwise,
+          error: (e, s) {
+            _log.severe('Failed to load membership', e, s);
+            return otherwise;
+          },
           loading: () => otherwise,
         );
   }
diff --git a/app/lib/common/widgets/spaces/select_space_form_field.dart b/app/lib/common/widgets/spaces/select_space_form_field.dart
index 3fa49b8963b5..a3f2bee7a873 100644
--- a/app/lib/common/widgets/spaces/select_space_form_field.dart
+++ b/app/lib/common/widgets/spaces/select_space_form_field.dart
@@ -5,8 +5,11 @@ import 'package:acter_avatar/acter_avatar.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::common::spaces::select_form_field');
+
 class SelectSpaceFormField extends ConsumerWidget {
   static Key openKey = const Key('select-space-form-field-open');
 
@@ -103,7 +106,10 @@ class SelectSpaceFormField extends ConsumerWidget {
                   useCompatView ? selectSpace(context, ref) : null,
             )
           : Text(currentSelectedSpace!),
-      error: (e, s) => Text(L10n.of(context).errorLoading(e)),
+      error: (e, s) {
+        _log.severe('Failed to load the details of selected space', e, s);
+        return Text(L10n.of(context).loadingFailed(e));
+      },
       loading: () => Skeletonizer(
         child: Chip(
           avatar: ActerAvatar(
diff --git a/app/lib/common/widgets/spaces/space_info.dart b/app/lib/common/widgets/spaces/space_info.dart
index 0c97d60aea11..a168e8018b2e 100644
--- a/app/lib/common/widgets/spaces/space_info.dart
+++ b/app/lib/common/widgets/spaces/space_info.dart
@@ -3,10 +3,13 @@ import 'package:acter/common/widgets/visibility/visibility_chip.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::common::spaces::info');
+
 final isActerSpaceForSpace =
     FutureProvider.autoDispose.family<bool, Space>((ref, space) async {
   return await space.isActerSpace();
@@ -33,7 +36,10 @@ class SpaceInfo extends ConsumerWidget {
           ],
         );
       },
-      error: (e, s) => Text(L10n.of(context).error(e)),
+      error: (e, s) {
+        _log.severe('Failed to load space', e, s);
+        return Text(L10n.of(context).loadingFailed(e));
+      },
       loading: () => skeletonUI(),
     );
   }
diff --git a/app/lib/common/widgets/user_builder.dart b/app/lib/common/widgets/user_builder.dart
index ddfe7db4c1a3..80101575ffd5 100644
--- a/app/lib/common/widgets/user_builder.dart
+++ b/app/lib/common/widgets/user_builder.dart
@@ -2,16 +2,15 @@ import 'dart:typed_data';
 
 import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/common/themes/colors/color_scheme.dart';
-
 import 'package:acter_avatar/acter_avatar.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
-import 'package:skeletonizer/skeletonizer.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
+import 'package:skeletonizer/skeletonizer.dart';
 
 final _log = Logger('a3::common::user');
 
diff --git a/app/lib/common/widgets/video_dialog.dart b/app/lib/common/widgets/video_dialog.dart
index 4a45b5f97bf2..ef59a5e6ee1d 100644
--- a/app/lib/common/widgets/video_dialog.dart
+++ b/app/lib/common/widgets/video_dialog.dart
@@ -1,9 +1,7 @@
 import 'dart:io';
-import 'package:acter/common/themes/app_theme.dart';
 import 'package:acter/common/widgets/acter_video_player.dart';
-import 'package:acter/common/widgets/download_button.dart';
+import 'package:acter/features/files/widgets/share_file_button.dart';
 import 'package:flutter/material.dart';
-import 'package:share_plus/share_plus.dart';
 
 class VideoDialog extends StatelessWidget {
   final String title;
@@ -17,7 +15,6 @@ class VideoDialog extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final canShare = !isDesktop;
     return Dialog(
       insetPadding: EdgeInsets.zero,
       child: Container(
@@ -37,14 +34,7 @@ class VideoDialog extends StatelessWidget {
                     overflow: TextOverflow.ellipsis,
                   ),
                 ),
-                if (canShare)
-                  IconButton(
-                    onPressed: () {
-                      Share.shareXFiles([XFile(videoFile.path)]);
-                    },
-                    icon: const Icon(Icons.share),
-                  ),
-                DownloadButton(file: videoFile),
+                ShareFileButton(file: videoFile),
                 IconButton(
                   onPressed: () => Navigator.pop(context),
                   icon: const Icon(Icons.close),
diff --git a/app/lib/common/widgets/visibility/visibility_chip.dart b/app/lib/common/widgets/visibility/visibility_chip.dart
index ded3913a308c..ec62a2c34d95 100644
--- a/app/lib/common/widgets/visibility/visibility_chip.dart
+++ b/app/lib/common/widgets/visibility/visibility_chip.dart
@@ -2,9 +2,12 @@ import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/common/utils/utils.dart';
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
+
+final _log = Logger('a3::common::visibility::chip');
 
 class VisibilityChip extends ConsumerWidget {
   final String roomId;
@@ -18,9 +21,12 @@ class VisibilityChip extends ConsumerWidget {
       data: (visibility) {
         return renderSpaceChip(context, visibility);
       },
-      error: (error, st) => Chip(
-        label: Text(L10n.of(context).loadingFailed(error)),
-      ),
+      error: (error, st) {
+        _log.severe('Failed to load room visibility', error, st);
+        return Chip(
+          label: Text(L10n.of(context).loadingFailed(error)),
+        );
+      },
       loading: () => renderLoading(),
     );
   }
diff --git a/app/lib/features/activities/widgets/invitation_card.dart b/app/lib/features/activities/widgets/invitation_card.dart
index 37a3db527320..e5ad545da390 100644
--- a/app/lib/features/activities/widgets/invitation_card.dart
+++ b/app/lib/features/activities/widgets/invitation_card.dart
@@ -1,5 +1,4 @@
 import 'package:acter/common/providers/room_providers.dart';
-
 import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
 import 'package:acter/features/activities/providers/invitations_providers.dart';
 import 'package:acter/features/home/providers/client_providers.dart';
diff --git a/app/lib/features/attachments/providers/notifiers/attachments_notifiers.dart b/app/lib/features/attachments/providers/notifiers/attachments_notifiers.dart
index 4990ec8e707f..b60e285677cd 100644
--- a/app/lib/features/attachments/providers/notifiers/attachments_notifiers.dart
+++ b/app/lib/features/attachments/providers/notifiers/attachments_notifiers.dart
@@ -7,7 +7,7 @@ import 'package:logging/logging.dart';
 import 'package:path_provider/path_provider.dart';
 import 'package:riverpod/riverpod.dart';
 
-final _log = Logger('a3::common::attachments');
+final _log = Logger('a3::attachments::notifiers');
 
 class AttachmentsManagerNotifier extends AutoDisposeFamilyAsyncNotifier<
     AttachmentsManager, Future<AttachmentsManager>> {
diff --git a/app/lib/features/attachments/widgets/attachment_item.dart b/app/lib/features/attachments/widgets/attachment_item.dart
index 312849c23ea8..0ed4aed13bb9 100644
--- a/app/lib/features/attachments/widgets/attachment_item.dart
+++ b/app/lib/features/attachments/widgets/attachment_item.dart
@@ -1,19 +1,17 @@
 import 'package:acter/common/actions/redact_content.dart';
 import 'package:acter/common/models/attachment_media_state/attachment_media_state.dart';
 import 'package:acter/common/models/types.dart';
-import 'package:acter/common/themes/app_theme.dart';
 import 'package:acter/common/themes/colors/color_scheme.dart';
 import 'package:acter/common/utils/utils.dart';
-import 'package:acter/common/widgets/download_button.dart';
 import 'package:acter/common/widgets/image_dialog.dart';
 import 'package:acter/common/widgets/video_dialog.dart';
 import 'package:acter/features/attachments/providers/attachment_providers.dart';
+import 'package:acter/features/files/actions/file_share.dart';
 import 'package:acter/features/pins/actions/attachment_leading_icon.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart' show Attachment;
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:share_plus/share_plus.dart';
 
 // Attachment item UI
 class AttachmentItem extends ConsumerWidget {
@@ -182,11 +180,7 @@ class AttachmentItem extends ConsumerWidget {
       }
       // If attachment is downloaded and file or others
       else {
-        if (isDesktop) {
-          downloadFile(context, mediaState.mediaFile!);
-        } else {
-          Share.shareXFiles([XFile(mediaState.mediaFile!.path)]);
-        }
+        openFileShareDialog(context: context, file: mediaState.mediaFile!);
       }
     }
   }
diff --git a/app/lib/features/attachments/widgets/attachment_section.dart b/app/lib/features/attachments/widgets/attachment_section.dart
index 84e0466def1d..ef00f3eaad56 100644
--- a/app/lib/features/attachments/widgets/attachment_section.dart
+++ b/app/lib/features/attachments/widgets/attachment_section.dart
@@ -10,8 +10,11 @@ import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::attachments::section');
+
 class AttachmentSectionWidget extends ConsumerWidget {
   static const attachmentsKey = Key('attachments');
   static const redactBtnKey = Key('attachments-redact-btn');
@@ -31,7 +34,10 @@ class AttachmentSectionWidget extends ConsumerWidget {
             attachmentManager: manager,
             key: attachmentsKey,
           ),
-          error: (e, st) => onError(context, e),
+          error: (e, st) {
+            _log.severe('Failed to load attachment manager', e, st);
+            return onError(context, e);
+          },
           loading: () => loading(context),
         );
   }
@@ -70,7 +76,10 @@ class FoundAttachmentSectionWidget extends ConsumerWidget {
 
     return attachments.when(
       data: (list) => attachmentData(list, context, ref),
-      error: (err, st) => Text(L10n.of(context).errorLoadingAttachments(err)),
+      error: (err, st) {
+        _log.severe('Failed to load attachments', err, st);
+        return Text(L10n.of(context).errorLoadingAttachments(err));
+      },
       loading: () => const Skeletonizer(
         child: Wrap(
           spacing: 5.0,
diff --git a/app/lib/features/attachments/widgets/views/file_view.dart b/app/lib/features/attachments/widgets/views/file_view.dart
index 9e055dc5fee6..0f8157b701be 100644
--- a/app/lib/features/attachments/widgets/views/file_view.dart
+++ b/app/lib/features/attachments/widgets/views/file_view.dart
@@ -1,12 +1,10 @@
 import 'package:acter/common/models/attachment_media_state/attachment_media_state.dart';
-import 'package:acter/common/themes/app_theme.dart';
-import 'package:acter/common/widgets/download_button.dart';
 import 'package:acter/features/attachments/providers/attachment_providers.dart';
+import 'package:acter/features/files/actions/file_share.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart' show Attachment;
 import 'package:flutter/material.dart';
 import 'package:flutter_chat_ui/flutter_chat_ui.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:share_plus/share_plus.dart';
 
 class FileView extends ConsumerWidget {
   final Attachment attachment;
@@ -47,11 +45,7 @@ class FileView extends ConsumerWidget {
     return InkWell(
       onTap: () async {
         if (mediaState.mediaFile != null) {
-          if (isDesktop) {
-            downloadFile(context, mediaState.mediaFile!);
-          } else {
-            Share.shareXFiles([XFile(mediaState.mediaFile!.path)]);
-          }
+          openFileShareDialog(context: context, file: mediaState.mediaFile!);
         } else {
           ref
               .read(attachmentMediaStateProvider(attachment).notifier)
@@ -97,11 +91,10 @@ class FileView extends ConsumerWidget {
     return InkWell(
       onTap: openView!
           ? () async {
-              if (isDesktop) {
-                downloadFile(context, mediaState.mediaFile!);
-              } else {
-                Share.shareXFiles([XFile(mediaState.mediaFile!.path)]);
-              }
+              openFileShareDialog(
+                context: context,
+                file: mediaState.mediaFile!,
+              );
             }
           : null,
       child: ClipRRect(
diff --git a/app/lib/features/auth/pages/forgot_password.dart b/app/lib/features/auth/pages/forgot_password.dart
index 4034e9d45001..b87305321ae3 100644
--- a/app/lib/features/auth/pages/forgot_password.dart
+++ b/app/lib/features/auth/pages/forgot_password.dart
@@ -14,7 +14,7 @@ import 'package:flutter_svg/flutter_svg.dart';
 import 'package:go_router/go_router.dart';
 import 'package:logging/logging.dart';
 
-final _log = Logger('a3::auth::passwordReset');
+final _log = Logger('a3::auth::forgot_password');
 
 class ForgotPassword extends ConsumerStatefulWidget {
   static Key passwordKey = const Key('pw-reset-password-field');
diff --git a/app/lib/features/auth/pages/register_page.dart b/app/lib/features/auth/pages/register_page.dart
index 475f6c782411..8e73a0191272 100644
--- a/app/lib/features/auth/pages/register_page.dart
+++ b/app/lib/features/auth/pages/register_page.dart
@@ -1,7 +1,6 @@
 import 'package:acter/common/providers/network_provider.dart';
 import 'package:acter/common/themes/colors/color_scheme.dart';
 import 'package:acter/common/toolkit/buttons/inline_text_button.dart';
-
 import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
 import 'package:acter/common/utils/constants.dart';
 import 'package:acter/common/utils/routes.dart';
@@ -19,7 +18,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
 import 'package:logging/logging.dart';
 
-final _log = Logger('Register');
+final _log = Logger('a3::auth::register');
 
 Future<void> tryRedeem(SuperInvites superInvites, String token) async {
   // try to redeem the token in a fire-and-forget-manner
diff --git a/app/lib/features/auth/providers/notifiers/auth_notifier.dart b/app/lib/features/auth/providers/notifiers/auth_notifier.dart
index b84278c15485..8fae4381464f 100644
--- a/app/lib/features/auth/providers/notifiers/auth_notifier.dart
+++ b/app/lib/features/auth/providers/notifiers/auth_notifier.dart
@@ -7,7 +7,7 @@ import 'package:go_router/go_router.dart';
 import 'package:logging/logging.dart';
 import 'package:riverpod/riverpod.dart';
 
-final _log = Logger('a3::onboarding::auth');
+final _log = Logger('a3::auth::notifier');
 
 class AuthStateNotifier extends StateNotifier<bool> {
   final Ref ref;
diff --git a/app/lib/features/bug_report/pages/bug_report_page.dart b/app/lib/features/bug_report/pages/bug_report_page.dart
index 91e39f6a17b2..38ec4481f65f 100644
--- a/app/lib/features/bug_report/pages/bug_report_page.dart
+++ b/app/lib/features/bug_report/pages/bug_report_page.dart
@@ -1,15 +1,16 @@
 import 'dart:convert';
 import 'dart:io';
 import 'dart:math';
+
+import 'package:acter/common/providers/common_providers.dart';
 import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
+import 'package:acter/common/utils/utils.dart';
 import 'package:acter/config/env.g.dart';
 import 'package:acter/config/setup.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
-import 'package:acter/common/providers/common_providers.dart';
-import 'package:acter/common/utils/utils.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
 import 'package:http/http.dart' as http;
diff --git a/app/lib/features/chat/pages/room_page.dart b/app/lib/features/chat/pages/room_page.dart
index f836e35bc6ef..36480702e13a 100644
--- a/app/lib/features/chat/pages/room_page.dart
+++ b/app/lib/features/chat/pages/room_page.dart
@@ -28,9 +28,12 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
 import 'package:intl/intl.dart';
+import 'package:logging/logging.dart';
 import 'package:scroll_to_index/scroll_to_index.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::chat::room');
+
 class RoomPage extends ConsumerWidget {
   static const roomPageKey = Key('chat-room-page');
   final String roomId;
@@ -75,9 +78,10 @@ class RoomPage extends ConsumerWidget {
                 );
               },
               skipLoadingOnReload: false,
-              error: (error, stackTrace) => Text(
-                L10n.of(context).errorLoadingMembersCount(error),
-              ),
+              error: (e, s) {
+                _log.severe('Failed to load active members', e, s);
+                return Text(L10n.of(context).errorLoadingMembersCount(e));
+              },
               loading: () => Skeletonizer(
                 child: Text(L10n.of(context).membersCount(100)),
               ),
diff --git a/app/lib/features/chat/pages/room_profile_page.dart b/app/lib/features/chat/pages/room_profile_page.dart
index 51a27d84718d..94bea2fb8479 100644
--- a/app/lib/features/chat/pages/room_profile_page.dart
+++ b/app/lib/features/chat/pages/room_profile_page.dart
@@ -5,9 +5,9 @@ import 'package:acter/common/providers/space_providers.dart';
 import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
 import 'package:acter/common/utils/routes.dart';
 import 'package:acter/common/utils/utils.dart';
+import 'package:acter/common/widgets/default_dialog.dart';
 import 'package:acter/common/widgets/edit_plain_description_sheet.dart';
 import 'package:acter/common/widgets/edit_title_sheet.dart';
-import 'package:acter/common/widgets/default_dialog.dart';
 import 'package:acter/common/widgets/visibility/visibility_chip.dart';
 import 'package:acter/features/chat/widgets/member_list.dart';
 import 'package:acter/features/chat/widgets/room_avatar.dart';
@@ -26,7 +26,7 @@ import 'package:settings_ui/settings_ui.dart';
 import 'package:share_plus/share_plus.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
-final _log = Logger('a3::chat::room_profile_page');
+final _log = Logger('a3::chat::room_profile');
 
 class RoomProfilePage extends ConsumerStatefulWidget {
   final String roomId;
@@ -272,11 +272,7 @@ class _RoomProfilePageState extends ConsumerState<RoomProfilePage> {
     );
   }
 
-  Widget _actions(
-    BuildContext context,
-    Convo? convo,
-    bool isDirectChat,
-  ) {
+  Widget _actions(BuildContext context, Convo? convo, bool isDirectChat) {
     final convoLoader = ref.watch(chatProvider(widget.roomId));
     final myMembership = ref.watch(roomMembershipProvider(widget.roomId));
 
@@ -294,15 +290,18 @@ class _RoomProfilePageState extends ConsumerState<RoomProfilePage> {
               onTap: () async => await conv?.setBookmarked(!isBookmarked),
             );
           },
-          error: (e, st) => Skeletonizer(
-            child: IconButton.filled(
-              icon: const Icon(
-                Icons.bookmark_add_outlined,
-                size: 20,
+          error: (e, st) {
+            _log.severe('Failed to load convo', e, st);
+            return Skeletonizer(
+              child: IconButton.filled(
+                icon: const Icon(
+                  Icons.bookmark_add_outlined,
+                  size: 20,
+                ),
+                onPressed: () {},
               ),
-              onPressed: () {},
-            ),
-          ),
+            );
+          },
           loading: () => ActionItemSkeleton(
             iconData: Icons.bookmark_add_outlined,
             actionName: L10n.of(context).bookmark,
@@ -325,7 +324,10 @@ class _RoomProfilePageState extends ConsumerState<RoomProfilePage> {
               onTap: () => _handleInvite(membership),
             );
           },
-          error: (e, st) => Text(L10n.of(context).errorLoadingTileDueTo(e)),
+          error: (e, st) {
+            _log.severe('Failed to load room membership', e, st);
+            return Text(L10n.of(context).errorLoadingTileDueTo(e));
+          },
           loading: () => ActionItemSkeleton(
             iconData: Atlas.user_plus_thin,
             actionName: L10n.of(context).invite,
@@ -468,8 +470,10 @@ class _RoomProfilePageState extends ConsumerState<RoomProfilePage> {
             loading: () => Skeletonizer(
               child: Text(L10n.of(context).membersCount(0)),
             ),
-            error: (error, stackTrace) =>
-                Text(L10n.of(context).errorLoadingMembersCount(error)),
+            error: (e, st) {
+              _log.severe('Failed to load room members', e, st);
+              return Text(L10n.of(context).errorLoadingMembersCount(e));
+            },
           ),
           MemberList(roomId: widget.roomId),
         ],
diff --git a/app/lib/features/chat/providers/notifiers/chat_room_notifier.dart b/app/lib/features/chat/providers/notifiers/chat_room_notifier.dart
index c360dc3f2570..0145f323dda6 100644
--- a/app/lib/features/chat/providers/notifiers/chat_room_notifier.dart
+++ b/app/lib/features/chat/providers/notifiers/chat_room_notifier.dart
@@ -10,8 +10,8 @@ import 'package:acter/features/chat/utils.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
-import 'package:riverpod/riverpod.dart';
 import 'package:logging/logging.dart';
+import 'package:riverpod/riverpod.dart';
 
 final _log = Logger('a3::chat::room_notifier');
 
@@ -231,8 +231,11 @@ class ChatRoomNotifier extends StateNotifier<ChatRoomState> {
     try {
       roomMsg = await timeline.getMessage(originalId);
     } catch (error, stack) {
-      _log.severe('Failing to load reference $replyId (from $originalId)',
-          error, stack,);
+      _log.severe(
+        'Failing to load reference $replyId (from $originalId)',
+        error,
+        stack,
+      );
       return;
     }
 
diff --git a/app/lib/features/chat/providers/notifiers/media_chat_notifier.dart b/app/lib/features/chat/providers/notifiers/media_chat_notifier.dart
index 082474df7b1e..e15cb8ede05b 100644
--- a/app/lib/features/chat/providers/notifiers/media_chat_notifier.dart
+++ b/app/lib/features/chat/providers/notifiers/media_chat_notifier.dart
@@ -6,10 +6,10 @@ import 'package:acter/features/chat/models/media_chat_state/media_chat_state.dar
 import 'package:acter/features/chat/providers/chat_providers.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:fc_native_video_thumbnail/fc_native_video_thumbnail.dart';
-import 'package:path_provider/path_provider.dart';
-import 'package:riverpod/riverpod.dart';
 import 'package:logging/logging.dart';
 import 'package:path/path.dart' as p;
+import 'package:path_provider/path_provider.dart';
+import 'package:riverpod/riverpod.dart';
 
 final _log = Logger('a3::chat::media_chat_notifier');
 
diff --git a/app/lib/features/chat/widgets/chats_list.dart b/app/lib/features/chat/widgets/chats_list.dart
index 9487cf63800e..bafa2e716b62 100644
--- a/app/lib/features/chat/widgets/chats_list.dart
+++ b/app/lib/features/chat/widgets/chats_list.dart
@@ -6,11 +6,14 @@ import 'package:acter/common/widgets/empty_state_widget.dart';
 import 'package:acter/features/chat/providers/chat_providers.dart';
 import 'package:acter/features/chat/providers/room_list_filter_provider.dart';
 import 'package:acter/features/home/providers/client_providers.dart';
+import 'package:diffutil_dart/diffutil.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
-import 'package:diffutil_dart/diffutil.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::chat::chats_list');
 
 class ChatsList extends ConsumerStatefulWidget {
   final Function(String)? onSelected;
@@ -48,14 +51,15 @@ class _ChatsListConsumerState extends ConsumerState<ChatsList> {
                 child: CircularProgressIndicator(),
               ),
             ),
-            error: (e, s) => SliverToBoxAdapter(
-              child: Center(
-                heightFactor: 10,
-                child: Text(
-                  '${L10n.of(context).searchingFailed}: $e',
+            error: (e, s) {
+              _log.severe('Failed to filter convos', e, s);
+              return SliverToBoxAdapter(
+                child: Center(
+                  heightFactor: 10,
+                  child: Text(L10n.of(context).searchingFailed(e)),
                 ),
-              ),
-            ),
+              );
+            },
             skipLoadingOnReload: true,
           );
     }
diff --git a/app/lib/features/chat/widgets/create_chat.dart b/app/lib/features/chat/widgets/create_chat.dart
index 9507c6841c96..8e61da6cd1f2 100644
--- a/app/lib/features/chat/widgets/create_chat.dart
+++ b/app/lib/features/chat/widgets/create_chat.dart
@@ -1,23 +1,23 @@
 import 'dart:io';
 
 import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
-import 'package:acter/features/chat/actions/create_chat.dart';
-import 'package:acter/common/widgets/user_builder.dart';
-import 'package:acter/features/invite_members/providers/invite_providers.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:acter/common/providers/space_providers.dart';
 import 'package:acter/common/utils/routes.dart';
 import 'package:acter/common/utils/utils.dart';
 import 'package:acter/common/widgets/input_text_field.dart';
 import 'package:acter/common/widgets/spaces/select_space_form_field.dart';
+import 'package:acter/common/widgets/user_builder.dart';
+import 'package:acter/features/chat/actions/create_chat.dart';
 import 'package:acter/features/chat/providers/create_chat_providers.dart';
 import 'package:acter/features/home/providers/client_providers.dart';
+import 'package:acter/features/invite_members/providers/invite_providers.dart';
 import 'package:acter_avatar/acter_avatar.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart' as ffi;
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:file_picker/file_picker.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
 import 'package:logging/logging.dart';
@@ -378,7 +378,10 @@ class _CreateChatWidgetConsumerState extends ConsumerState<_CreateChatWidget> {
                       onUp: _onUp,
                     ),
                   ),
-            error: (e, st) => Text(L10n.of(context).errorLoadingUsers(e)),
+            error: (e, st) {
+              _log.severe('Failed to search users', e, st);
+              return Text(L10n.of(context).errorLoadingUsers(e));
+            },
             loading: () => const Center(
               heightFactor: 5,
               child: CircularProgressIndicator(),
@@ -716,7 +719,10 @@ class _UserWidget extends ConsumerWidget {
             ),
           );
         },
-        error: (e, st) => Text(L10n.of(context).errorLoadingAvatar(e)),
+        error: (e, st) {
+          _log.severe('Failed to load binary data of avatar', e, st);
+          return Text(L10n.of(context).errorLoadingAvatar(e));
+        },
         loading: () => Skeletonizer(
           child: ActerAvatar(
             options: AvatarOptions.DM(
diff --git a/app/lib/features/chat/widgets/custom_input.dart b/app/lib/features/chat/widgets/custom_input.dart
index b9269726c20f..88cc8eb73ab8 100644
--- a/app/lib/features/chat/widgets/custom_input.dart
+++ b/app/lib/features/chat/widgets/custom_input.dart
@@ -3,7 +3,6 @@ import 'dart:io';
 import 'package:acter/common/models/types.dart';
 import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/common/themes/app_theme.dart';
-
 import 'package:acter/common/widgets/emoji_picker_widget.dart';
 import 'package:acter/common/widgets/frost_effect.dart';
 import 'package:acter/features/attachments/actions/select_attachment.dart';
diff --git a/app/lib/features/chat/widgets/file_message_builder.dart b/app/lib/features/chat/widgets/file_message_builder.dart
index 316a37dec992..5554f310e95d 100644
--- a/app/lib/features/chat/widgets/file_message_builder.dart
+++ b/app/lib/features/chat/widgets/file_message_builder.dart
@@ -1,14 +1,12 @@
 import 'package:acter/common/models/types.dart';
-import 'package:acter/common/themes/app_theme.dart';
-import 'package:acter/common/widgets/download_button.dart';
 import 'package:acter/features/chat/models/media_chat_state/media_chat_state.dart';
 import 'package:acter/features/chat/providers/chat_providers.dart';
+import 'package:acter/features/files/actions/file_share.dart';
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
 import 'package:flutter_chat_ui/flutter_chat_ui.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:share_plus/share_plus.dart';
 
 class FileMessageBuilder extends ConsumerWidget {
   final types.FileMessage message;
@@ -31,11 +29,7 @@ class FileMessageBuilder extends ConsumerWidget {
     return InkWell(
       onTap: () async {
         if (mediaState.mediaFile != null) {
-          if (isDesktop) {
-            downloadFile(context, mediaState.mediaFile!);
-          } else {
-            Share.shareXFiles([XFile(mediaState.mediaFile!.path)]);
-          }
+          openFileShareDialog(context: context, file: mediaState.mediaFile!);
         } else {
           await ref
               .read(mediaChatStateProvider(messageInfo).notifier)
diff --git a/app/lib/features/chat/widgets/member_list.dart b/app/lib/features/chat/widgets/member_list.dart
index 977da52f315a..9142da8acb38 100644
--- a/app/lib/features/chat/widgets/member_list.dart
+++ b/app/lib/features/chat/widgets/member_list.dart
@@ -2,8 +2,11 @@ import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/features/chat/widgets/skeletons/members_list_skeleton_widget.dart';
 import 'package:acter/features/member/widgets/member_list_entry.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::chat::member_list');
 
 class MemberList extends ConsumerWidget {
   final String roomId;
@@ -21,9 +24,7 @@ class MemberList extends ConsumerWidget {
       data: (members) {
         if (members.isEmpty) {
           return Center(
-            child: Text(
-              L10n.of(context).noMembersFound,
-            ),
+            child: Text(L10n.of(context).noMembersFound),
           );
         }
         return ListView.builder(
@@ -42,9 +43,12 @@ class MemberList extends ConsumerWidget {
           },
         );
       },
-      error: (error, stack) => Center(
-        child: Text(L10n.of(context).loadingFailed(error)),
-      ),
+      error: (error, stack) {
+        _log.severe('Failed to load room members', error, stack);
+        return Center(
+          child: Text(L10n.of(context).loadingFailed(error)),
+        );
+      },
       loading: () => const MembersListSkeleton(),
     );
   }
diff --git a/app/lib/features/chat/widgets/mention_profile_builder.dart b/app/lib/features/chat/widgets/mention_profile_builder.dart
index adef6abd8d27..fd5e4c771348 100644
--- a/app/lib/features/chat/widgets/mention_profile_builder.dart
+++ b/app/lib/features/chat/widgets/mention_profile_builder.dart
@@ -5,9 +5,12 @@ import 'package:acter/features/home/providers/client_providers.dart';
 import 'package:acter_avatar/acter_avatar.dart';
 import 'package:acter_trigger_auto_complete/acter_trigger_autocomplete.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
+
+final _log = Logger('a3::chat::mention_profile_builder');
 
 class MentionProfileBuilder extends ConsumerWidget {
   final BuildContext context;
@@ -23,7 +26,7 @@ class MentionProfileBuilder extends ConsumerWidget {
   Widget build(BuildContext context, WidgetRef ref) {
     final client = ref.watch(alwaysClientProvider);
     final userId = client.userId().toString();
-    var memberIds = ref.watch(membersIdsProvider((roomQuery.roomId)));
+    var memberIds = ref.watch(membersIdsProvider(roomQuery.roomId));
     return memberIds.when(
       loading: () => Skeletonizer(
         child: SizedBox(
@@ -31,7 +34,10 @@ class MentionProfileBuilder extends ConsumerWidget {
           child: Card(child: ListView()),
         ),
       ),
-      error: (error, st) => ErrorWidget(L10n.of(context).failedToLoad(error)),
+      error: (error, st) {
+        _log.severe('Failed to load room members', error, st);
+        return ErrorWidget(L10n.of(context).loadingFailed(error));
+      },
       data: (data) {
         final users = data.fold<Map<String, String>>({}, (map, uId) {
           if (uId != userId) {
diff --git a/app/lib/features/chat/widgets/message_actions.dart b/app/lib/features/chat/widgets/message_actions.dart
index c7b3305aba03..34e6ec5a38a9 100644
--- a/app/lib/features/chat/widgets/message_actions.dart
+++ b/app/lib/features/chat/widgets/message_actions.dart
@@ -1,10 +1,9 @@
+import 'package:acter/common/actions/report_content.dart';
 import 'package:acter/common/providers/chat_providers.dart';
 import 'package:acter/common/providers/common_providers.dart';
 import 'package:acter/common/providers/room_providers.dart';
-
 import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
 import 'package:acter/common/widgets/default_dialog.dart';
-import 'package:acter/common/actions/report_content.dart';
 import 'package:acter/features/chat/providers/chat_providers.dart';
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
diff --git a/app/lib/features/chat/widgets/room_avatar.dart b/app/lib/features/chat/widgets/room_avatar.dart
index 4d4533c228e0..93e6ad5f8457 100644
--- a/app/lib/features/chat/widgets/room_avatar.dart
+++ b/app/lib/features/chat/widgets/room_avatar.dart
@@ -3,10 +3,13 @@ import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/features/home/providers/client_providers.dart';
 import 'package:acter_avatar/acter_avatar.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::chat::room_avatar');
+
 class RoomAvatar extends ConsumerWidget {
   final String roomId;
   final double avatarSize;
@@ -107,8 +110,10 @@ class RoomAvatar extends ConsumerWidget {
         }
       },
       skipLoadingOnReload: false,
-      error: (error, stackTrace) =>
-          errorAvatar(L10n.of(context).loadingMembersCountFailed(error)),
+      error: (e, st) {
+        _log.severe('Failed to load room members', e, st);
+        return errorAvatar(L10n.of(context).loadingMembersCountFailed(e));
+      },
       loading: () => loadingAvatar(),
     );
   }
diff --git a/app/lib/features/comments/widgets/comments_list.dart b/app/lib/features/comments/widgets/comments_list.dart
index 0ad2c3ea4c6e..38b382fa8e31 100644
--- a/app/lib/features/comments/widgets/comments_list.dart
+++ b/app/lib/features/comments/widgets/comments_list.dart
@@ -4,8 +4,11 @@ import 'package:acter/features/comments/widgets/comment.dart';
 import 'package:acter/features/comments/widgets/create_comment.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::comments::list');
 
 class CommentsList extends ConsumerStatefulWidget {
   final CommentsManager manager;
@@ -32,7 +35,10 @@ class _CommentsListState extends ConsumerState<CommentsList> {
               return commentListUI(context, manager);
             }
           },
-          error: (e, st) => onError(context, e),
+          error: (e, st) {
+            _log.severe('Failed to load comments', e, st);
+            return onError(context, e);
+          },
           loading: () => loading(context),
         );
   }
diff --git a/app/lib/features/comments/widgets/comments_section.dart b/app/lib/features/comments/widgets/comments_section.dart
index a69f539740ff..eaaa9e534611 100644
--- a/app/lib/features/comments/widgets/comments_section.dart
+++ b/app/lib/features/comments/widgets/comments_section.dart
@@ -5,8 +5,11 @@ import 'package:acter/features/settings/providers/settings_providers.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::comments::section');
 
 class CommentsSection extends ConsumerWidget {
   final Future<CommentsManager> manager;
@@ -24,7 +27,10 @@ class CommentsSection extends ConsumerWidget {
     }
     return ref.watch(commentsManagerProvider(manager)).when(
           data: (manager) => found(context, manager),
-          error: (e, st) => onError(context, e),
+          error: (e, st) {
+            _log.severe('Failed to load comment manager', e, st);
+            return onError(context, e);
+          },
           loading: () => loading(context),
         );
   }
diff --git a/app/lib/features/events/pages/create_event_page.dart b/app/lib/features/events/pages/create_event_page.dart
index 2f7d38d12d41..1a7f83866eab 100644
--- a/app/lib/features/events/pages/create_event_page.dart
+++ b/app/lib/features/events/pages/create_event_page.dart
@@ -16,7 +16,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
 import 'package:logging/logging.dart';
 
-final _log = Logger('a3::event::createOrEdit');
+final _log = Logger('a3::cal_event::createOrEdit');
 
 const createEditEventKey = Key('create-edit-event');
 
diff --git a/app/lib/features/events/pages/event_details_page.dart b/app/lib/features/events/pages/event_details_page.dart
index bac992c3f720..fb9eb48be7ea 100644
--- a/app/lib/features/events/pages/event_details_page.dart
+++ b/app/lib/features/events/pages/event_details_page.dart
@@ -1,8 +1,9 @@
+import 'dart:io';
+
 import 'package:acter/common/actions/redact_content.dart';
 import 'package:acter/common/actions/report_content.dart';
 import 'package:acter/common/providers/common_providers.dart';
 import 'package:acter/common/providers/room_providers.dart';
-import 'package:acter/common/themes/app_theme.dart';
 import 'package:acter/common/utils/utils.dart';
 import 'package:acter/features/events/actions/get_event_type.dart';
 import 'package:acter/features/events/widgets/change_date_sheet.dart';
@@ -19,6 +20,7 @@ import 'package:acter/features/events/utils/events_utils.dart';
 import 'package:acter/features/events/widgets/event_date_widget.dart';
 import 'package:acter/features/events/widgets/participants_list.dart';
 import 'package:acter/features/events/widgets/skeletons/event_details_skeleton_widget.dart';
+import 'package:acter/features/files/actions/file_share.dart';
 import 'package:acter/features/home/providers/client_providers.dart';
 import 'package:acter/features/home/widgets/space_chip.dart';
 import 'package:acter/features/space/widgets/member_avatar.dart';
@@ -26,7 +28,6 @@ import 'package:acter_avatar/acter_avatar.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:atlas_icons/atlas_icons.dart';
-import 'package:file_picker/file_picker.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
@@ -35,9 +36,9 @@ import 'package:jiffy/jiffy.dart';
 import 'package:logging/logging.dart';
 import 'package:path/path.dart' show join;
 import 'package:path_provider/path_provider.dart';
-import 'package:share_plus/share_plus.dart';
+import 'package:phosphor_flutter/phosphor_flutter.dart';
 
-final _log = Logger('a3::event::details');
+final _log = Logger('a3::cal_event::details');
 
 class EventDetailPage extends ConsumerStatefulWidget {
   final String calendarId;
@@ -68,8 +69,10 @@ class _EventDetailPageConsumerState extends ConsumerState<EventDetailPage> {
             ],
           );
         },
-        error: (error, stackTrace) =>
-            Text(L10n.of(context).errorLoadingEventDueTo(error)),
+        error: (e, st) {
+          _log.severe('Failed to load cal event', e, st);
+          return Text(L10n.of(context).errorLoadingEventDueTo(e));
+        },
         loading: () => const EventDetailsSkeleton(),
       ),
     );
@@ -419,51 +422,29 @@ class _EventDetailPageConsumerState extends ConsumerState<EventDetailPage> {
   }
 
   Widget _buildShareAction(CalendarEvent calendarEvent) {
-    return PopupMenuButton(
-      icon: const Icon(Icons.share),
-      itemBuilder: (context) => [
-        PopupMenuItem(
-          onTap: () => onShareEvent(calendarEvent),
-          child: Row(
-            children: <Widget>[
-              const Icon(Icons.share),
-              const SizedBox(width: 10),
-              Text(L10n.of(context).shareIcal),
-            ],
-          ),
-        ),
-      ],
+    return IconButton(
+      icon: PhosphorIcon(PhosphorIcons.shareFat()),
+      onPressed: () => onShareEvent(calendarEvent),
     );
   }
 
   Future<void> onShareEvent(CalendarEvent event) async {
     try {
       final filename = event.title().replaceAll(RegExp(r'[^A-Za-z0-9_-]'), '_');
-
-      if (isDesktop) {
-        String? outputFile = await FilePicker.platform.saveFile(
-          dialogTitle: 'Please select where to store the file',
-          fileName: '$filename.ics',
-        );
-
-        if (outputFile != null) {
-          // User canceled the picker
-          event.icalForSharing(outputFile);
-          EasyLoading.showToast('File saved to $outputFile');
-        }
-        return;
-      }
-
       final tempDir = await getTemporaryDirectory();
       final icalPath = join(tempDir.path, '$filename.ics');
       event.icalForSharing(icalPath);
 
-      await Share.shareXFiles([
-        XFile(
-          icalPath,
+      if (context.mounted) {
+        await openFileShareDialog(
+          // ignore: use_build_context_synchronously
+          context: context,
+          // ignore: use_build_context_synchronously
+          header: Text(L10n.of(context).shareIcal),
+          file: File(icalPath),
           mimeType: 'text/calendar',
-        ),
-      ]);
+        );
+      }
     } catch (error, stack) {
       _log.severe('Creating iCal Share Event failed:', error, stack);
       // ignore: use_build_context_synchronously
diff --git a/app/lib/features/events/pages/event_list_page.dart b/app/lib/features/events/pages/event_list_page.dart
index ff3968b20539..89187a2f6436 100644
--- a/app/lib/features/events/pages/event_list_page.dart
+++ b/app/lib/features/events/pages/event_list_page.dart
@@ -1,4 +1,5 @@
 import 'dart:math';
+
 import 'package:acter/common/providers/space_providers.dart';
 import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
 import 'package:acter/common/utils/routes.dart';
@@ -11,10 +12,13 @@ import 'package:acter/features/events/widgets/event_item.dart';
 import 'package:acter/features/events/widgets/skeletons/event_list_skeleton_widget.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::cal_event::list');
 
 class EventListPage extends ConsumerStatefulWidget {
   final String? spaceId;
@@ -76,15 +80,17 @@ class _EventListPageState extends ConsumerState<EventListPage> {
     return Column(
       crossAxisAlignment: CrossAxisAlignment.stretch,
       children: [
-        ActerSearchWidget(
-          searchTextController: searchTextController,
-        ),
+        ActerSearchWidget(searchTextController: searchTextController),
         filterChipsButtons(),
         Expanded(
           child: eventList.when(
             data: (events) => _buildEventList(events),
-            error: (error, stack) =>
-                Center(child: Text(L10n.of(context).loadingFailed(error))),
+            error: (e, st) {
+              _log.severe('Failed to search events in space', e, st);
+              return Center(
+                child: Text(L10n.of(context).searchingFailed(e)),
+              );
+            },
             loading: () => const EventListSkeleton(),
           ),
         ),
diff --git a/app/lib/features/events/widgets/event_item.dart b/app/lib/features/events/widgets/event_item.dart
index cb844bf7b844..b4b0da1640c1 100644
--- a/app/lib/features/events/widgets/event_item.dart
+++ b/app/lib/features/events/widgets/event_item.dart
@@ -8,9 +8,12 @@ import 'package:acter/features/events/widgets/event_date_widget.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'
     show CalendarEvent;
 import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::cal_event::event_item');
 
 class EventItem extends StatelessWidget {
   final CalendarEvent event;
@@ -115,12 +118,15 @@ class EventItem extends StatelessWidget {
                 ? rsvpStatusWidget
                 : const SizedBox.shrink();
           },
-          error: (e, st) => Chip(
-            label: Text(
-              L10n.of(context).errorLoadingRsvpStatus(e),
-              softWrap: true,
-            ),
-          ),
+          error: (e, st) {
+            _log.severe('Failed to load RSVP status', e, st);
+            return Chip(
+              label: Text(
+                L10n.of(context).errorLoadingRsvpStatus(e),
+                softWrap: true,
+              ),
+            );
+          },
           loading: () => Chip(
             label: Text(L10n.of(context).loadingRsvpStatus),
           ),
@@ -133,12 +139,12 @@ class EventItem extends StatelessWidget {
     if (status != null) {
       switch (status) {
         case 'yes':
-          return  Icon(
+          return Icon(
             Icons.check_circle,
             color: Theme.of(context).colorScheme.secondary,
           );
         case 'no':
-          return  Icon(
+          return Icon(
             Icons.cancel,
             color: Theme.of(context).colorScheme.error,
           );
diff --git a/app/lib/features/files/actions/download_file.dart b/app/lib/features/files/actions/download_file.dart
new file mode 100644
index 000000000000..0a245a62d2d9
--- /dev/null
+++ b/app/lib/features/files/actions/download_file.dart
@@ -0,0 +1,24 @@
+import 'dart:io';
+import 'package:path/path.dart';
+
+import 'package:file_picker/file_picker.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_easyloading/flutter_easyloading.dart';
+
+Future<bool> downloadFile(BuildContext context, File file) async {
+  final lang = L10n.of(context);
+  final filename = basename(file.path);
+  String? outputFile = await FilePicker.platform.saveFile(
+    dialogTitle: lang.downloadFileDialogTitle,
+    fileName: filename,
+  );
+
+  if (outputFile == null) {
+    return false;
+  }
+
+  await file.copy(outputFile);
+  EasyLoading.showToast(lang.downloadFileSuccess(outputFile));
+  return true;
+}
diff --git a/app/lib/features/files/actions/file_share.dart b/app/lib/features/files/actions/file_share.dart
new file mode 100644
index 000000000000..e2427fdd95e2
--- /dev/null
+++ b/app/lib/features/files/actions/file_share.dart
@@ -0,0 +1,109 @@
+import 'dart:io';
+
+import 'package:acter/features/files/actions/download_file.dart';
+import 'package:open_filex/open_filex.dart';
+import 'package:phosphor_flutter/phosphor_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:share_plus/share_plus.dart';
+
+Future<void> openFileShareDialog({
+  required BuildContext context,
+  required File file,
+  Widget? header,
+  String? mimeType,
+  List<Widget>? beforeOptions,
+  List<Widget>? afterOptions,
+}) async {
+  await showModalBottomSheet(
+    showDragHandle: true,
+    useSafeArea: true,
+    context: context,
+    isDismissible: true,
+    constraints: const BoxConstraints(maxHeight: 300),
+    builder: (context) => _FileOptionsDialog(
+      file: file,
+      header: header,
+      beforeOptions: beforeOptions,
+      afterOptions: afterOptions,
+      mimeType: mimeType,
+    ),
+  );
+}
+
+class _FileOptionsDialog extends StatelessWidget {
+  final File file;
+  final String? mimeType;
+  final Widget? header;
+  final List<Widget>? beforeOptions;
+  final List<Widget>? afterOptions;
+
+  const _FileOptionsDialog({
+    required this.file,
+    this.header,
+    this.afterOptions,
+    this.beforeOptions,
+    this.mimeType,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    final lang = L10n.of(context);
+    return Container(
+      padding: const EdgeInsets.symmetric(horizontal: 20.0),
+      constraints: const BoxConstraints(
+        maxWidth: 600,
+        minWidth: 300,
+      ),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          header ?? const SizedBox.shrink(),
+          if (header != null) const SizedBox(height: 16.0),
+          if (beforeOptions?.isNotEmpty == true) ...beforeOptions!,
+          TextButton.icon(
+            onPressed: () async {
+              final result = await OpenFilex.open(file.absolute.path);
+              if (result.type == ResultType.done) {
+                // done, close this dialog
+                if (context.mounted) {
+                  Navigator.pop(context);
+                }
+              }
+            },
+            label: Text(lang.openFile),
+            icon: PhosphorIcon(PhosphorIcons.fileArrowUp()),
+          ),
+          TextButton.icon(
+            onPressed: () async {
+              final result = await Share.shareXFiles(
+                  [XFile(file.path, mimeType: mimeType)],);
+              if (result.status == ShareResultStatus.success) {
+                // done, close this dialog
+                if (context.mounted) {
+                  Navigator.pop(context);
+                }
+              }
+            },
+            label: Text(lang.shareFile),
+            icon: PhosphorIcon(PhosphorIcons.shareNetwork()),
+          ),
+          if (!Platform.isAndroid) // crashes on Android for some reason ...
+            TextButton.icon(
+              onPressed: () async {
+                if (await downloadFile(context, file)) {
+                  // done, close this dialog
+                  if (context.mounted) {
+                    Navigator.pop(context);
+                  }
+                }
+              },
+              label: Text(lang.saveFileAs),
+              icon: PhosphorIcon(PhosphorIcons.downloadSimple()),
+            ),
+          if (afterOptions?.isNotEmpty == true) ...afterOptions!,
+        ],
+      ),
+    );
+  }
+}
diff --git a/app/lib/features/files/widgets/share_file_button.dart b/app/lib/features/files/widgets/share_file_button.dart
new file mode 100644
index 000000000000..bbf32c02bc1f
--- /dev/null
+++ b/app/lib/features/files/widgets/share_file_button.dart
@@ -0,0 +1,18 @@
+import 'dart:io';
+import 'package:acter/features/files/actions/file_share.dart';
+import 'package:flutter/material.dart';
+import 'package:phosphor_flutter/phosphor_flutter.dart';
+
+class ShareFileButton extends StatelessWidget {
+  final File file;
+
+  const ShareFileButton({super.key, required this.file});
+
+  @override
+  Widget build(BuildContext context) {
+    return IconButton(
+      onPressed: () => openFileShareDialog(context: context, file: file),
+      icon: PhosphorIcon(PhosphorIcons.shareFat()),
+    );
+  }
+}
diff --git a/app/lib/features/home/pages/home_shell.dart b/app/lib/features/home/pages/home_shell.dart
index 9106217ab214..a9692a584b31 100644
--- a/app/lib/features/home/pages/home_shell.dart
+++ b/app/lib/features/home/pages/home_shell.dart
@@ -83,7 +83,7 @@ class HomeShellState extends ConsumerState<HomeShell> {
     // shake is possible in only actual mobile devices
     if (await isRealPhone()) {
       detector = ShakeDetector.autoStart(
-        shakeThresholdGravity: 3.0,
+        shakeThresholdGravity: 30.0,
         onShake: () {
           openBugReport(context);
         },
diff --git a/app/lib/features/home/widgets/my_events.dart b/app/lib/features/home/widgets/my_events.dart
index 3390b0ca250d..0ae8cfb8d2de 100644
--- a/app/lib/features/home/widgets/my_events.dart
+++ b/app/lib/features/home/widgets/my_events.dart
@@ -5,9 +5,12 @@ import 'package:acter/features/events/widgets/event_item.dart';
 import 'package:acter/features/events/widgets/skeletons/event_list_skeleton_widget.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::home::my_events');
 
 class MyEventsSection extends ConsumerWidget {
   final int? limit;
@@ -44,9 +47,10 @@ class MyEventsSection extends ConsumerWidget {
               )
             : const SizedBox.shrink();
       },
-      error: (error, stackTrace) => Text(
-        L10n.of(context).loadingEventsFailed(error),
-      ),
+      error: (error, stackTrace) {
+        _log.severe('Failed to load cal events', error, stackTrace);
+        return Text(L10n.of(context).loadingEventsFailed(error));
+      },
       loading: () => const EventListSkeleton(),
     );
   }
diff --git a/app/lib/features/home/widgets/my_tasks.dart b/app/lib/features/home/widgets/my_tasks.dart
index 5d33b61ce7e5..823e6c204334 100644
--- a/app/lib/features/home/widgets/my_tasks.dart
+++ b/app/lib/features/home/widgets/my_tasks.dart
@@ -7,6 +7,9 @@ import 'package:flutter_easyloading/flutter_easyloading.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::home::my_tasks');
 
 class MyTasksSection extends ConsumerWidget {
   final int limit;
@@ -26,8 +29,10 @@ class MyTasksSection extends ConsumerWidget {
                 ListView.separated(
                   shrinkWrap: true,
                   physics: const NeverScrollableScrollPhysics(),
-                  separatorBuilder: (context, index) =>
-                      const Divider(color: Colors.white24, indent: 30),
+                  separatorBuilder: (context, index) => const Divider(
+                    color: Colors.white24,
+                    indent: 30,
+                  ),
                   itemCount: tasks.length,
                   itemBuilder: (context, index) {
                     return TaskItem(
@@ -42,7 +47,10 @@ class MyTasksSection extends ConsumerWidget {
                 ),
               ],
             ),
-      error: (error, stack) => Text(L10n.of(context).loadingTasksFailed(error)),
+      error: (error, stack) {
+        _log.severe('Failed to load open tasks', error, stack);
+        return Text(L10n.of(context).loadingTasksFailed(error));
+      },
       loading: () => Text(L10n.of(context).loading),
     );
   }
diff --git a/app/lib/features/home/widgets/space_chip.dart b/app/lib/features/home/widgets/space_chip.dart
index c8bec38528e5..04347a31ca0b 100644
--- a/app/lib/features/home/widgets/space_chip.dart
+++ b/app/lib/features/home/widgets/space_chip.dart
@@ -3,9 +3,12 @@ import 'package:acter/common/toolkit/buttons/inline_text_button.dart';
 import 'package:acter/router/utils.dart';
 import 'package:acter_avatar/acter_avatar.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
+
+final _log = Logger('a3::home::space_chip');
 
 class SpaceChip extends ConsumerWidget {
   final SpaceItem? space;
@@ -34,9 +37,12 @@ class SpaceChip extends ConsumerWidget {
         data: (space) {
           return renderSpace(context, space);
         },
-        error: (error, st) => Chip(
-          label: Text(L10n.of(context).loadingFailed(error)),
-        ),
+        error: (error, st) {
+          _log.severe('Failed to load brief of space', error, st);
+          return Chip(
+            label: Text(L10n.of(context).loadingFailed(error)),
+          );
+        },
         loading: () => renderLoading(spaceId!),
       );
     }
@@ -48,9 +54,7 @@ class SpaceChip extends ConsumerWidget {
       child: Chip(
         avatar: ActerAvatar(
           options: AvatarOptions(
-            AvatarInfo(
-              uniqueId: spaceId,
-            ),
+            AvatarInfo(uniqueId: spaceId),
             size: 24,
           ),
         ),
diff --git a/app/lib/features/invite_members/pages/invite_individual_users.dart b/app/lib/features/invite_members/pages/invite_individual_users.dart
index af9d9959927f..51f5cca0819c 100644
--- a/app/lib/features/invite_members/pages/invite_individual_users.dart
+++ b/app/lib/features/invite_members/pages/invite_individual_users.dart
@@ -1,15 +1,18 @@
 import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/common/widgets/empty_state_widget.dart';
 import 'package:acter/common/widgets/user_builder.dart';
+import 'package:acter/features/invite_members/providers/invite_providers.dart';
 import 'package:acter/features/invite_members/widgets/direct_invite.dart';
 import 'package:acter_avatar/acter_avatar.dart';
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
-import 'package:acter/features/invite_members/providers/invite_providers.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::invite::individual_users');
+
 class InviteIndividualUsers extends ConsumerWidget {
   final String roomId;
 
@@ -172,8 +175,10 @@ class InviteIndividualUsers extends ConsumerWidget {
                       userId: data[index].userId().toString(),
                       roomId: roomId,
                     ),
-                    error: (err, stackTrace) =>
-                        Text(L10n.of(context).error(err)),
+                    error: (err, st) {
+                      _log.severe('Failed to search users', err, st);
+                      return Text(L10n.of(context).searchingFailed(err));
+                    },
                     loading: () => Padding(
                       padding: const EdgeInsets.symmetric(horizontal: 10.0),
                       child: Skeletonizer(
diff --git a/app/lib/features/invite_members/pages/invite_space_members.dart b/app/lib/features/invite_members/pages/invite_space_members.dart
index 269e4a6adae1..7ca1325b37c5 100644
--- a/app/lib/features/invite_members/pages/invite_space_members.dart
+++ b/app/lib/features/invite_members/pages/invite_space_members.dart
@@ -5,12 +5,12 @@ import 'package:acter/features/invite_members/widgets/space_member_invite_card.d
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
-final _log = Logger('a3::invite::invite_space_members');
+final _log = Logger('a3::invite::space_members');
 
 class InviteSpaceMembers extends ConsumerStatefulWidget {
   final String roomId;
@@ -106,9 +106,12 @@ class _InviteSpaceMembersConsumerState
         ref.watch(otherSpacesForInviteMembersProvider(widget.roomId));
     return otherSpaces.when(
       data: _buildOtherSpaceData,
-      error: (error, stack) => ListTile(
-        title: Text(error.toString()),
-      ),
+      error: (error, stack) {
+        _log.severe('Failed to load other spaces', error, stack);
+        return ListTile(
+          title: Text(L10n.of(context).loadingFailed(error)),
+        );
+      },
       loading: () => _buildSkeletonizerLoading(),
     );
   }
diff --git a/app/lib/features/invite_members/providers/invite_providers.dart b/app/lib/features/invite_members/providers/invite_providers.dart
index 299342161fc5..5b654cf4c6cd 100644
--- a/app/lib/features/invite_members/providers/invite_providers.dart
+++ b/app/lib/features/invite_members/providers/invite_providers.dart
@@ -8,7 +8,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 
-final _log = Logger('a3::common::invite_provider');
+final _log = Logger('a3::invite::providers');
 
 final userNameRegExp = RegExp(
   r'@\S+:\S+.\S+$',
@@ -66,8 +66,11 @@ final suggestedUsersProvider = FutureProvider.family<List<FoundUser>, String>(
       MemoryImage? avatar;
       if (user.hasAvatar()) {
         try {
-          avatar = await user.getAvatar(null).then((val) =>
-              MemoryImage(Uint8List.fromList(val.data()!.asTypedList())),);
+          avatar = await user.getAvatar(null).then(
+                (val) => MemoryImage(
+                  Uint8List.fromList(val.data()!.asTypedList()),
+                ),
+              );
         } catch (e, s) {
           _log.severe('failure fetching avatar', e, s);
         }
diff --git a/app/lib/features/invite_members/widgets/invite_code_ui.dart b/app/lib/features/invite_members/widgets/invite_code_ui.dart
index 61b60de23672..27195dcf5178 100644
--- a/app/lib/features/invite_members/widgets/invite_code_ui.dart
+++ b/app/lib/features/invite_members/widgets/invite_code_ui.dart
@@ -15,7 +15,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
 import 'package:logging/logging.dart';
 
-final _log = Logger('a3::invite_members::invite_code');
+final _log = Logger('a3::invite::invite_code');
 
 class InviteCodeUI extends ConsumerStatefulWidget {
   final String roomId;
diff --git a/app/lib/features/member/widgets/member_info_drawer.dart b/app/lib/features/member/widgets/member_info_drawer.dart
index c076f771052a..504f4a0f9816 100644
--- a/app/lib/features/member/widgets/member_info_drawer.dart
+++ b/app/lib/features/member/widgets/member_info_drawer.dart
@@ -17,8 +17,11 @@ import 'package:flutter/services.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::member::member_info_drawer');
+
 class _MemberInfoDrawerInner extends ConsumerWidget {
   final Member member;
   final String memberId;
@@ -218,15 +221,18 @@ class _MemberInfoDrawerInner extends ConsumerWidget {
             }
             return menu;
           },
-          error: (e, s) => [
-            _roomTitle(context, ref),
-            MenuItemWidget(
-              iconData: Atlas.triangle_exclamation_thin,
-              title: L10n.of(context).errorLoading(e),
-              withMenu: false,
-              onTap: () {},
-            ),
-          ],
+          error: (e, s) {
+            _log.severe('Failed to load room membership', e, s);
+            return [
+              _roomTitle(context, ref),
+              MenuItemWidget(
+                iconData: Atlas.triangle_exclamation_thin,
+                title: L10n.of(context).loadingFailed(e),
+                withMenu: false,
+                onTap: () {},
+              ),
+            ];
+          },
           loading: () => [
             _roomTitle(context, ref),
             Skeletonizer(
@@ -314,10 +320,13 @@ class MemberInfoDrawer extends ConsumerWidget {
             memberId: memberId,
             isShowActions: isShowActions,
           ),
-          error: (e, s) => Padding(
-            padding: const EdgeInsets.all(20.0),
-            child: Text(L10n.of(context).errorLoadingProfile(e)),
-          ),
+          error: (e, s) {
+            _log.severe('Failed to load room member', e, s);
+            return Padding(
+              padding: const EdgeInsets.all(20.0),
+              child: Text(L10n.of(context).errorLoadingProfile(e)),
+            );
+          },
           loading: () => const MemberInfoSkeleton(),
         );
   }
diff --git a/app/lib/features/news/pages/add_news_page.dart b/app/lib/features/news/pages/add_news_page.dart
index d88b6242b6e3..a1d306d94842 100644
--- a/app/lib/features/news/pages/add_news_page.dart
+++ b/app/lib/features/news/pages/add_news_page.dart
@@ -27,8 +27,11 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/flutter_svg.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
 import 'package:mime/mime.dart';
 
+final _log = Logger('a3::news::add_page');
+
 const addNewsKey = Key('add-news');
 
 class AddNewsPage extends ConsumerStatefulWidget {
@@ -227,11 +230,16 @@ class AddNewsState extends ConsumerState<AddNewsPage> {
                       ),
                     );
                   },
-                  loading: () =>
-                      const SizedBox(width: 300, child: EventItemSkeleton()),
-                  error: (e, s) => Center(
-                    child: Text(L10n.of(context).failedToLoadEvent(e)),
+                  loading: () => const SizedBox(
+                    width: 300,
+                    child: EventItemSkeleton(),
                   ),
+                  error: (e, s) {
+                    _log.severe('Failed to load cal event', e, s);
+                    return Center(
+                      child: Text(L10n.of(context).failedToLoadEvent(e)),
+                    );
+                  },
                 ),
         ],
       ),
@@ -345,9 +353,8 @@ class AddNewsState extends ConsumerState<AddNewsPage> {
       return;
     }
 
-    String displayMsg = L10n.of(context).slidePosting;
     // Show loading message
-    EasyLoading.show(status: displayMsg);
+    EasyLoading.show(status: L10n.of(context).slidePosting);
     try {
       final space = await ref.read(spaceProvider(spaceId).future);
       NewsEntryDraft draft = space.newsDraft();
@@ -467,7 +474,7 @@ class AddNewsState extends ConsumerState<AddNewsPage> {
         return;
       }
       EasyLoading.showError(
-        '$displayMsg ${L10n.of(context).failed}: \n $err',
+        L10n.of(context).error(err),
         duration: const Duration(seconds: 3),
       );
     }
diff --git a/app/lib/features/news/widgets/news_item.dart b/app/lib/features/news/widgets/news_item.dart
index 97d44ea9e64e..2cbf696ef1fb 100644
--- a/app/lib/features/news/widgets/news_item.dart
+++ b/app/lib/features/news/widgets/news_item.dart
@@ -4,9 +4,9 @@ import 'package:acter/features/events/widgets/event_item.dart';
 import 'package:acter/features/events/widgets/skeletons/event_item_skeleton_widget.dart';
 import 'package:acter/features/news/model/news_references_model.dart';
 import 'package:acter/features/news/widgets/news_item_slide/video_slide.dart';
-import 'package:acter/features/news/widgets/news_side_bar.dart';
 import 'package:acter/features/news/widgets/news_item_slide/image_slide.dart';
 import 'package:acter/features/news/widgets/news_item_slide/text_slide.dart';
+import 'package:acter/features/news/widgets/news_side_bar.dart';
 import 'package:acter/router/utils.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
@@ -14,8 +14,11 @@ import 'package:carousel_indicator/carousel_indicator.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::news::news_item');
+
 class NewsItem extends ConsumerStatefulWidget {
   final Client client;
   final NewsEntry news;
@@ -104,7 +107,10 @@ class _NewsItemState extends ConsumerState<NewsItem> {
                 padding: const EdgeInsets.all(16),
                 child: space.when(
                   data: (space) => Text(space.avatarInfo.displayName ?? roomId),
-                  error: (e, st) => Text(L10n.of(context).errorLoadingSpace(e)),
+                  error: (e, st) {
+                    _log.severe('Failed to load brief of space', e, st);
+                    return Text(L10n.of(context).errorLoadingSpace(e));
+                  },
                   loading: () => Skeletonizer(
                     child: Text(roomId),
                   ),
@@ -180,8 +186,12 @@ class _NewsItemState extends ConsumerState<NewsItem> {
               );
             },
             loading: () => const EventItemSkeleton(),
-            error: (e, s) =>
-                Center(child: Text(L10n.of(context).failedToLoadEvent(e))),
+            error: (e, s) {
+              _log.severe('Failed to load cal event', e, s);
+              return Center(
+                child: Text(L10n.of(context).failedToLoadEvent(e)),
+              );
+            },
           );
     } else {
       return Card(
diff --git a/app/lib/features/news/widgets/news_item_slide/image_slide.dart b/app/lib/features/news/widgets/news_item_slide/image_slide.dart
index ed998413c913..03fa3b2e2f05 100644
--- a/app/lib/features/news/widgets/news_item_slide/image_slide.dart
+++ b/app/lib/features/news/widgets/news_item_slide/image_slide.dart
@@ -1,8 +1,12 @@
 import 'dart:typed_data';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
+
 import 'package:acter/features/news/model/keys.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::news::widget::image_slide');
 
 class ImageSlide extends StatelessWidget {
   final NewsSlide slide;
@@ -22,6 +26,11 @@ class ImageSlide extends StatelessWidget {
       future: slide.sourceBinary(null),
       builder: (BuildContext context, AsyncSnapshot<FfiBufferUint8> snapshot) {
         if (snapshot.hasError) {
+          _log.severe(
+            'Failed to load image of slide',
+            snapshot.error,
+            snapshot.stackTrace,
+          );
           return Center(
             child: Text(L10n.of(context).errorLoadingImage(snapshot.error!)),
           );
diff --git a/app/lib/features/news/widgets/news_item_slide/video_slide.dart b/app/lib/features/news/widgets/news_item_slide/video_slide.dart
index 81563f859a2a..e92709358206 100644
--- a/app/lib/features/news/widgets/news_item_slide/video_slide.dart
+++ b/app/lib/features/news/widgets/news_item_slide/video_slide.dart
@@ -5,9 +5,12 @@ import 'package:acter/features/news/model/keys.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:logging/logging.dart';
 import 'package:path/path.dart' as p;
 import 'package:path_provider/path_provider.dart';
 
+final _log = Logger('a3::news::widget::video_slide');
+
 class VideoSlide extends StatelessWidget {
   final NewsSlide slide;
   final Color bgColor;
@@ -43,8 +46,13 @@ class VideoSlide extends StatelessWidget {
         future: getNewsVideo(),
         builder: (BuildContext context, AsyncSnapshot<File> snapshot) {
           if (snapshot.hasError) {
+            _log.severe(
+              'Failed to load video of slide',
+              snapshot.error,
+              snapshot.stackTrace,
+            );
             return Center(
-              child: Text(L10n.of(context).errorLoading(snapshot.error!)),
+              child: Text(L10n.of(context).loadingFailed(snapshot.error!)),
             );
           }
 
diff --git a/app/lib/features/news/widgets/news_side_bar.dart b/app/lib/features/news/widgets/news_side_bar.dart
index d38f60b1b9b7..596baab669ee 100644
--- a/app/lib/features/news/widgets/news_side_bar.dart
+++ b/app/lib/features/news/widgets/news_side_bar.dart
@@ -100,7 +100,7 @@ class NewsSideBar extends ConsumerWidget {
             ),
           ),
           error: (e, st) {
-            _log.severe('Error loading space', e, st);
+            _log.severe('Failed to load brief of space', e, st);
             return ActerAvatar(
               options: AvatarOptions(
                 AvatarInfo(
diff --git a/app/lib/features/news/widgets/news_widget.dart b/app/lib/features/news/widgets/news_widget.dart
index 9c5d4c4ad153..2d96bb1dafb2 100644
--- a/app/lib/features/news/widgets/news_widget.dart
+++ b/app/lib/features/news/widgets/news_widget.dart
@@ -6,9 +6,12 @@ import 'package:acter/features/home/providers/client_providers.dart';
 import 'package:acter/features/news/providers/news_providers.dart';
 import 'package:acter/features/news/widgets/news_item.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::news::news_widget');
 
 class NewsWidget extends ConsumerStatefulWidget {
   const NewsWidget({super.key});
@@ -76,7 +79,10 @@ class _NewsWidgetState extends ConsumerState<NewsWidget> {
         );
       },
       error: (error, stackTrace) {
-        return Center(child: Text(L10n.of(context).couldNotFetchNews));
+        _log.severe('Failed to load news list', error, stackTrace);
+        return Center(
+          child: Text(L10n.of(context).couldNotFetchNews),
+        );
       },
       loading: () => const Center(
         child: SizedBox(
diff --git a/app/lib/features/pins/pages/pin_page.dart b/app/lib/features/pins/pages/pin_page.dart
index 85a5ed996f95..63d8a86306bf 100644
--- a/app/lib/features/pins/pages/pin_page.dart
+++ b/app/lib/features/pins/pages/pin_page.dart
@@ -15,8 +15,11 @@ import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::pins::pin_page');
+
 class PinPage extends ConsumerWidget {
   static const pinPageKey = Key('pin-page');
   static const actionMenuKey = Key('pin-action-menu');
@@ -195,11 +198,16 @@ class PinPage extends ConsumerWidget {
               );
             },
             loading: () => SliverAppBar(
-              title: Skeletonizer(child: Text(L10n.of(context).loadingPin)),
-            ),
-            error: (err, st) => SliverAppBar(
-              title: Text(L10n.of(context).errorLoadingPin(err)),
+              title: Skeletonizer(
+                child: Text(L10n.of(context).loadingPin),
+              ),
             ),
+            error: (err, st) {
+              _log.severe('Failed to load pin', err, st);
+              return SliverAppBar(
+                title: Text(L10n.of(context).errorLoadingPin(err)),
+              );
+            },
           ),
           SliverToBoxAdapter(
             child: pin.when(
@@ -213,7 +221,10 @@ class PinPage extends ConsumerWidget {
                   CommentsSection(manager: acterPin.comments()),
                 ],
               ),
-              error: (err, st) => Text(L10n.of(context).errorLoadingPin(err)),
+              error: (err, st) {
+                _log.severe('Failed to load pin', err, st);
+                return Text(L10n.of(context).errorLoadingPin(err));
+              },
               loading: () => const Skeletonizer(
                 child: Card(),
               ),
diff --git a/app/lib/features/pins/pages/pins_list_page.dart b/app/lib/features/pins/pages/pins_list_page.dart
index 6c5ac0bf12c5..dcdd28620449 100644
--- a/app/lib/features/pins/pages/pins_list_page.dart
+++ b/app/lib/features/pins/pages/pins_list_page.dart
@@ -1,4 +1,5 @@
 import 'dart:math';
+
 import 'package:acter/common/providers/space_providers.dart';
 import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
 import 'package:acter/common/utils/routes.dart';
@@ -11,10 +12,13 @@ import 'package:acter/features/pins/widgets/pin_list_item.dart';
 import 'package:acter/features/pins/widgets/pin_list_skeleton.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::pins::list');
 
 class PinsListPage extends ConsumerStatefulWidget {
   final String? spaceId;
@@ -86,8 +90,12 @@ class _AllPinsPageConsumerState extends ConsumerState<PinsListPage> {
         Expanded(
           child: pinList.when(
             data: (pins) => _buildPinsList(pins),
-            error: (error, stack) =>
-                Center(child: Text(L10n.of(context).loadingFailed(error))),
+            error: (error, stack) {
+              _log.severe('Failed to load pins', error, stack);
+              return Center(
+                child: Text(L10n.of(context).loadingFailed(error)),
+              );
+            },
             loading: () => const PinListSkeleton(),
           ),
         ),
diff --git a/app/lib/features/pins/widgets/pin_list_item.dart b/app/lib/features/pins/widgets/pin_list_item.dart
index b5ef57bb001e..1ab13bd25452 100644
--- a/app/lib/features/pins/widgets/pin_list_item.dart
+++ b/app/lib/features/pins/widgets/pin_list_item.dart
@@ -10,8 +10,11 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_matrix_html/flutter_html.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::pins::pin_item');
+
 class PinListItemById extends ConsumerWidget {
   final String pinId;
   final bool showSpace;
@@ -31,7 +34,10 @@ class PinListItemById extends ConsumerWidget {
         pin: acterPin,
         showSpace: showSpace,
       ),
-      error: (err, st) => Text(L10n.of(context).errorLoading(err)),
+      error: (err, st) {
+        _log.severe('Failed to load pin', err, st);
+        return Text(L10n.of(context).errorLoadingPin(err));
+      },
       loading: () => const Skeletonizer(
         child: SizedBox(
           height: 100,
diff --git a/app/lib/features/public_room_search/widgets/public_room_item.dart b/app/lib/features/public_room_search/widgets/public_room_item.dart
index f8c76e566520..86b6f3426d08 100644
--- a/app/lib/features/public_room_search/widgets/public_room_item.dart
+++ b/app/lib/features/public_room_search/widgets/public_room_item.dart
@@ -3,10 +3,10 @@ import 'package:acter/features/public_room_search/providers/public_space_info_pr
 import 'package:acter/features/public_room_search/types.dart';
 import 'package:acter_avatar/acter_avatar.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter/material.dart';
-import 'package:logging/logging.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
 final _log = Logger('a3::public_room_search::public_room_item');
@@ -26,14 +26,12 @@ class _JoinBtn extends ConsumerWidget {
           data: (data) =>
               data == null ? noMember(context) : alreadyMember(context),
           error: (error, st) {
-            _log.severe('loading membership info failed', error, st);
+            _log.severe('Failed to load room membership', error, st);
             return Text(L10n.of(context).loadingFailed(error));
           },
           loading: () => Skeletonizer(
             child: OutlinedButton(
-              onPressed: () => onSelected(
-                item,
-              ),
+              onPressed: () => onSelected(item),
               child: Text(L10n.of(context).requestToJoin),
             ),
           ),
@@ -42,9 +40,7 @@ class _JoinBtn extends ConsumerWidget {
 
   Widget alreadyMember(BuildContext context) {
     return OutlinedButton(
-      onPressed: () => onSelected(
-        item,
-      ),
+      onPressed: () => onSelected(item),
       child: Text(L10n.of(context).member),
     );
   }
@@ -52,16 +48,12 @@ class _JoinBtn extends ConsumerWidget {
   Widget noMember(BuildContext context) {
     if (item.joinRuleStr() == 'Public') {
       return OutlinedButton(
-        onPressed: () => onSelected(
-          item,
-        ),
+        onPressed: () => onSelected(item),
         child: Text(L10n.of(context).join),
       );
     } else {
       return OutlinedButton(
-        onPressed: () => onSelected(
-          item,
-        ),
+        onPressed: () => onSelected(item),
         child: Text(L10n.of(context).requestToJoin),
       );
     }
@@ -93,17 +85,13 @@ class PublicRoomItem extends ConsumerWidget {
             child: Padding(
               padding: const EdgeInsets.symmetric(vertical: 5),
               child: ListTile(
-                onTap: () => onSelected(
-                  item,
-                ),
+                onTap: () => onSelected(item),
                 leading: profileInfo.when(
                   data: (profile) => ActerAvatar(
-                    options: AvatarOptions(
-                      profile,
-                    ),
+                    options: AvatarOptions(profile),
                   ),
                   error: (e, s) {
-                    _log.severe('loading failed', e, s);
+                    _log.severe('Failed to load avatar info', e, s);
                     return fallbackAvatar();
                   },
                   loading: fallbackAvatar,
@@ -128,8 +116,10 @@ class PublicRoomItem extends ConsumerWidget {
           if (topic != null)
             Flexible(
               child: Padding(
-                padding:
-                    const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
+                padding: const EdgeInsets.symmetric(
+                  horizontal: 12,
+                  vertical: 8,
+                ),
                 child: Text(
                   topic,
                   style: Theme.of(context).textTheme.labelMedium,
diff --git a/app/lib/features/room/actions/join_room.dart b/app/lib/features/room/actions/join_room.dart
index de3c183d63bb..b830ca8be932 100644
--- a/app/lib/features/room/actions/join_room.dart
+++ b/app/lib/features/room/actions/join_room.dart
@@ -35,7 +35,7 @@ Future<String?> joinRoom(
       return null;
     }
     EasyLoading.showError(
-      '$displayMsg ${L10n.of(context).failed}: \n $err"',
+      L10n.of(context).error(err),
       duration: const Duration(seconds: 3),
     );
     return null;
diff --git a/app/lib/features/room/widgets/notifications_settings_tile.dart b/app/lib/features/room/widgets/notifications_settings_tile.dart
index bb8fa8602108..8ce80e1b2311 100644
--- a/app/lib/features/room/widgets/notifications_settings_tile.dart
+++ b/app/lib/features/room/widgets/notifications_settings_tile.dart
@@ -7,7 +7,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 import 'package:settings_ui/settings_ui.dart';
 
-final _log = Logger('a3::room::notification_settings_tile');
+final _log = Logger('a3::room::notification_settings');
 
 String? notifToText(BuildContext context, String curNotifStatus) {
   if (curNotifStatus == 'muted') {
diff --git a/app/lib/features/search/widgets/pins_builder.dart b/app/lib/features/search/widgets/pins_builder.dart
index e83d7d01c70b..19a6613cacc0 100644
--- a/app/lib/features/search/widgets/pins_builder.dart
+++ b/app/lib/features/search/widgets/pins_builder.dart
@@ -1,9 +1,12 @@
 import 'package:acter/common/utils/routes.dart';
 import 'package:acter/features/search/providers/pins.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::search::pins_builder');
 
 class PinsBuilder extends ConsumerWidget {
   final bool popBeforeRoute;
@@ -17,7 +20,10 @@ class PinsBuilder extends ConsumerWidget {
     final foundPins = ref.watch(pinsFoundProvider);
     return foundPins.when(
       loading: () => Text(L10n.of(context).loading),
-      error: (e, st) => Text(L10n.of(context).error(e)),
+      error: (e, st) {
+        _log.severe('Failed to search pins', e, st);
+        return Text(L10n.of(context).searchingFailed(e));
+      },
       data: (data) {
         final Widget body;
         if (data.isEmpty) {
diff --git a/app/lib/features/search/widgets/quick_actions_builder.dart b/app/lib/features/search/widgets/quick_actions_builder.dart
index e3ef0a5b421c..2c826885dedb 100644
--- a/app/lib/features/search/widgets/quick_actions_builder.dart
+++ b/app/lib/features/search/widgets/quick_actions_builder.dart
@@ -9,10 +9,10 @@ import 'package:acter/features/spaces/model/keys.dart';
 import 'package:acter/features/tasks/sheets/create_update_task_list.dart';
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
 import 'package:logging/logging.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
 
 final _log = Logger('a3::search::quick_actions_builder');
 
diff --git a/app/lib/features/search/widgets/spaces_builder.dart b/app/lib/features/search/widgets/spaces_builder.dart
index 6a73b13db000..f104f998df7c 100644
--- a/app/lib/features/search/widgets/spaces_builder.dart
+++ b/app/lib/features/search/widgets/spaces_builder.dart
@@ -4,11 +4,14 @@ import 'package:acter/features/search/providers/search.dart';
 import 'package:acter/features/search/providers/spaces.dart';
 import 'package:acter/router/utils.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::search::spaces_builder');
+
 class SpacesBuilder extends ConsumerWidget {
   final bool popBeforeRoute;
 
@@ -22,10 +25,13 @@ class SpacesBuilder extends ConsumerWidget {
     final foundSpaces = ref.watch(spacesFoundProvider);
     return foundSpaces.when(
       loading: () => renderLoading(context),
-      error: (e, st) => inBox(
-        context,
-        Text(L10n.of(context).error(e)),
-      ),
+      error: (e, st) {
+        _log.severe('Failed to search spaces', e, st);
+        return inBox(
+          context,
+          Text(L10n.of(context).searchingFailed(e)),
+        );
+      },
       data: (data) {
         if (data.isEmpty) {
           return renderEmpty(context, ref);
diff --git a/app/lib/features/settings/model/language_model.dart b/app/lib/features/settings/model/language_model.dart
index 6a11cef87134..fd774e3c390b 100644
--- a/app/lib/features/settings/model/language_model.dart
+++ b/app/lib/features/settings/model/language_model.dart
@@ -9,8 +9,12 @@ class LanguageModel {
 
   factory LanguageModel.fromCode(String? locale) {
     switch (locale) {
+      case 'ar':
+        return const LanguageModel.arabic();
       case 'de':
         return const LanguageModel.german();
+      case 'es':
+        return const LanguageModel.spanish();
       case 'pl':
         return const LanguageModel.polish();
       case 'fr':
@@ -38,11 +42,21 @@ class LanguageModel {
       : languageName = 'Polski',
         languageCode = 'pl';
 
+  const LanguageModel.spanish()
+      : languageName = 'Espanol',
+        languageCode = 'es';
+
+  const LanguageModel.arabic()
+      : languageName = 'اَلْعَرَبِيَّةُ',
+        languageCode = 'ar';
+
   static const allLanguagesList = [
-    // we show them in ehm... alphabetical order
+    // we show them in ehm... alphabetical order of the name in their own language
     LanguageModel.german(),
     LanguageModel.english(),
+    LanguageModel.spanish(),
     LanguageModel.french(),
     LanguageModel.polish(),
+    LanguageModel.arabic(),
   ];
 }
diff --git a/app/lib/features/settings/pages/blocked_users.dart b/app/lib/features/settings/pages/blocked_users.dart
index c4b60331bd1c..971df563f935 100644
--- a/app/lib/features/settings/pages/blocked_users.dart
+++ b/app/lib/features/settings/pages/blocked_users.dart
@@ -119,8 +119,9 @@ class BlockedUsersPage extends ConsumerWidget {
                   child: Text(L10n.of(context).hereYouCanSeeAllUsersYouBlocked),
                 ),
           error: (error, stack) {
+            _log.severe('Failed to load the ignored users', error, stack);
             return Center(
-              child: Text(L10n.of(context).failedToLoad(error)),
+              child: Text(L10n.of(context).loadingFailed(error)),
             );
           },
           loading: () => const Center(
diff --git a/app/lib/features/settings/pages/change_password.dart b/app/lib/features/settings/pages/change_password.dart
index 2bc43c981522..9a2cbbebc64c 100644
--- a/app/lib/features/settings/pages/change_password.dart
+++ b/app/lib/features/settings/pages/change_password.dart
@@ -6,11 +6,11 @@ import 'package:acter/features/settings/pages/settings_page.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 
-final _log = Logger('a3::room::change_password');
+final _log = Logger('a3::settings::change_password');
 
 class ChangePasswordPage extends ConsumerStatefulWidget {
   const ChangePasswordPage({super.key});
diff --git a/app/lib/features/settings/pages/chat_settings_page.dart b/app/lib/features/settings/pages/chat_settings_page.dart
index 13a0abdffeb6..21337609f361 100644
--- a/app/lib/features/settings/pages/chat_settings_page.dart
+++ b/app/lib/features/settings/pages/chat_settings_page.dart
@@ -7,9 +7,9 @@ import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:settings_ui/settings_ui.dart';
 import 'package:skeletonizer/skeletonizer.dart';
-import 'package:logging/logging.dart';
 
 final _log = Logger('a3::settings::chat_settings');
 
@@ -47,11 +47,12 @@ class ChatSettingsPage extends ConsumerWidget {
               }
             },
           ),
-          error: (error, stack) => SettingsTile.navigation(
-            title: Text(
-              L10n.of(context).failed,
-            ),
-          ),
+          error: (error, stack) {
+            _log.severe('Failed to load user app settings', error, stack);
+            return SettingsTile.navigation(
+              title: Text(L10n.of(context).loadingFailed(error)),
+            );
+          },
           loading: () => SettingsTile.switchTile(
             title: Skeletonizer(
               child: Text(L10n.of(context).chatSettingsAutoDownload),
@@ -66,10 +67,7 @@ class ChatSettingsPage extends ConsumerWidget {
         );
   }
 
-  AbstractSettingsTile _typingNotice(
-    BuildContext context,
-    WidgetRef ref,
-  ) {
+  AbstractSettingsTile _typingNotice(BuildContext context, WidgetRef ref) {
     return ref.watch(userAppSettingsProvider).when(
           data: (settings) => SettingsTile.switchTile(
             title: Text(L10n.of(context).chatSettingsTyping),
@@ -98,11 +96,12 @@ class ChatSettingsPage extends ConsumerWidget {
               }
             },
           ),
-          error: (error, stack) => SettingsTile.navigation(
-            title: Text(
-              L10n.of(context).failed,
-            ),
-          ),
+          error: (error, stack) {
+            _log.severe('Failed to load user app settings', error, stack);
+            return SettingsTile.navigation(
+              title: Text(L10n.of(context).loadingFailed(error)),
+            );
+          },
           loading: () => SettingsTile.switchTile(
             title: Skeletonizer(
               child: Text(L10n.of(context).chatSettingsTyping),
diff --git a/app/lib/features/settings/pages/email_addresses.dart b/app/lib/features/settings/pages/email_addresses.dart
index 488bf2ff40de..d8c647048f78 100644
--- a/app/lib/features/settings/pages/email_addresses.dart
+++ b/app/lib/features/settings/pages/email_addresses.dart
@@ -9,6 +9,9 @@ import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::settings::email_addresses');
 
 class AddEmailAddr extends StatefulWidget {
   const AddEmailAddr({super.key});
@@ -92,15 +95,14 @@ class EmailAddressesPage extends ConsumerWidget {
             ),
             IconButton(
               onPressed: () => addEmailAddress(context, ref),
-              icon: const Icon(
-                Atlas.plus_circle_thin,
-              ),
+              icon: const Icon(Atlas.plus_circle_thin),
             ),
           ],
         ),
         body: emailAddresses.when(
           data: (addresses) => buildAddresses(context, addresses),
           error: (error, stack) {
+            _log.severe('Failed to load email addresses', error, stack);
             return Center(
               child: Text(L10n.of(context).errorLoadingEmailAddresses(error)),
             );
diff --git a/app/lib/features/settings/pages/notifications_page.dart b/app/lib/features/settings/pages/notifications_page.dart
index dad30e7c81af..07e8193032ed 100644
--- a/app/lib/features/settings/pages/notifications_page.dart
+++ b/app/lib/features/settings/pages/notifications_page.dart
@@ -1,7 +1,6 @@
 import 'package:acter/config/notifications/init.dart';
 import 'package:acter_notifify/util.dart';
 import 'package:acter/common/toolkit/buttons/danger_action_button.dart';
-
 import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
 import 'package:acter/common/utils/utils.dart';
 import 'package:acter/common/widgets/with_sidebar.dart';
@@ -261,11 +260,14 @@ class NotificationsSettingsPage extends ConsumerWidget {
                   .map((item) => _pusherTile(context, ref, item))
                   .toList();
             },
-            error: (e, s) => [
-              SettingsTile(
-                title: Text(L10n.of(context).failedToLoadPushTargets(e)),
-              ),
-            ],
+            error: (e, s) {
+              _log.severe('Failed to load pushers', e, s);
+              return [
+                SettingsTile(
+                  title: Text(L10n.of(context).failedToLoadPushTargets(e)),
+                ),
+              ];
+            },
             loading: () => [
               SettingsTile(
                 title: Text(L10n.of(context).loadingTargets),
diff --git a/app/lib/features/settings/pages/sessions_page.dart b/app/lib/features/settings/pages/sessions_page.dart
index 4d0d3852f1b0..7fc67f3be824 100644
--- a/app/lib/features/settings/pages/sessions_page.dart
+++ b/app/lib/features/settings/pages/sessions_page.dart
@@ -8,6 +8,9 @@ import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::settings::sessions');
 
 class SessionsPage extends ConsumerWidget {
   const SessionsPage({super.key});
@@ -36,6 +39,7 @@ class SessionsPage extends ConsumerWidget {
         body: allSessions.when(
           data: (sessions) => buildSessions(context, sessions),
           error: (error, stack) {
+            _log.severe('Failed to load unknown sessions', error, stack);
             return Center(
               child: Text(L10n.of(context).couldNotLoadAllSessions),
             );
diff --git a/app/lib/features/settings/widgets/app_notifications_settings_tile.dart b/app/lib/features/settings/widgets/app_notifications_settings_tile.dart
index 7d7f7e3eca50..6f938a692346 100644
--- a/app/lib/features/settings/widgets/app_notifications_settings_tile.dart
+++ b/app/lib/features/settings/widgets/app_notifications_settings_tile.dart
@@ -2,9 +2,12 @@ import 'package:acter/common/providers/common_providers.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:settings_ui/settings_ui.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::settings::app_notifications');
+
 class _AppNotificationSettingsTile extends ConsumerWidget {
   final String title;
   final String appKey;
@@ -22,9 +25,16 @@ class _AppNotificationSettingsTile extends ConsumerWidget {
   Widget build(BuildContext context, WidgetRef ref) {
     return ref.watch(appContentNotificationSetting(appKey)).when(
           data: (v) => innerBuild(context, ref, v),
-          error: (error, st) => SettingsTile(
-            title: Text('${L10n.of(context).error}: $error'),
-          ),
+          error: (error, st) {
+            _log.severe(
+              'Fetching of app content notification setting failed',
+              error,
+              st,
+            );
+            return SettingsTile(
+              title: Text(L10n.of(context).loadingFailed(error)),
+            );
+          },
           loading: () => Skeletonizer(
             child: SettingsTile.switchTile(
               initialValue: true,
diff --git a/app/lib/features/settings/widgets/labs_notifications_settings_tile.dart b/app/lib/features/settings/widgets/labs_notifications_settings_tile.dart
index 54508d505e33..52022a1e5467 100644
--- a/app/lib/features/settings/widgets/labs_notifications_settings_tile.dart
+++ b/app/lib/features/settings/widgets/labs_notifications_settings_tile.dart
@@ -12,7 +12,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 import 'package:settings_ui/settings_ui.dart';
 
-final _log = Logger('a3::settings::labs_notifications_settings_tile');
+final _log = Logger('a3::settings::labs_notifications');
 
 final isOnSupportedPlatform = Platform.isAndroid || Platform.isIOS;
 
diff --git a/app/lib/features/space/actions/set_space_title.dart b/app/lib/features/space/actions/set_space_title.dart
index 5680e20469b1..969a9e82d6f5 100644
--- a/app/lib/features/space/actions/set_space_title.dart
+++ b/app/lib/features/space/actions/set_space_title.dart
@@ -3,11 +3,11 @@ import 'package:acter/common/providers/space_providers.dart';
 import 'package:acter/common/widgets/edit_title_sheet.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 
-final _log = Logger('a3::space::set_space_title');
+final _log = Logger('a3::space::actions::set_space_title');
 
 void showEditSpaceNameBottomSheet({
   required BuildContext context,
diff --git a/app/lib/features/space/dialogs/suggested_rooms.dart b/app/lib/features/space/dialogs/suggested_rooms.dart
index 1e8d6180c5f0..ad23d43d3e72 100644
--- a/app/lib/features/space/dialogs/suggested_rooms.dart
+++ b/app/lib/features/space/dialogs/suggested_rooms.dart
@@ -8,8 +8,8 @@ import 'package:acter/features/space/actions/has_seen_suggested.dart';
 import 'package:acter/features/space/providers/suggested_provider.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 
 final _log = Logger('a3::spaces::suggested_rooms');
diff --git a/app/lib/features/space/pages/members_page.dart b/app/lib/features/space/pages/members_page.dart
index 4bd789460b08..b3b39d3edeb3 100644
--- a/app/lib/features/space/pages/members_page.dart
+++ b/app/lib/features/space/pages/members_page.dart
@@ -1,12 +1,16 @@
 import 'dart:math';
+
 import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/common/providers/space_providers.dart';
 import 'package:acter/common/utils/routes.dart';
 import 'package:acter/features/member/widgets/member_list_entry.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::space::members_page');
 
 class SpaceMembersPage extends ConsumerWidget {
   final String spaceIdOrAlias;
@@ -52,9 +56,7 @@ class SpaceMembersPage extends ConsumerWidget {
             if (members.isEmpty) {
               return SliverToBoxAdapter(
                 child: Center(
-                  child: Text(
-                    L10n.of(context).noMembersFound,
-                  ),
+                  child: Text(L10n.of(context).noMembersFound),
                 ),
               );
             }
@@ -72,11 +74,14 @@ class SpaceMembersPage extends ConsumerWidget {
               },
             );
           },
-          error: (error, stack) => SliverToBoxAdapter(
-            child: Center(
-              child: Text(L10n.of(context).loadingFailed(error)),
-            ),
-          ),
+          error: (error, stack) {
+            _log.severe('Failed to load space members', error, stack);
+            return SliverToBoxAdapter(
+              child: Center(
+                child: Text(L10n.of(context).loadingFailed(error)),
+              ),
+            );
+          },
           loading: () => SliverToBoxAdapter(
             child: Center(
               child: Text(L10n.of(context).loading),
diff --git a/app/lib/features/space/pages/space_details_page.dart b/app/lib/features/space/pages/space_details_page.dart
index 38dcafd102aa..cf97629e3378 100644
--- a/app/lib/features/space/pages/space_details_page.dart
+++ b/app/lib/features/space/pages/space_details_page.dart
@@ -18,8 +18,11 @@ import 'package:acter/features/space/widgets/space_toolbar.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
 
+final _log = Logger('a3::space::space_details');
+
 class SpaceDetailsPage extends ConsumerStatefulWidget {
   static const headerKey = Key('space-menus-header');
   final String spaceId;
@@ -146,7 +149,10 @@ class _SpaceDetailsPageState extends ConsumerState<SpaceDetailsPage> {
           },
         );
       },
-      error: (error, stack) => Text(L10n.of(context).loadingFailed(error)),
+      error: (error, stack) {
+        _log.severe('Failed to load tabs in space', error, stack);
+        return Text(L10n.of(context).loadingFailed(error));
+      },
       loading: () => const SpaceDetailsSkeletons(),
     );
   }
diff --git a/app/lib/features/space/pages/sub_spaces_page.dart b/app/lib/features/space/pages/sub_spaces_page.dart
index b4a932e3555a..eb4fb4f2e4e6 100644
--- a/app/lib/features/space/pages/sub_spaces_page.dart
+++ b/app/lib/features/space/pages/sub_spaces_page.dart
@@ -12,6 +12,9 @@ import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::space::sub_spaces');
 
 class SubSpacesPage extends ConsumerWidget {
   static const moreOptionKey = Key('related-spaces-more-actions');
@@ -115,9 +118,12 @@ class SubSpacesPage extends ConsumerWidget {
                 return const SizedBox.shrink();
               }
             },
-            error: (error, stack) => Center(
-              child: Text(L10n.of(context).loadingFailed(error)),
-            ),
+            error: (error, stack) {
+              _log.severe('Failed to load the related spaces', error, stack);
+              return Center(
+                child: Text(L10n.of(context).loadingFailed(error)),
+              );
+            },
             loading: () => const SizedBox.shrink(),
           ),
         ],
@@ -139,9 +145,12 @@ class SubSpacesPage extends ConsumerWidget {
                       canLinkSpace,
                     );
               },
-              error: (error, stack) => Center(
-                child: Text(L10n.of(context).loadingFailed(error)),
-              ),
+              error: (error, stack) {
+                _log.severe('Failed to load the related spaces', error, stack);
+                return Center(
+                  child: Text(L10n.of(context).loadingFailed(error)),
+                );
+              },
               loading: () => Center(
                 child: Text(L10n.of(context).loading),
               ),
diff --git a/app/lib/features/space/providers/suggested_provider.dart b/app/lib/features/space/providers/suggested_provider.dart
index 4721d2cd7750..166178478500 100644
--- a/app/lib/features/space/providers/suggested_provider.dart
+++ b/app/lib/features/space/providers/suggested_provider.dart
@@ -1,8 +1,8 @@
 import 'package:acter/common/providers/room_providers.dart';
 import 'package:acter/common/providers/space_providers.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
-import 'package:riverpod/riverpod.dart';
 import 'package:logging/logging.dart';
+import 'package:riverpod/riverpod.dart';
 
 final _log = Logger('a3::space::providers::suggested');
 
diff --git a/app/lib/features/space/settings/pages/apps_settings_page.dart b/app/lib/features/space/settings/pages/apps_settings_page.dart
index a92c24ea6a1c..f66bcd80dad3 100644
--- a/app/lib/features/space/settings/pages/apps_settings_page.dart
+++ b/app/lib/features/space/settings/pages/apps_settings_page.dart
@@ -342,9 +342,12 @@ class SpaceAppsSettingsPage extends ConsumerWidget {
           );
         },
         loading: () => const Center(child: Text('loading')),
-        error: (e, s) => Center(
-          child: Text('Error loading app settings: $e'),
-        ),
+        error: (e, s) {
+          _log.severe('Failed to load space settings', e, s);
+          return Center(
+            child: Text(L10n.of(context).loadingFailed(e)),
+          );
+        },
       ),
     );
   }
diff --git a/app/lib/features/space/settings/pages/visibility_accessibility_page.dart b/app/lib/features/space/settings/pages/visibility_accessibility_page.dart
index 723e355b64b5..b186f194b28c 100644
--- a/app/lib/features/space/settings/pages/visibility_accessibility_page.dart
+++ b/app/lib/features/space/settings/pages/visibility_accessibility_page.dart
@@ -3,18 +3,18 @@ import 'package:acter/common/providers/sdk_provider.dart';
 import 'package:acter/common/providers/space_providers.dart';
 import 'package:acter/common/utils/utils.dart';
 import 'package:acter/common/widgets/spaces/has_space_permission.dart';
-import 'package:acter/common/widgets/visibility/room_visibilty_type.dart';
 import 'package:acter/common/widgets/spaces/space_selector_drawer.dart';
+import 'package:acter/common/widgets/visibility/room_visibilty_type.dart';
 import 'package:acter_avatar/acter_avatar.dart';
 import 'package:atlas_icons/atlas_icons.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
-final _log = Logger('a3::space::settings::visibility_accessibility_settings');
+final _log = Logger('a3::space::settings::visibility_accessibility');
 
 class VisibilityAccessibilityPage extends ConsumerStatefulWidget {
   final String roomId;
@@ -109,9 +109,12 @@ class _VisibilityAccessibilityPageState
                 },
         );
       },
-      error: (e, st) => const RoomVisibilityType(
-        selectedVisibilityEnum: RoomVisibility.Private,
-      ),
+      error: (e, st) {
+        _log.severe('Failed to load room visibility', e, st);
+        return const RoomVisibilityType(
+          selectedVisibilityEnum: RoomVisibility.Private,
+        );
+      },
       loading: () => const Skeletonizer(
         child: RoomVisibilityType(
           selectedVisibilityEnum: RoomVisibility.Private,
@@ -150,7 +153,7 @@ class _VisibilityAccessibilityPageState
               },
             ),
             error: (error, stack) {
-              _log.severe('Loading Space Info failed', error, stack);
+              _log.severe('Failed to load the allowed rooms', error, stack);
               return _spaceItemCard(
                 'Loading Space Info failed',
                 subtitle: Text('$error'),
@@ -214,7 +217,7 @@ class _VisibilityAccessibilityPageState
     return ref.watch(briefSpaceItemProvider(spaceId)).when(
           data: (d) => _spaceFoundUI(d, canEdit),
           error: (error, stack) {
-            _log.severe('Loading Space Info failed', error, stack);
+            _log.severe('Failed to load brief of space', error, stack);
             return _spaceItemCard(
               spaceId,
               subtitle: Text('Loading Space Info failed: $error'),
diff --git a/app/lib/features/space/sheets/link_room_sheet.dart b/app/lib/features/space/sheets/link_room_sheet.dart
index df0d990eefa2..8edf591e0388 100644
--- a/app/lib/features/space/sheets/link_room_sheet.dart
+++ b/app/lib/features/space/sheets/link_room_sheet.dart
@@ -14,6 +14,9 @@ import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::space::link_room_sheet');
 
 // ChildRoomType configures the sub child type of the `Spaces`
 enum ChildRoomType {
@@ -138,7 +141,10 @@ class _LinkRoomPageConsumerState extends ConsumerState<LinkRoomPage> {
                   ],
                 );
         },
-        error: (e, s) => errorUI(L10n.of(context).error(e)),
+        error: (e, s) {
+          _log.severe('Failed to load the details of selected space', e, s);
+          return errorUI(L10n.of(context).loadingFailed(e));
+        },
         loading: () => Container(),
       ),
     );
@@ -178,7 +184,10 @@ class _LinkRoomPageConsumerState extends ConsumerState<LinkRoomPage> {
       data: (chats) => chats.isEmpty
           ? Text(L10n.of(context).noChatsFoundMatchingYourSearchTerm)
           : chatListUI(chats),
-      error: (e, s) => errorUI(L10n.of(context).searchingFailed(e)),
+      error: (e, s) {
+        _log.severe('Failed to search chats', e, s);
+        return errorUI(L10n.of(context).searchingFailed(e));
+      },
       loading: () => loadingUI(),
     );
   }
@@ -233,7 +242,10 @@ class _LinkRoomPageConsumerState extends ConsumerState<LinkRoomPage> {
         return spaceListUI(spaces);
       },
       loading: () => loadingUI(),
-      error: (e, s) => errorUI(L10n.of(context).searchingFailed(e)),
+      error: (e, s) {
+        _log.severe('Failed to search spaces', e, s);
+        return errorUI(L10n.of(context).searchingFailed(e));
+      },
     );
   }
 
diff --git a/app/lib/features/space/widgets/related/chats_helpers.dart b/app/lib/features/space/widgets/related/chats_helpers.dart
index 36b3bf9ce12e..76e93b31ec05 100644
--- a/app/lib/features/space/widgets/related/chats_helpers.dart
+++ b/app/lib/features/space/widgets/related/chats_helpers.dart
@@ -3,10 +3,13 @@ import 'package:acter/common/widgets/chat/convo_card.dart';
 import 'package:acter/common/widgets/chat/convo_hierarchy_card.dart';
 import 'package:acter/router/utils.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::space::related::chats_helpers');
+
 Widget chatsListUI(WidgetRef ref, List<String> chats, int chatsLimit) {
   return ListView.builder(
     shrinkWrap: true,
@@ -54,10 +57,16 @@ Widget renderFurther(
         },
       );
     },
-    error: (e, s) =>
-        Card(child: Text(L10n.of(context).errorLoadingRelatedChats(e))),
+    error: (e, s) {
+      _log.severe('Failed to load the related chats', e, s);
+      return Card(
+        child: Text(L10n.of(context).errorLoadingRelatedChats(e)),
+      );
+    },
     loading: () => Skeletonizer(
-      child: Card(child: Text(L10n.of(context).loadingOtherChats)),
+      child: Card(
+        child: Text(L10n.of(context).loadingOtherChats),
+      ),
     ),
   );
 }
diff --git a/app/lib/features/space/widgets/related/spaces_helpers.dart b/app/lib/features/space/widgets/related/spaces_helpers.dart
index 5487633031d5..62964b595b9d 100644
--- a/app/lib/features/space/widgets/related/spaces_helpers.dart
+++ b/app/lib/features/space/widgets/related/spaces_helpers.dart
@@ -9,7 +9,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
-final _log = Logger('a3::space::widget::related::spaces_helpers');
+final _log = Logger('a3::space::related::spaces_helpers');
 
 List<Widget>? _renderKnownSubspaces(
   BuildContext context,
@@ -92,15 +92,12 @@ Widget renderMoreSubspaces(
         },
       );
     },
-    error: (error, s) {
-      _log.severe(
-        'Loading subspaces from remote failed $spaceIdOrAlias',
-        error,
-        s,
-      );
+    error: (e, s) {
+      _log.severe('Failed to load the related subspaces', e, s);
       return Card(
-        child:
-            ListTile(title: Text(L10n.of(context).loadingSpacesFailed(error))),
+        child: ListTile(
+          title: Text(L10n.of(context).loadingSpacesFailed(e)),
+        ),
       );
     },
     loading: () => const Skeletonizer(
diff --git a/app/lib/features/space/widgets/space_header_profile.dart b/app/lib/features/space/widgets/space_header_profile.dart
index a2f52e14df5e..e8179cddeb54 100644
--- a/app/lib/features/space/widgets/space_header_profile.dart
+++ b/app/lib/features/space/widgets/space_header_profile.dart
@@ -9,8 +9,11 @@ import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::space::space_header_profile');
+
 class SpaceHeaderProfile extends ConsumerWidget {
   static const headerKey = Key('space-header');
 
@@ -126,9 +129,10 @@ class SpaceHeaderProfile extends ConsumerWidget {
           ),
         );
       },
-      error: (error, stack) => Text(
-        L10n.of(context).loadingMembersFailed(error),
-      ),
+      error: (error, stack) {
+        _log.severe('Failed to load members in space', error, stack);
+        return Text(L10n.of(context).loadingMembersFailed(error));
+      },
       loading: () => const Skeletonizer(
         child: Wrap(
           direction: Axis.horizontal,
diff --git a/app/lib/features/space/widgets/space_sections/about_section.dart b/app/lib/features/space/widgets/space_sections/about_section.dart
index 159e49d61652..cb36a809beb9 100644
--- a/app/lib/features/space/widgets/space_sections/about_section.dart
+++ b/app/lib/features/space/widgets/space_sections/about_section.dart
@@ -3,8 +3,11 @@ import 'package:acter/features/space/actions/set_space_topic.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::space::sections::about');
+
 class AboutSection extends ConsumerWidget {
   final String spaceId;
 
@@ -60,9 +63,10 @@ class AboutSection extends ConsumerWidget {
           ),
         );
       },
-      error: (error, stack) => Text(
-        L10n.of(context).loadingFailed(error),
-      ),
+      error: (error, stack) {
+        _log.severe('Failed to load space', error, stack);
+        return Text(L10n.of(context).loadingFailed(error));
+      },
       loading: () => Skeletonizer(
         child: Text(L10n.of(context).loading),
       ),
diff --git a/app/lib/features/space/widgets/space_sections/chats_section.dart b/app/lib/features/space/widgets/space_sections/chats_section.dart
index 9bee2206e686..e0a5b87e151f 100644
--- a/app/lib/features/space/widgets/space_sections/chats_section.dart
+++ b/app/lib/features/space/widgets/space_sections/chats_section.dart
@@ -4,11 +4,14 @@ import 'package:acter/features/space/widgets/related/chats_helpers.dart';
 import 'package:acter/features/space/widgets/related/util.dart';
 import 'package:acter/features/space/widgets/space_sections/section_header.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
 import 'package:skeletonizer/skeletonizer.dart';
 
+final _log = Logger('a3::space::sections::chats');
+
 class ChatsSection extends ConsumerWidget {
   final String spaceId;
   final int limit;
@@ -28,8 +31,12 @@ class ChatsSection extends ConsumerWidget {
         ref,
         spaceRelationsOverview.knownChats,
       ),
-      error: (error, stack) =>
-          Center(child: Text(L10n.of(context).loadingFailed(error))),
+      error: (error, stack) {
+        _log.severe('Failed to load the related spaces', error, stack);
+        return Center(
+          child: Text(L10n.of(context).loadingSpacesFailed(error)),
+        );
+      },
       loading: () => Skeletonizer(
         child: Center(
           child: Text(L10n.of(context).loading),
diff --git a/app/lib/features/space/widgets/space_sections/events_section.dart b/app/lib/features/space/widgets/space_sections/events_section.dart
index cd58e7c5fd18..3e8b12c0d33e 100644
--- a/app/lib/features/space/widgets/space_sections/events_section.dart
+++ b/app/lib/features/space/widgets/space_sections/events_section.dart
@@ -4,9 +4,12 @@ import 'package:acter/features/events/widgets/event_item.dart';
 import 'package:acter/features/space/widgets/space_sections/section_header.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::space::sections::cal_events');
 
 class EventsSection extends ConsumerWidget {
   final String spaceId;
@@ -21,14 +24,16 @@ class EventsSection extends ConsumerWidget {
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final eventsList = ref.watch(
-      eventListSearchFilterProvider(
-        (spaceId: spaceId, searchText: ''),
-      ),
+      eventListSearchFilterProvider((spaceId: spaceId, searchText: '')),
     );
     return eventsList.when(
       data: (events) => buildEventsSectionUI(context, events),
-      error: (error, stack) =>
-          Center(child: Text(L10n.of(context).loadingFailed(error))),
+      error: (e, s) {
+        _log.severe('Failed to search cal events in space', e, s);
+        return Center(
+          child: Text(L10n.of(context).searchingFailed(e)),
+        );
+      },
       loading: () => Center(
         child: Text(L10n.of(context).loading),
       ),
diff --git a/app/lib/features/space/widgets/space_sections/members_section.dart b/app/lib/features/space/widgets/space_sections/members_section.dart
index 99b2f423752d..4d5e11c5ce2b 100644
--- a/app/lib/features/space/widgets/space_sections/members_section.dart
+++ b/app/lib/features/space/widgets/space_sections/members_section.dart
@@ -3,9 +3,12 @@ import 'package:acter/common/utils/routes.dart';
 import 'package:acter/features/member/widgets/member_list_entry.dart';
 import 'package:acter/features/space/widgets/space_sections/section_header.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::space::sections::members');
 
 class MembersSection extends ConsumerWidget {
   final String spaceId;
@@ -22,8 +25,12 @@ class MembersSection extends ConsumerWidget {
     final membersList = ref.watch(membersIdsProvider(spaceId));
     return membersList.when(
       data: (members) => buildMembersSectionUI(context, members),
-      error: (error, stack) =>
-          Center(child: Text(L10n.of(context).loadingFailed(error))),
+      error: (error, stack) {
+        _log.severe('Failed to load members in space', error, stack);
+        return Center(
+          child: Text(L10n.of(context).loadingMembersFailed(error)),
+        );
+      },
       loading: () => Center(
         child: Text(L10n.of(context).loading),
       ),
diff --git a/app/lib/features/space/widgets/space_sections/pins_section.dart b/app/lib/features/space/widgets/space_sections/pins_section.dart
index 1284140f14ab..7c5f7368f79e 100644
--- a/app/lib/features/space/widgets/space_sections/pins_section.dart
+++ b/app/lib/features/space/widgets/space_sections/pins_section.dart
@@ -4,9 +4,12 @@ import 'package:acter/features/pins/widgets/pin_list_item.dart';
 import 'package:acter/features/space/widgets/space_sections/section_header.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::space::sections::pins');
 
 class PinsSection extends ConsumerWidget {
   final String spaceId;
@@ -23,8 +26,12 @@ class PinsSection extends ConsumerWidget {
     final pinList = ref.watch(pinListProvider(spaceId));
     return pinList.when(
       data: (pins) => buildPinsSectionUI(context, pins),
-      error: (error, stack) =>
-          Center(child: Text(L10n.of(context).loadingFailed(error))),
+      error: (error, stack) {
+        _log.severe('Failed to load pins in space', error, stack);
+        return Center(
+          child: Text(L10n.of(context).loadingFailed(error)),
+        );
+      },
       loading: () => Center(
         child: Text(L10n.of(context).loading),
       ),
diff --git a/app/lib/features/space/widgets/space_sections/spaces_section.dart b/app/lib/features/space/widgets/space_sections/spaces_section.dart
index f55cef616c6a..2790521b9925 100644
--- a/app/lib/features/space/widgets/space_sections/spaces_section.dart
+++ b/app/lib/features/space/widgets/space_sections/spaces_section.dart
@@ -8,6 +8,9 @@ import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::space::sections::spaces');
 
 class SpacesSection extends ConsumerWidget {
   final String spaceId;
@@ -28,8 +31,12 @@ class SpacesSection extends ConsumerWidget {
         ref,
         spaceRelationsOverview.knownSubspaces,
       ),
-      error: (error, stack) =>
-          Center(child: Text(L10n.of(context).loadingFailed(error))),
+      error: (error, stack) {
+        _log.severe('Failed to load the related spaces', error, stack);
+        return Center(
+          child: Text(L10n.of(context).loadingSpacesFailed(error)),
+        );
+      },
       loading: () => Center(
         child: Text(L10n.of(context).loading),
       ),
diff --git a/app/lib/features/space/widgets/space_sections/tasks_section.dart b/app/lib/features/space/widgets/space_sections/tasks_section.dart
index 8f6ce82998e2..2cfbdb536c78 100644
--- a/app/lib/features/space/widgets/space_sections/tasks_section.dart
+++ b/app/lib/features/space/widgets/space_sections/tasks_section.dart
@@ -6,6 +6,9 @@ import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::space::sections::tasks');
 
 class TasksSection extends ConsumerWidget {
   final String spaceId;
@@ -22,8 +25,12 @@ class TasksSection extends ConsumerWidget {
     final taskList = ref.watch(taskListProvider(spaceId));
     return taskList.when(
       data: (tasks) => buildTasksSectionUI(context, tasks),
-      error: (error, stack) =>
-          Center(child: Text(L10n.of(context).loadingFailed(error))),
+      error: (error, stack) {
+        _log.severe('Failed to load tasks in space', error, stack);
+        return Center(
+          child: Text(L10n.of(context).loadingTasksFailed(error)),
+        );
+      },
       loading: () => Center(
         child: Text(L10n.of(context).loading),
       ),
diff --git a/app/lib/features/super_invites/dialogs/redeem_dialog.dart b/app/lib/features/super_invites/dialogs/redeem_dialog.dart
index c7e07c95c75b..533b6e8efd0a 100644
--- a/app/lib/features/super_invites/dialogs/redeem_dialog.dart
+++ b/app/lib/features/super_invites/dialogs/redeem_dialog.dart
@@ -12,7 +12,7 @@ import 'package:skeletonizer/skeletonizer.dart';
 const redeemConfirmKey = Key('super-invite-redeem-confirm-btn');
 const redeemInfoKey = Key('super-invites-redeem-info');
 
-final _log = Logger('a3::super_invites::redeem_dialog');
+final _log = Logger('a3::super_invites::redeem');
 
 class _ShowRedeemTokenDialog extends ConsumerWidget {
   final String token;
@@ -33,13 +33,9 @@ class _ShowRedeemTokenDialog extends ConsumerWidget {
           children: [
             info.when(
               data: (info) => renderInfo(context, ref, info),
-              error: (error, stackTrace) {
-                _log.severe(
-                  'Loading super invite failed: $token',
-                  error,
-                  stackTrace,
-                );
-                final errorStr = error.toString();
+              error: (e, s) {
+                _log.severe('Failed to load the super invite: $token', e, s);
+                final errorStr = e.toString();
                 if (errorStr.contains('error: [404]')) {
                   // Server doesn't yet support previewing
                   return Text(
@@ -48,20 +44,16 @@ class _ShowRedeemTokenDialog extends ConsumerWidget {
                 }
                 if (errorStr.contains('error: [403]')) {
                   // 403 means we can't use that anymore
-                  return Text(
-                    L10n.of(context).superInvitesDeleted(token),
-                  );
+                  return Text(L10n.of(context).superInvitesDeleted(token));
                 }
-                return Text(L10n.of(context).loadingFailed(error));
+                return Text(L10n.of(context).loadingFailed(e));
               },
               loading: () => Skeletonizer(
                 child: Card(
                   child: ListTile(
                     leading: ActerAvatar(
                       options: const AvatarOptions.DM(
-                        AvatarInfo(
-                          uniqueId: 'nothing',
-                        ),
+                        AvatarInfo(uniqueId: 'nothing'),
                         size: 18,
                       ),
                     ),
@@ -101,9 +93,7 @@ class _ShowRedeemTokenDialog extends ConsumerWidget {
               displayName != null ? '$displayName ($userId)' : userId,
             ),
           ),
-          subtitle: Text(
-            L10n.of(context).superInvitedTo(info.roomsCount()),
-          ),
+          subtitle: Text(L10n.of(context).superInvitedTo(info.roomsCount())),
           leading: ActerAvatar(
             options: AvatarOptions.DM(
               AvatarInfo(
diff --git a/app/lib/features/super_invites/pages/super_invites.dart b/app/lib/features/super_invites/pages/super_invites.dart
index b56350907cbd..6a8d141acf81 100644
--- a/app/lib/features/super_invites/pages/super_invites.dart
+++ b/app/lib/features/super_invites/pages/super_invites.dart
@@ -8,6 +8,9 @@ import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::super_invites::list');
 
 class SuperInvitesPage extends ConsumerWidget {
   static Key createNewToken = const Key('super-invites-create');
@@ -29,7 +32,7 @@ class SuperInvitesPage extends ConsumerWidget {
               icon: const Icon(Atlas.arrows_rotating_right_thin),
               iconSize: 28,
               color: Theme.of(context).colorScheme.surface,
-              onPressed: () async {
+              onPressed: () {
                 ref.invalidate(superInvitesTokensProvider);
               },
             ),
@@ -38,7 +41,7 @@ class SuperInvitesPage extends ConsumerWidget {
               icon: const Icon(Atlas.plus_circle_thin),
               iconSize: 28,
               color: Theme.of(context).colorScheme.surface,
-              onPressed: () async {
+              onPressed: () {
                 context.pushNamed(Routes.actionCreateSuperInvite.name);
               },
             ),
@@ -98,12 +101,11 @@ class SuperInvitesPage extends ConsumerWidget {
                         ),
                       ),
                     ),
-              error: (error, stack) {
+              error: (e, s) {
+                _log.severe('Failed to load the super invite tokens', e, s);
                 return SliverToBoxAdapter(
                   child: Center(
-                    child: Text(
-                      L10n.of(context).failedToLoadInviteCodes(error),
-                    ),
+                    child: Text(L10n.of(context).failedToLoadInviteCodes(e)),
                   ),
                 );
               },
diff --git a/app/lib/features/tasks/pages/task_item_detail_page.dart b/app/lib/features/tasks/pages/task_item_detail_page.dart
index d22bf0c5a16f..d54233516331 100644
--- a/app/lib/features/tasks/pages/task_item_detail_page.dart
+++ b/app/lib/features/tasks/pages/task_item_detail_page.dart
@@ -21,7 +21,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 
-final _log = Logger('a3::tasks::task_item_details_page');
+final _log = Logger('a3::tasks::task_item_details');
 
 class TaskItemDetailPage extends ConsumerWidget {
   final String taskListId;
@@ -131,8 +131,15 @@ class TaskItemDetailPage extends ConsumerWidget {
           ),
         ],
       ),
-      error: (e, s) => AppBar(title: Text(L10n.of(context).failedToLoad(e))),
-      loading: () => AppBar(title: Text(L10n.of(context).loading)),
+      error: (e, s) {
+        _log.severe('Failed to load task', e, s);
+        return AppBar(
+          title: Text(L10n.of(context).loadingFailed(e)),
+        );
+      },
+      loading: () => AppBar(
+        title: Text(L10n.of(context).loading),
+      ),
     );
   }
 
@@ -177,7 +184,10 @@ class TaskItemDetailPage extends ConsumerWidget {
   ) {
     return task.when(
       data: (data) => taskData(context, data, ref),
-      error: (e, s) => Text(L10n.of(context).failedToLoad(e)),
+      error: (e, s) {
+        _log.severe('Failed to load task', e, s);
+        return Text(L10n.of(context).loadingFailed(e));
+      },
       loading: () => const TaskItemDetailPageSkeleton(),
     );
   }
diff --git a/app/lib/features/tasks/pages/task_list_details_page.dart b/app/lib/features/tasks/pages/task_list_details_page.dart
index 4bd6dbc82891..b71da73f44a3 100644
--- a/app/lib/features/tasks/pages/task_list_details_page.dart
+++ b/app/lib/features/tasks/pages/task_list_details_page.dart
@@ -1,8 +1,8 @@
 import 'package:acter/common/actions/redact_content.dart';
+import 'package:acter/common/actions/report_content.dart';
 import 'package:acter/common/widgets/edit_html_description_sheet.dart';
 import 'package:acter/common/widgets/edit_title_sheet.dart';
 import 'package:acter/common/widgets/render_html.dart';
-import 'package:acter/common/actions/report_content.dart';
 import 'package:acter/features/attachments/widgets/attachment_section.dart';
 import 'package:acter/features/comments/widgets/comments_section.dart';
 import 'package:acter/features/tasks/providers/tasklists_providers.dart';
@@ -14,7 +14,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:logging/logging.dart';
 
-final _log = Logger('a3::tasks::task_list_details_page');
+final _log = Logger('a3::tasks::tasklist_details');
 
 class TaskListDetailPage extends ConsumerStatefulWidget {
   static const pageKey = Key('task-list-details-page');
@@ -92,7 +92,12 @@ class _TaskListPageState extends ConsumerState<TaskListDetailPage> {
           ),
         ],
       ),
-      error: (e, s) => AppBar(title: Text(L10n.of(context).failedToLoad(e))),
+      error: (e, s) {
+        _log.severe('Failed to load tasklist', e, s);
+        return AppBar(
+          title: Text(L10n.of(context).loadingFailed(e)),
+        );
+      },
       loading: () => AppBar(
         title: Text(L10n.of(context).loading),
       ),
@@ -128,7 +133,10 @@ class _TaskListPageState extends ConsumerState<TaskListDetailPage> {
     final taskList = ref.watch(taskListItemProvider(widget.taskListId));
     return taskList.when(
       data: (data) => _buildTaskListData(data),
-      error: (e, s) => Text(L10n.of(context).failedToLoad(e)),
+      error: (e, s) {
+        _log.severe('Failed to load tasklist', e, s);
+        return Text(L10n.of(context).loadingFailed(e));
+      },
       loading: () => Text(L10n.of(context).loading),
     );
   }
diff --git a/app/lib/features/tasks/pages/tasks_list_page.dart b/app/lib/features/tasks/pages/tasks_list_page.dart
index 671418e59a85..095e5fab8ff6 100644
--- a/app/lib/features/tasks/pages/tasks_list_page.dart
+++ b/app/lib/features/tasks/pages/tasks_list_page.dart
@@ -14,6 +14,9 @@ import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::tasks::tasklist');
 
 class TasksListPage extends ConsumerStatefulWidget {
   static const scrollView = Key('space-task-lists');
@@ -108,9 +111,12 @@ class _TasksListPageConsumerState extends ConsumerState<TasksListPage> {
         Expanded(
           child: tasksList.when(
             data: (tasks) => _buildTasksList(tasks),
-            error: (error, stack) => Center(
-              child: Text(L10n.of(context).loadingFailed(error)),
-            ),
+            error: (e, s) {
+              _log.severe('Failed to search tasklists in space', e, s);
+              return Center(
+                child: Text(L10n.of(context).searchingFailed(e)),
+              );
+            },
             loading: () => const TasksListSkeleton(),
           ),
         ),
diff --git a/app/lib/features/tasks/providers/notifiers.dart b/app/lib/features/tasks/providers/notifiers.dart
index 5845ff71e8bd..f3b60a1117c8 100644
--- a/app/lib/features/tasks/providers/notifiers.dart
+++ b/app/lib/features/tasks/providers/notifiers.dart
@@ -6,7 +6,7 @@ import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:logging/logging.dart';
 import 'package:riverpod/riverpod.dart';
 
-final _log = Logger('a3::tasks::providers');
+final _log = Logger('a3::tasks::notifiers');
 
 //List of task items based on the specified task list
 class TaskItemsListNotifier
diff --git a/app/lib/features/tasks/widgets/task_item.dart b/app/lib/features/tasks/widgets/task_item.dart
index 1eab00bc1bf7..4e093915e197 100644
--- a/app/lib/features/tasks/widgets/task_item.dart
+++ b/app/lib/features/tasks/widgets/task_item.dart
@@ -59,13 +59,13 @@ class TaskItem extends ConsumerWidget {
             trailing: trailing(ref, task),
           ),
           error: (error, stack) {
-            _log.severe('failed to load task', error, stack);
+            _log.severe('Failed to load task', error, stack);
             return ListTile(
-              title: Text('Loading of task failed: $error'),
+              title: Text(L10n.of(context).loadingFailed(error)),
             );
           },
-          loading: () => const ListTile(
-            title: Text('loading'),
+          loading: () => ListTile(
+            title: Text(L10n.of(context).loading),
           ),
         );
   }
@@ -127,7 +127,10 @@ class TaskItem extends ConsumerWidget {
                       ),
                     ],
                   ),
-                  error: (e, s) => Text(L10n.of(context).loadingFailed(e)),
+                  error: (e, s) {
+                    _log.severe('Failed to load task', e, s);
+                    return Text(L10n.of(context).loadingFailed(e));
+                  },
                   loading: () => Skeletonizer(
                     child: Text(L10n.of(context).loading),
                   ),
diff --git a/app/lib/features/tasks/widgets/task_items_list_widget.dart b/app/lib/features/tasks/widgets/task_items_list_widget.dart
index 444f45479792..548eb795c8e5 100644
--- a/app/lib/features/tasks/widgets/task_items_list_widget.dart
+++ b/app/lib/features/tasks/widgets/task_items_list_widget.dart
@@ -10,6 +10,9 @@ import 'package:flutter/material.dart';
 import 'package:flutter_easyloading/flutter_easyloading.dart';
 import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:logging/logging.dart';
+
+final _log = Logger('a3::tasks::list');
 
 class TaskItemsListWidget extends ConsumerWidget {
   final TaskList taskList;
@@ -28,7 +31,10 @@ class TaskItemsListWidget extends ConsumerWidget {
     final tasks = ref.watch(taskItemsListProvider(taskList));
     return tasks.when(
       data: (overview) => taskData(context, overview),
-      error: (error, stack) => Text(L10n.of(context).errorLoadingTasks(error)),
+      error: (error, stack) {
+        _log.severe('Failed to load tasklist', error, stack);
+        return Text(L10n.of(context).errorLoadingTasks(error));
+      },
       loading: () => const TaskItemsSkeleton(),
     );
   }
diff --git a/app/lib/features/tasks/widgets/task_list_item_card.dart b/app/lib/features/tasks/widgets/task_list_item_card.dart
index 59cdfa5d1352..d1e567f7ce7d 100644
--- a/app/lib/features/tasks/widgets/task_list_item_card.dart
+++ b/app/lib/features/tasks/widgets/task_list_item_card.dart
@@ -4,6 +4,7 @@ import 'package:acter/features/tasks/providers/tasklists_providers.dart';
 import 'package:acter/features/tasks/widgets/task_items_list_widget.dart';
 import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/l10n.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
 import 'package:logging/logging.dart';
@@ -47,13 +48,13 @@ class TaskListItemCard extends ConsumerWidget {
             ),
           ),
           error: (error, stack) {
-            _log.severe('failed to load tasklist', error, stack);
+            _log.severe('Failed to load tasklist', error, stack);
             return Card(
-              child: Text('Loading of tasklist failed: $error'),
+              child: Text(L10n.of(context).errorLoadingTasks(error)),
             );
           },
-          loading: () => const Card(
-            child: Text('loading'),
+          loading: () => Card(
+            child: Text(L10n.of(context).loading),
           ),
         );
   }
diff --git a/app/lib/l10n/app_ar.arb b/app/lib/l10n/app_ar.arb
index 5bd66c7dcf90..ba7c3532ae11 100644
--- a/app/lib/l10n/app_ar.arb
+++ b/app/lib/l10n/app_ar.arb
@@ -855,16 +855,12 @@
   "@errorSubmittingComment": {},
   "errorUpdatingEvent": "خطأ في تحديث الحدث: {error}",
   "@errorUpdatingEvent": {},
-  "failedToLoad": "فشل في التحميل: {error}",
-  "@failedToLoad": {},
   "encryptionBackupDisableActionKeepIt": "لا، احتفظ بها",
   "@encryptionBackupDisableActionKeepIt": {},
   "encryptionBackupDisableActionDestroyIt": "نعم، أتلفه",
   "@encryptionBackupDisableActionDestroyIt": {},
   "encryptionBackupRecover": "استرجاع النسخة الاحتياطية للتشفير",
   "@encryptionBackupRecover": {},
-  "errorLoading": "خطأ في التحميل {error}",
-  "@errorLoading": {},
   "eventDescriptionsData": "بيانات شرح الحدث",
   "@eventDescriptionsData": {},
   "eventTitleData": "بيانات عنوان الحدث",
@@ -1172,5 +1168,1116 @@
   "errorUpdatingDescription": "خطأ في تحديث الوصف: {error}",
   "@errorUpdatingDescription": {},
   "formatMustBe": "يجب أن تكون الصيغة @user:server.tld",
-  "@formatMustBe": {}
+  "@formatMustBe": {},
+  "closingRoomTitleDescription": "عند إغلاق هذه الغرفة، سنقوم بما يلي :\n\n - طرد كل من لديه مستوى إذن أقل من الإذن الذي لديك \n - إزالتها كفرع من الفضاءات الأم (حيث لديك الأذونات للقيام بذلك),\n - ضبط قاعدة الدعوة إلى \"خاص'\n - سوف تغادر الغرفة.\n\nلا يمكن التراجع فيه. هل أنت متأكد من أنك تريد الإغلاق؟",
+  "@closingRoomTitleDescription": {},
+  "noTasksListAvailableDescription": "شارك المهام ذات الأولوية مع مجتمعك وقم بإدارتها، مثل أي قائمة مهام، حتى يتم إطلاع الجميع على آخر المستجدات.",
+  "@noTasksListAvailableDescription": {},
+  "suggestedRoomsSubtitle": "نقترح عليك أيضاً الانضمام إلى",
+  "@suggestedRoomsSubtitle": {},
+  "invitingSpaceMembersProgress": "دعوة عضو فضاء{count} / {total}",
+  "@invitingSpaceMembersProgress": {},
+  "closingRoomDoneBut": "تم الإغلاق وتمّت مغادرتك. ولكن لم تتمكن من إزالة {skipped} المستخدمين الآخرين وإزالتها كفرع من {skippedParents} الفضاءات بسبب عدم وجود إذن. قد لا يزال بإمكان الآخرين الوصول إليها.",
+  "@closingRoomDoneBut": {},
+  "analyticsDescription2": "هذه بالطبع مجهولة المصدر ولا تحتوي على أي معلومات خاصة",
+  "@analyticsDescription2": {},
+  "sendCrashReportsInfo": "شارك تعقّب الأعطال تلقائياً عبر نظام Sentry مع فريق Acter",
+  "@sendCrashReportsInfo": {},
+  "memberDescriptionsData": "بيانات وصف العضو",
+  "@memberDescriptionsData": {},
+  "noIStay": "لا، سأبقى",
+  "@noIStay": {},
+  "introPageDescription2ndLine": "تواصل مع زملائك النشطاء، وتبادل الأفكار وتعاون معهم لإحداث تغيير هادف.",
+  "@introPageDescription2ndLine": {},
+  "shareFailed": "المشاركة فشلت: {error}",
+  "@shareFailed": {},
+  "joinSpaceTutorialTitle": "الانضمام إلى الفضاء الموجود",
+  "@joinSpaceTutorialTitle": {},
+  "creatingSpace": "إنشاء فضاء",
+  "@creatingSpace": {},
+  "defaultModes": "الإعدادات التلقائية",
+  "@defaultModes": {},
+  "encryptedSpace": "فضاء مشفر",
+  "@encryptedSpace": {},
+  "loginSuccess": "تم تسجيل الدخول بنجاح",
+  "@loginSuccess": {},
+  "newPassword": "كلمة المرور الجديدة",
+  "@newPassword": {},
+  "personalSettings": "الإعدادات الخاصة",
+  "@personalSettings": {},
+  "suggestedUsers": "المستخدمين المقترحين",
+  "@suggestedUsers": {},
+  "emailAddress": "عنوان البريد الإلكتروني",
+  "@emailAddress": {},
+  "noMatchingTasksListFound": "لم يتم العثور على قائمة المهام المطابقة",
+  "@noMatchingTasksListFound": {},
+  "introPageDescriptionHl": " مجتمع صنّاع التغيير.",
+  "@introPageDescriptionHl": {},
+  "linkExistingSpace": "ربط الفضاء الموجود",
+  "@linkExistingSpace": {},
+  "manageBudgetsCooperatively": "إدارة الميزانيات بشكل جماعي",
+  "@manageBudgetsCooperatively": {},
+  "reportThisMessage": "الإبلاغ عن هذه الرسالة",
+  "@reportThisMessage": {},
+  "theParentSpace": "الفضاء الأم",
+  "@theParentSpace": {},
+  "updatePowerLevel": "تحديث مستوى الإذن",
+  "@updatePowerLevel": {},
+  "addImageSlide": "أضف شريحة صورة",
+  "@addImageSlide": {},
+  "changingNotificationMode": "تغيير وضع الإشعارات…",
+  "@changingNotificationMode": {},
+  "peopleGoing": "{count} أشخاص مغادرون",
+  "@peopleGoing": {},
+  "pushTargetDetails": "تفاصيل الهدف المدفوع",
+  "@pushTargetDetails": {},
+  "rageShakeTargetUrl": "رابط الهدف Rageshake",
+  "@rageShakeTargetUrl": {},
+  "searchPublicDirectory": "البحث في الدليل العام",
+  "@searchPublicDirectory": {},
+  "sendingEmailFailed": "فشل الإرسال: {error}",
+  "@sendingEmailFailed": {},
+  "verificationRequestWaitingFor": "في انتظار {sender}…",
+  "@verificationRequestWaitingFor": {
+    "placeholders": {
+      "sender": {
+        "example": "@kyra:acter.global",
+        "type": "String"
+      }
+    }
+  },
+  "dueSuccess": "تم تغيير الأجل بنجاح",
+  "@dueSuccess": {},
+  "loadingOtherChats": "جاري تحميل المحادثات الأخرى",
+  "@loadingOtherChats": {},
+  "loadingCommentsList": "جاري تحميل قائمة التعليقات",
+  "@loadingCommentsList": {},
+  "resettingPassword": "إعادة ضبط كلمة المرور الخاصة بك",
+  "@resettingPassword": {},
+  "errorSyncing": "خطأ في المزامنة: {error}",
+  "@errorSyncing": {},
+  "failedToReject": "لم ينجح الرفض",
+  "@failedToReject": {},
+  "copyToClipboard": "نسخ للحافظة",
+  "@copyToClipboard": {},
+  "createSpaceTutorialTitle": "إنشاء فضاء جديد",
+  "@createSpaceTutorialTitle": {},
+  "protectPrivacyTitle": "حماية خصوصيتك",
+  "@protectPrivacyTitle": {},
+  "endDateRequired": "تاريخ الانتهاء ضروري!",
+  "@endDateRequired": {},
+  "startGroupDM": "ابدأ إدارة مجموعة دي ام DM",
+  "@startGroupDM": {},
+  "invitingSpaceMembersLoading": "دعوة أعضاء الفضاء",
+  "@invitingSpaceMembersLoading": {},
+  "encryptionBackupNoBackupAction": "تفعيل النسخ الاحتياطي",
+  "@encryptionBackupNoBackupAction": {},
+  "forgotPassword": "هل نسيت كلمة المرور؟",
+  "@forgotPassword": {},
+  "reportSent": "تم إرسال التقرير!",
+  "@reportSent": {},
+  "selectLanguage": "اختر اللغة",
+  "@selectLanguage": {},
+  "unblockingUserProgress": "إلغاء حظر المستخدم",
+  "@unblockingUserProgress": {},
+  "unverifiedSessions": "دورات لم يتم التحقق منها",
+  "@unverifiedSessions": {},
+  "loadingVideo": "جارٍ تحميل الفيديو",
+  "@loadingVideo": {},
+  "avatarUploading": "تحميل الصورة الرمزية لملف التعريف",
+  "@avatarUploading": {},
+  "shareInviteCode": "شارك رمز الدعوة",
+  "@shareInviteCode": {},
+  "changingYourPassword": "تغيير كلمة المرور الخاصة بك",
+  "@changingYourPassword": {},
+  "reportTaskItem": "إبلاغ عن بند المهام",
+  "@reportTaskItem": {},
+  "dueDate": "تاريخ الأجل",
+  "@dueDate": {},
+  "encryptionBackupRecoverInputHint": "مفتاح الاسترجاع",
+  "@encryptionBackupRecoverInputHint": {},
+  "joinActer": "انضم إلىActer",
+  "@joinActer": {},
+  "labsAppFeatures": "خصائص التطبيق",
+  "@labsAppFeatures": {},
+  "settingsKeyBackUpTitle": "مفتاح النسخ الاحتياطي",
+  "@settingsKeyBackUpTitle": {},
+  "yesLeave": "نعم، مغادرة",
+  "@yesLeave": {},
+  "eventUpdate": "تحديث الفعالية",
+  "@eventUpdate": {},
+  "loadingChat": "جارٍ تحميل المحادثة…",
+  "@loadingChat": {},
+  "chatInvitedUserId": "{userId} دعا",
+  "@chatInvitedUserId": {},
+  "selectSpace": "اختر فضاءً",
+  "@selectSpace": {},
+  "encryptionBackupProvideKeyAction": "توفير مفتاح",
+  "@encryptionBackupProvideKeyAction": {},
+  "foundUsers": "المستخدمون الذين تم إيجادهم",
+  "@foundUsers": {},
+  "noThanks": "لا، شكراً",
+  "@noThanks": {},
+  "notificationsOverwrites": "إلغاء الإشعارات",
+  "@notificationsOverwrites": {},
+  "pollsAndSurveys": "استبيانات واستطلاعات الرأي",
+  "@pollsAndSurveys": {},
+  "resetPassword": "إعادة ضبط كلمة المرور",
+  "@resetPassword": {},
+  "roomNotFound": "لم يتم العثور على المحادثة",
+  "@roomNotFound": {},
+  "sasGotIt": "فهمت",
+  "@sasGotIt": {},
+  "debugInfo": "معلومات التصحيح",
+  "@debugInfo": {},
+  "debugLevel": "مستوى التصحيح",
+  "@debugLevel": {},
+  "httpProxy": "بروكسي HTTP",
+  "@httpProxy": {},
+  "mobilePushNotifications": "الإشعارات المدفوعة عبر الهاتف المحمول",
+  "@mobilePushNotifications": {},
+  "newEncryptedMessage": "رسالة جديدة مشفرة",
+  "@newEncryptedMessage": {},
+  "myDashboard": "لوحة المتابعة الخاصة بي",
+  "@myDashboard": {},
+  "newChat": "محادثة جديدة",
+  "@newChat": {},
+  "newMessage": "رسالة جديدة",
+  "@newMessage": {},
+  "notificationStatusSubmitted": "حالة الإشعار تم إرسالها",
+  "@notificationStatusSubmitted": {},
+  "noTopicFound": "لم يتم العثور على أي موضوع",
+  "@noTopicFound": {},
+  "notYetSupported": "غير مدعوم بعد",
+  "@notYetSupported": {},
+  "notificationsUnmuted": "تم إلغاء كتم الإشعارات",
+  "@notificationsUnmuted": {},
+  "notificationTargets": "أهداف الإشعارات",
+  "@notificationTargets": {},
+  "notVisible": "غير ظاهرة",
+  "@notVisible": {},
+  "postponeN": "تأجيل {days} أيام",
+  "@postponeN": {},
+  "postingTaskList": "نشر قائمة المهام",
+  "@postingTaskList": {},
+  "powerLevel": "مستوى الإذن",
+  "@powerLevel": {},
+  "sasIncomingReqNotifTitle": "طلب التحقق",
+  "@sasIncomingReqNotifTitle": {},
+  "saveChanges": "حفظ التغييرات",
+  "@saveChanges": {},
+  "savingCode": "رمز الحفظ",
+  "@savingCode": {},
+  "searchTermFieldHint": "البحث عن...",
+  "@searchTermFieldHint": {},
+  "seenBy": "تمت مشاهدته من قبل",
+  "@seenBy": {},
+  "spaceConfiguration": "تهيئة الفضاء",
+  "@spaceConfiguration": {},
+  "typingUser1": "{user} يقوم بالكتابة...",
+  "@typingUser1": {},
+  "updatingDisplayName": "تحديث اسم العرض",
+  "@updatingDisplayName": {},
+  "updatingProfileImage": "تحديث صورة ملف التعريف",
+  "@updatingProfileImage": {},
+  "usedTimes": "استُخدمت {count} مرات",
+  "@usedTimes": {},
+  "usersYouBlocked": "المستخدمون الذين قمت بحظرهم",
+  "@usersYouBlocked": {},
+  "updatingDue": "التحديث المستحق",
+  "@updatingDue": {},
+  "updatingEvent": "تحديث الفعالية",
+  "@updatingEvent": {},
+  "updatingRSVP": "تحديث RSVP",
+  "@updatingRSVP": {},
+  "updatingSpace": "تحديث الفضاء",
+  "@updatingSpace": {},
+  "uploadAvatar": "تحميل الصورة الرمزية",
+  "@uploadAvatar": {},
+  "verifyOtherSession": "التحقق من دورة أخرى",
+  "@verifyOtherSession": {},
+  "verifySession": "التحقق من الدورة",
+  "@verifySession": {},
+  "deactivateAccount": "إلغاء تفعيل الحساب",
+  "@deactivateAccount": {},
+  "deletingCode": "حذف الرمز",
+  "@deletingCode": {},
+  "dueToday": "الموعد المحدد اليوم",
+  "@dueToday": {},
+  "forgotYourPassword": "هل نسيت كلمة المرور؟",
+  "@forgotYourPassword": {},
+  "editInviteCode": "تعديل رمز الدعوة",
+  "@editInviteCode": {},
+  "createInviteCode": "إنشاء رمز الدعوة",
+  "@createInviteCode": {},
+  "pleaseSelectValidEndDate": "الرجاء تحديد تاريخ انتهاء الصلاحية",
+  "@pleaseSelectValidEndDate": {},
+  "powerLevelSubmitted": "تحديث مستوى الإذن لـ {module} المرسلة",
+  "@powerLevelSubmitted": {},
+  "optionalParentSpace": "فضاء الأم الاختياري",
+  "@optionalParentSpace": {},
+  "redeeming": "استرداد {token}",
+  "@redeeming": {},
+  "analyticsDescription1": "من خلال مشاركة بيانات الأعطال وتقارير الأخطاء معنا.",
+  "@analyticsDescription1": {},
+  "sendCrashReportsTitle": "إرسال تقارير الأعطال والأخطاء",
+  "@sendCrashReportsTitle": {},
+  "analyticsTitle": "ساعدنا على مساعدتك",
+  "@analyticsTitle": {},
+  "closingRoomRemovingFromParents": "الإغلاق قيد التنفيذ. إزالة الغرفة من الغرفة الأم {currentParent} / {totalParents}",
+  "@closingRoomRemovingFromParents": {},
+  "closingRoomRemovingMembers": "الإغلاق قيد التنفيذ. طرد عضو {kicked} / {total}",
+  "@closingRoomRemovingMembers": {},
+  "createDefaultChat": "إنشاء غرفة محادثة افتراضية كذلك",
+  "@createDefaultChat": {},
+  "closingRoomMatrixMsg": "تم إغلاق الغرفة",
+  "@closingRoomMatrixMsg": {},
+  "closingRoomTitle": "أغلق هذه الغرفة",
+  "@closingRoomTitle": {},
+  "closingRoomFailed": "الإغلاق فشل: {error}",
+  "@closingRoomFailed": {},
+  "dangerZone": "منطقة خطرة",
+  "@dangerZone": {},
+  "defaultNotification": "تلقائي{type}",
+  "@defaultNotification": {},
+  "deleteAttachment": "حذف المرفق",
+  "@deleteAttachment": {},
+  "deleteCode": "حذف الرمز",
+  "@deleteCode": {},
+  "deleteTarget": "حذف الهدف",
+  "@deleteTarget": {},
+  "deviceId": "معرّف الجهاز",
+  "@deviceId": {},
+  "deviceName": "اسم الجهاز",
+  "@deviceName": {},
+  "displayName": "اسم العرض",
+  "@displayName": {},
+  "due": "الأجل: {date}",
+  "@due": {},
+  "editDetails": "تعديل التفاصيل",
+  "@editDetails": {},
+  "editMessage": "تعديل الرسالة",
+  "@editMessage": {},
+  "editProfile": "تعديل الملف الشخصي",
+  "@editProfile": {},
+  "editSpace": "تعديل الفضاء",
+  "@editSpace": {},
+  "encryptionBackupEnabling": "تمكين النسخ الاحتياطي",
+  "@encryptionBackupEnabling": {},
+  "encryptionBackupResetting": "إعادة ضبط النسخ الاحتياطي",
+  "@encryptionBackupResetting": {},
+  "encryptionBackupResettingSuccess": "تمت إعادة الضبط بنجاح",
+  "@encryptionBackupResettingSuccess": {},
+  "encryptionBackupRecoverRecoveringSuccess": "نجاح عملية الاسترجاع",
+  "@encryptionBackupRecoverRecoveringSuccess": {},
+  "encryptionBackupRecoverRecoveringImportFailed": "فشلت عملية الاستيراد",
+  "@encryptionBackupRecoverRecoveringImportFailed": {},
+  "encryptionBackupKeyBackup": "مفتاح النسخ الاحتياطي",
+  "@encryptionBackupKeyBackup": {},
+  "error": "خطأ {error}",
+  "@error": {},
+  "eventName": "اسم الحدث",
+  "@eventName": {},
+  "loginAgain": "تسجيل الدخول مجدداً",
+  "@loginAgain": {},
+  "linkToChat": "ربط بالمحادثة",
+  "@linkToChat": {},
+  "loadingFailed": "فشل التحميل: {error}",
+  "@loadingFailed": {},
+  "inviteCode": "رمز الدعوة",
+  "@inviteCode": {},
+  "joinRoom": "انضم إلى المحادثة",
+  "@joinRoom": {},
+  "kickProgress": "إزالة المستخدم",
+  "@kickProgress": {},
+  "kickSuccess": "تمت إزالة المستخدم",
+  "@kickSuccess": {},
+  "kickUser": "حذف مستخدم",
+  "@kickUser": {},
+  "leaveRoom": "مغادرة المحادثة",
+  "@leaveRoom": {},
+  "leaveSpace": "ترك الفضاء",
+  "@leaveSpace": {},
+  "leavingSpace": "مغادرة الفضاء",
+  "@leavingSpace": {},
+  "leavingRoom": "مغادرة المحادثة",
+  "@leavingRoom": {},
+  "logIn": "تسجيل الدخول",
+  "@logIn": {},
+  "markedAsDone": "تم وضع علامة تم إنجازه",
+  "@markedAsDone": {},
+  "memberTitleData": "بيانات عنوان العضو",
+  "@memberTitleData": {},
+  "noChatsFound": "لم يتم العثور على أي محادثات",
+  "@noChatsFound": {},
+  "noConnectedSpaces": "لا توجد فضاءات متصلة",
+  "@noConnectedSpaces": {},
+  "noDisplayName": "لا يوجد اسم عرض",
+  "@noDisplayName": {},
+  "noDueDate": "لا يوجد تاريخ محدد",
+  "@noDueDate": {},
+  "noParticipantsGoing": "لا يوجد مشاركين راحلين",
+  "@noParticipantsGoing": {},
+  "noSpacesFound": "لم يتم العثور على أي فضاءت",
+  "@noSpacesFound": {},
+  "moreRooms": "+{count} غرف إضافية",
+  "@moreRooms": {},
+  "logSettings": "إعدادات التسجيل",
+  "@logSettings": {},
+  "newUpdate": "تحديث جديد",
+  "@newUpdate": {},
+  "noOverwrite": "عدم الكتابة فوق",
+  "@noOverwrite": {},
+  "pleaseSelectSpace": "الرجاء اختيار فضاء",
+  "@pleaseSelectSpace": {},
+  "pushTargetDeleted": "تم حذف الهدف المدفوع",
+  "@pushTargetDeleted": {},
+  "rageShakeAppName": "اسم التطبيق Rageshake",
+  "@rageShakeAppName": {},
+  "notGoing": "عدم المغادرة",
+  "@notGoing": {},
+  "parentSpace": "الفضاء الأم",
+  "@parentSpace": {},
+  "parentSpaces": "الفضاءات الأم",
+  "@parentSpaces": {},
+  "passwordResetTitle": "إعادة ضبط كلمة المرور",
+  "@passwordResetTitle": {},
+  "pinName": "دبس الاسم",
+  "@pinName": {},
+  "playbackSpeed": "سرعة إعادة التشغيل",
+  "@playbackSpeed": {},
+  "pleaseWait": "الرجاء الانتظار…",
+  "@pleaseWait": {},
+  "privacyPolicy": "اتفاقية الخصوصية",
+  "@privacyPolicy": {},
+  "quickSelect": "اختيار سريع:",
+  "@quickSelect": {},
+  "redeemingFailed": "فشل الاسترداد: {error}",
+  "@redeemingFailed": {},
+  "replyTo": "الردّ على {name}",
+  "@replyTo": {},
+  "reportThisEvent": "الإبلاغ عن هذا الحدث",
+  "@reportThisEvent": {},
+  "reportThisPost": "الإبلاغ عن هذا المنشور",
+  "@reportThisPost": {},
+  "reportSendingFailed": "فشل إرسال التقرير",
+  "@reportSendingFailed": {},
+  "requestToJoin": "طلب الانضمام",
+  "@requestToJoin": {},
+  "searchingFailed": "فشل البحث {error}",
+  "@searchingFailed": {},
+  "seeOpenTasks": "انظر المهام المفتوحة",
+  "@seeOpenTasks": {},
+  "selectParentSpace": "اختر الفضاء الأم",
+  "@selectParentSpace": {},
+  "reasonHint": "سبب اختياري",
+  "@reasonHint": {},
+  "removePin": "إزالة الدبوس",
+  "@removePin": {},
+  "reportPin": "الإبلاغ عن الدبوس",
+  "@reportPin": {},
+  "searchChats": "بحث عن المحادثات",
+  "@searchChats": {},
+  "searchSpace": "البحث عن فضاء",
+  "@searchSpace": {},
+  "searchSpaces": "البحث عن الفضاءات",
+  "@searchSpaces": {},
+  "selectDue": "اختر تاريخ الاستحقاق",
+  "@selectDue": {},
+  "sendingAttachment": "إرسال المرفق",
+  "@sendingAttachment": {},
+  "sendingReport": "إرسال التقرير",
+  "@sendingReport": {},
+  "sentAnImage": "تم إرسال صورة.",
+  "@sentAnImage": {},
+  "sessionTokenName": "اسم توكن (Token) الدورة",
+  "@sessionTokenName": {},
+  "setDebugLevel": "ضبط مستوى التصحيح",
+  "@setDebugLevel": {},
+  "setHttpProxy": "ضبط بروكسي HTTP",
+  "@setHttpProxy": {},
+  "securityAndPrivacy": "الأمن والخصوصية",
+  "@securityAndPrivacy": {},
+  "spaceNotificationOverwrite": "استبدال إشعار الفضاء",
+  "@spaceNotificationOverwrite": {},
+  "spacesAndChats": "الفضاءات و المحادثات",
+  "@spacesAndChats": {},
+  "superInvitedBy": "{user} يدعوك",
+  "@superInvitedBy": {},
+  "taskListName": "اسم قائمة المهام",
+  "@taskListName": {},
+  "termsOfService": "بنود الخدمة",
+  "@termsOfService": {},
+  "createNewPin": "إنشاء دبوس جديد",
+  "@createNewPin": {},
+  "suggestedRoomsTitle": "مقترح للانضمام",
+  "@suggestedRoomsTitle": {},
+  "addSuggested": "تم تحديده كمقترح",
+  "@addSuggested": {},
+  "sendingEmail": "إرسال بريد إلكتروني",
+  "@sendingEmail": {},
+  "shareIcal": "مشاركة iCal",
+  "@shareIcal": {},
+  "signUp": "التسجيل",
+  "@signUp": {},
+  "slidePosting": "نشر الشرائح",
+  "@slidePosting": {},
+  "spaceName": "اسم الفضاء",
+  "@spaceName": {},
+  "spaceNotifications": "إشعارات الفضاء",
+  "@spaceNotifications": {},
+  "startDM": "ابدأ دي ام DM",
+  "@startDM": {},
+  "submittingComment": "إرسال التعليق",
+  "@submittingComment": {},
+  "superInvitations": "دعوات مميزة",
+  "@superInvitations": {},
+  "superInvites": "رموز الدعوة",
+  "@superInvites": {},
+  "createComment": "خلق تعليق",
+  "@createComment": {},
+  "theSelectedRooms": "المحادثات المختارة",
+  "@theSelectedRooms": {},
+  "tryToJoin": "حاول الانضمام",
+  "@tryToJoin": {},
+  "createNewSpace": "إنشاء فضاء جديد",
+  "@createNewSpace": {},
+  "thirdParty": "طرف ثالث",
+  "@thirdParty": {},
+  "typeName": "اكتب الاسم",
+  "@typeName": {},
+  "unblockingUser": "إلغاء حظر المستخدم",
+  "@unblockingUser": {},
+  "unblockTitle": "إلغاء حظر {userId}",
+  "@unblockTitle": {},
+  "unblockUser": "إلغاء حظر مستخدم",
+  "@unblockUser": {},
+  "unreadMarkerFeatureTitle": "العلامات غير المقروءة",
+  "@unreadMarkerFeatureTitle": {},
+  "unknownRoom": "محادثة غير معروفة",
+  "@unknownRoom": {},
+  "verificationSasDoNotMatch": "لا تتطابق",
+  "@verificationSasDoNotMatch": {},
+  "verifyThisSession": "تحقق من هذه الدورة",
+  "@verifyThisSession": {},
+  "yesPleaseUpdate": "نعم، الرجاء التحديث",
+  "@yesPleaseUpdate": {},
+  "yourActiveDevices": "أجهزتك النشطة",
+  "@yourActiveDevices": {},
+  "addTextSlide": "أضف شريحة نصية",
+  "@addTextSlide": {},
+  "addVideoSlide": "أضف شريحة فيديو",
+  "@addVideoSlide": {},
+  "verificationSasMatch": "تتطابق",
+  "@verificationSasMatch": {},
+  "verificationScanEmojiTitle": "لا يمكن المسح الضوئي",
+  "@verificationScanEmojiTitle": {},
+  "welcomeBack": "أهلاً بعودتك",
+  "@welcomeBack": {},
+  "welcomeTo": "مرحباً بك في ",
+  "@welcomeTo": {},
+  "yourPassword": "كلمة المرور الخاصة بك",
+  "@yourPassword": {},
+  "adding": "إضافة {email}",
+  "@adding": {},
+  "acterApp": "تطبيق Acter",
+  "@acterApp": {},
+  "creatingPin": "إنشاء دبوس…",
+  "@creatingPin": {},
+  "dueTomorrow": "الموعد المحدد غداً",
+  "@dueTomorrow": {},
+  "endDate": "تاريخ الانتهاء",
+  "@endDate": {},
+  "endTime": "نهاية الوقت",
+  "@endTime": {},
+  "emailAddresses": "عناوين البريد الإلكتروني",
+  "@emailAddresses": {},
+  "eventCreate": "إنشاء حدث",
+  "@eventCreate": {},
+  "eventEdit": "تعديل حدث",
+  "@eventEdit": {},
+  "eventRemove": "إزالة حدث",
+  "@eventRemove": {},
+  "eventReport": "إبلاغ عن حدث",
+  "@eventReport": {},
+  "eventShare": "مشاركة الفعالية",
+  "@eventShare": {},
+  "loadingRsvpStatus": "جاري تحميل حالة rsvp",
+  "@loadingRsvpStatus": {},
+  "loadingFirstSync": "جاري تحميل المزامنة الأولى",
+  "@loadingFirstSync": {},
+  "pinCreatedSuccessfully": "تم إنشاء الدبوس بنجاح",
+  "@pinCreatedSuccessfully": {},
+  "encryptedDMChat": "محادثة دي ام DM المشفرة",
+  "@encryptedDMChat": {},
+  "loadingPin": "جارٍ تحميل الدبوس",
+  "@loadingPin": {},
+  "loadingRoom": "جارٍ تحميل المحادثة",
+  "@loadingRoom": {},
+  "loadingTargets": "جارٍ تحميل الأهداف",
+  "@loadingTargets": {},
+  "loadingImage": "جارٍ تحميل الصورة",
+  "@loadingImage": {},
+  "encryptedChatMessageInfoTitle": "رسالة مقفلة",
+  "@encryptedChatMessageInfoTitle": {},
+  "chatMessageDeleted": "تم حذف الرسالة",
+  "@chatMessageDeleted": {},
+  "chatJoinedDisplayName": "{name} انضم",
+  "@chatJoinedDisplayName": {},
+  "chatJoinedUserId": "{userId} انضم",
+  "@chatJoinedUserId": {},
+  "chatYouJoined": "انضممت",
+  "@chatYouJoined": {},
+  "chatYouInvited": "لقد قمت بدعوة",
+  "@chatYouInvited": {},
+  "chatInvitedDisplayName": "{name} دعا",
+  "@chatInvitedDisplayName": {},
+  "introPageDescriptionPre": "Acter أكثر من مجرد تطبيق.\nإنها",
+  "@introPageDescriptionPre": {},
+  "changedPushNotificationSettingsSuccessfully": "تم تغيير إعدادات الإشعارات المدفوعة بنجاح",
+  "@changedPushNotificationSettingsSuccessfully": {},
+  "seeAllMyEvents": "شاهد {count} أحداث الخاصة بي",
+  "@seeAllMyEvents": {},
+  "chatInvitationAcceptedDisplayName": "{name} قبل الدعوة",
+  "@chatInvitationAcceptedDisplayName": {},
+  "chatInvitationAcceptedUserId": "{userId} قبل الدعوة",
+  "@chatInvitationAcceptedUserId": {},
+  "removeThisPin": "أزل هذا الدبوس",
+  "@removeThisPin": {},
+  "removeThisPost": "أزل هذا المنشور",
+  "@removeThisPost": {},
+  "reportThisPin": "أبلغ عن هذا الدبوس",
+  "@reportThisPin": {},
+  "resettingPasswordFailed": "إعادة الضبط فشلت: {error}",
+  "@resettingPasswordFailed": {},
+  "resettingPasswordSuccessful": "تمت إعادة تعيين كلمة المرور بنجاح.",
+  "@resettingPasswordSuccessful": {},
+  "startDateRequired": "تاريخ البدء ضروري!",
+  "@startDateRequired": {},
+  "startTimeRequired": "وقت البدء ضروري!",
+  "@startTimeRequired": {},
+  "endTimeRequired": "وقت النهاية ضروري!",
+  "@endTimeRequired": {},
+  "selectCustomDate": "اختر تاريخاً معيناً",
+  "@selectCustomDate": {},
+  "joinExistingSpace": "انضم إلى الفضاء الموجود",
+  "@joinExistingSpace": {},
+  "dmChat": "محادثة دي ام DM",
+  "@dmChat": {},
+  "removingContent": "إزالة محتوى",
+  "@removingContent": {},
+  "removingAttachment": "إزالة المرفق",
+  "@removingAttachment": {},
+  "reportThis": "الإبلاغ عن هذا",
+  "@reportThis": {},
+  "sharedSuccessfully": "تمت المشاركة بنجاح",
+  "@sharedSuccessfully": {},
+  "searchUser": "البحث عن مستخدم",
+  "@searchUser": {},
+  "bugReportTitle": "أبلغ عن مشكلة",
+  "@bugReportTitle": {},
+  "emptyDescription": "الرجاء إدخال الوصف",
+  "@emptyDescription": {},
+  "includeLog": "قم بإدراج السجلات الحالية",
+  "@includeLog": {},
+  "nukeLocalData": "نوك للبيانات المحلية",
+  "@nukeLocalData": {},
+  "sharingRoom": "مشاركة هذه المحادثة…",
+  "@sharingRoom": {},
+  "commentEmptyStateTitle": "لم يتم العثور على أي تعليقات.",
+  "@commentEmptyStateTitle": {},
+  "acterUsername": "اسم المستخدم Acter الخاص بك",
+  "@acterUsername": {},
+  "copyToClip": "نسخ إلى الحافظة",
+  "@copyToClip": {},
+  "avatarAddTitle": "إضافة صورة رمزية للمستخدم",
+  "@avatarAddTitle": {},
+  "inviteSpaceMembersTitle": "دعوة أعضاء الفضاء",
+  "@inviteSpaceMembersTitle": {},
+  "inviteIndividualUsersTitle": "دعوة المستخدمين الأفراد",
+  "@inviteIndividualUsersTitle": {},
+  "generateInviteCode": "إنشاء رمز الدعوة",
+  "@generateInviteCode": {},
+  "noUserFoundTitle": "لم يتم العثور على مستخدمين",
+  "@noUserFoundTitle": {},
+  "membersInvited": "{count} أعضاء تمت دعوتهم",
+  "@membersInvited": {},
+  "visibilityAndAccessibility": "وضوح الرؤية وسهولة الوصول",
+  "@visibilityAndAccessibility": {},
+  "spaceWithAccess": "فضاء مع إمكانية الدخول",
+  "@spaceWithAccess": {},
+  "changePasswordDescription": "تغيير كلمة المرور الخاصة بك",
+  "@changePasswordDescription": {},
+  "passwordChangedSuccessfully": "تم تغيير كلمة المرور بنجاح",
+  "@passwordChangedSuccessfully": {},
+  "addMoreDetails": "أضف المزيد من التفاصيل",
+  "@addMoreDetails": {},
+  "changePassword": "تغيير كلمة المرور",
+  "@changePassword": {},
+  "oldPassword": "كلمة المرور القديمة",
+  "@oldPassword": {},
+  "noEventAvailableDescription": "أنشئ فعالية جديدة واجلب مجتمعك معًا.",
+  "@noEventAvailableDescription": {},
+  "failedToUploadAvatar": "فشل تحميل الصورة الرمزية: {error}",
+  "@failedToUploadAvatar": {},
+  "noTasksListAvailableYet": "لا توجد قائمة مهام متاحة بعد",
+  "@noTasksListAvailableYet": {},
+  "noMatchingEventsFound": "لم يتم العثور على أحداث مماثلة",
+  "@noMatchingEventsFound": {},
+  "deleteTaskList": "حذف قائمة المهام",
+  "@deleteTaskList": {},
+  "deleteTaskItem": "حذف بند المهام",
+  "@deleteTaskItem": {},
+  "reportTaskList": "إبلاغ عن قائمة المهام",
+  "@reportTaskList": {},
+  "noEventsFound": "لم يتم العثور على أي فعاليات",
+  "@noEventsFound": {},
+  "myUpcomingEvents": "فعالياتي القادمة",
+  "@myUpcomingEvents": {},
+  "from": "من",
+  "@from": {},
+  "gallery": "معرض الصور",
+  "@gallery": {},
+  "general": "عام",
+  "@general": {},
+  "notifications": "الإشعارات",
+  "@notifications": {},
+  "polls": "الاستطلاعات",
+  "@polls": {},
+  "retry": "أعد المحاولة",
+  "@retry": {},
+  "roomId": "معرف المحادثة",
+  "@roomId": {},
+  "rsvp": "RSVP",
+  "@rsvp": {},
+  "space": "فضاء",
+  "@space": {},
+  "going": "الانتقال",
+  "@going": {},
+  "image": "صورة",
+  "@image": {},
+  "info": "معلومات",
+  "@info": {},
+  "invited": "دعا",
+  "@invited": {},
+  "labs": "المختبرات",
+  "@labs": {},
+  "moderator": "المشرف",
+  "@moderator": {},
+  "more": "المزيد",
+  "@more": {},
+  "muted": "مكتوم",
+  "@muted": {},
+  "name": "الاسم",
+  "@name": {},
+  "ok": "موافق",
+  "@ok": {},
+  "postpone": "تأجيل",
+  "@postpone": {},
+  "sasVerified": "تم التحقق!",
+  "@sasVerified": {},
+  "save": "حفظ",
+  "@save": {},
+  "search": "بحث",
+  "@search": {},
+  "title": "العنوان",
+  "@title": {},
+  "to": "إلى",
+  "@to": {},
+  "today": "اليوم",
+  "@today": {},
+  "token": "توكن (token)",
+  "@token": {},
+  "tomorrow": "غداً",
+  "@tomorrow": {},
+  "username": "اسم المستخدم",
+  "@username": {},
+  "selectPicture": "اختر صورة",
+  "@selectPicture": {},
+  "selectVideo": "اختر فيديو",
+  "@selectVideo": {},
+  "selectDate": "اختر تاريخاً",
+  "@selectDate": {},
+  "selectTime": "اختر توقيت",
+  "@selectTime": {},
+  "sendDM": "أرسل دي ام (DM)",
+  "@sendDM": {},
+  "showMore": "عرض المزيد",
+  "@showMore": {},
+  "showLess": "عرض الأقل",
+  "@showLess": {},
+  "recommendedSpace": "الفضاء المُوصى به",
+  "@recommendedSpace": {},
+  "joinSpace": "الانضمام لفضاء",
+  "@joinSpace": {},
+  "invitingLoading": "دعوة {userId}",
+  "@invitingLoading": {},
+  "invitations": "الدعوات",
+  "@invitations": {},
+  "invite": "ادعُ",
+  "@invite": {},
+  "updateName": "تحديث الاسم",
+  "@updateName": {},
+  "updateDescription": "تحديث الوصف",
+  "@updateDescription": {},
+  "editName": "تعديل الاسم",
+  "@editName": {},
+  "editDescription": "تعديل الوصف",
+  "@editDescription": {},
+  "eventParticipants": "المشاركون في الفعالية",
+  "@eventParticipants": {},
+  "upcomingEvents": "الفعاليات المقبلة",
+  "@upcomingEvents": {},
+  "closeSpace": "إغلاق الفضاء",
+  "@closeSpace": {},
+  "closeChat": "إغلاق المحادثة",
+  "@closeChat": {},
+  "closingRoom": "جاري الغلق",
+  "@closingRoom": {},
+  "closingRoomDone": "تم الغلق بنجاح.",
+  "@closingRoomDone": {},
+  "defaultChatName": "{name} المحادثة",
+  "@defaultChatName": {},
+  "custom": "خصِّص",
+  "@custom": {},
+  "deactivate": "إلغاء التفعيل",
+  "@deactivate": {},
+  "decline": "رفض",
+  "@decline": {},
+  "delete": "حذف",
+  "@delete": {},
+  "denied": "تم النفي",
+  "@denied": {},
+  "description": "الوصف",
+  "@description": {},
+  "dms": "دي ام (DMs)",
+  "@dms": {},
+  "edit": "تعديل",
+  "@edit": {},
+  "edited": "تم تعديلها",
+  "@edited": {},
+  "encrypted": "مشفرة",
+  "@encrypted": {},
+  "encryptionBackupRecoverAction": "استرجاع",
+  "@encryptionBackupRecoverAction": {},
+  "encryptionBackupRecoverRecovering": "استرداد",
+  "@encryptionBackupRecoverRecovering": {},
+  "events": "الفعاليات",
+  "@events": {},
+  "failed": "فشلت",
+  "@failed": {},
+  "file": "ملف",
+  "@file": {},
+  "join": "انضم",
+  "@join": {},
+  "joined": "إنضم",
+  "@joined": {},
+  "language": "اللغة",
+  "@language": {},
+  "leave": "غادر",
+  "@leave": {},
+  "licenses": "التراخيص",
+  "@licenses": {},
+  "link": "الرابط",
+  "@link": {},
+  "links": "الروابط",
+  "@links": {},
+  "loading": "جارٍ التحميل",
+  "@loading": {},
+  "location": "الموقع",
+  "@location": {},
+  "logOut": "تسجيل الخروج",
+  "@logOut": {},
+  "manage": "إدارة",
+  "@manage": {},
+  "maybe": "ربما",
+  "@maybe": {},
+  "member": "عضو",
+  "@member": {},
+  "members": "الأعضاء",
+  "@members": {},
+  "message": "رسالة",
+  "@message": {},
+  "next": "التالي",
+  "@next": {},
+  "no": "لا",
+  "@no": {},
+  "noChatsStillSyncing": "جاري المزامنة...",
+  "@noChatsStillSyncing": {},
+  "past": "السابق",
+  "@past": {},
+  "pending": "قيد الانتظار",
+  "@pending": {},
+  "pins": "الدبابيس",
+  "@pins": {},
+  "play": "شغل",
+  "@play": {},
+  "preview": "لمحة عامة",
+  "@preview": {},
+  "private": "خاص",
+  "@private": {},
+  "profile": "ملف التعريف",
+  "@profile": {},
+  "pushKey": "مفتاح الضغط",
+  "@pushKey": {},
+  "notes": "الملاحظات",
+  "@notes": {},
+  "okay": "موافق",
+  "@okay": {},
+  "on": "على",
+  "@on": {},
+  "optional": "اختياري",
+  "@optional": {},
+  "or": " أو ",
+  "@or": {},
+  "overview": "لمحة عامة",
+  "@overview": {},
+  "parents": "الأم",
+  "@parents": {},
+  "password": "كلمة المرور",
+  "@password": {},
+  "reason": "السبب",
+  "@reason": {},
+  "reasonLabel": "السبب",
+  "@reasonLabel": {},
+  "redeem": "استرداد",
+  "@redeem": {},
+  "register": "التسجيل",
+  "@register": {},
+  "regular": "منتظم",
+  "@regular": {},
+  "remove": "إزالة",
+  "@remove": {},
+  "reply": "ردّ",
+  "@reply": {},
+  "report": "تقرير",
+  "@report": {},
+  "reset": "إعادة ضبط",
+  "@reset": {},
+  "select": "اختر",
+  "@select": {},
+  "send": "أرسل",
+  "@send": {},
+  "selectAll": "اختيار الكل",
+  "@selectAll": {},
+  "unselectAll": "إلغاء اختيار الكل",
+  "@unselectAll": {},
+  "server": "السيرفر",
+  "@server": {},
+  "sessions": "الدورات",
+  "@sessions": {},
+  "settings": "الإعدادات",
+  "@settings": {},
+  "share": "شارك",
+  "@share": {},
+  "skip": "تجاوز",
+  "@skip": {},
+  "spaces": "الفضاءات",
+  "@spaces": {},
+  "state": "الحالة",
+  "@state": {},
+  "submit": "إرسال",
+  "@submit": {},
+  "subspace": "فضاء فرعي",
+  "@subspace": {},
+  "subspaces": "الفضاءات الفرعية",
+  "@subspaces": {},
+  "tasks": "المهام",
+  "@tasks": {},
+  "suggested": "مقترحة",
+  "@suggested": {},
+  "joiningSuggested": "اقتراح الانضمام",
+  "@joiningSuggested": {},
+  "removeSuggested": "حذف الاقتراح",
+  "@removeSuggested": {},
+  "topic": "الموضوع",
+  "@topic": {},
+  "unblock": "إلغاء الحظر",
+  "@unblock": {},
+  "undefined": "غير محدد",
+  "@undefined": {},
+  "unknown": "مجهول",
+  "@unknown": {},
+  "unlink": "فك الربط",
+  "@unlink": {},
+  "unmute": "إلغاء الكتم",
+  "@unmute": {},
+  "unset": "إلغاء الضبط",
+  "@unset": {},
+  "unverified": "لم يتم التحقق",
+  "@unverified": {},
+  "upcoming": "القادم",
+  "@upcoming": {},
+  "updates": "التحديثات",
+  "@updates": {},
+  "verified": "تم التحقق",
+  "@verified": {},
+  "version": "الإصدار",
+  "@version": {},
+  "via": "عن طريق",
+  "@via": {},
+  "video": "فيديو",
+  "@video": {},
+  "yes": "نعم",
+  "@yes": {},
+  "acter": "Acter",
+  "@acter": {},
+  "selectChat": "اختر المحادثة",
+  "@selectChat": {},
+  "recommendedSpaces": "الفضاءات الموصى بها",
+  "@recommendedSpaces": {},
+  "mySpaces": "فضاءاتي",
+  "@mySpaces": {},
+  "startDate": "تاريخ البدء",
+  "@startDate": {},
+  "startTime": "موعد البدء",
+  "@startTime": {},
+  "moreSubspaces": "المزيد من الفضاءات الفرعية",
+  "@moreSubspaces": {},
+  "myTasks": "مهامي",
+  "@myTasks": {},
+  "unlinkRoom": "فك ربط المحادثة",
+  "@unlinkRoom": {},
+  "logOutConformationDescription1": "انتبه: ",
+  "@logOutConformationDescription1": {},
+  "membersCount": "{count} أعضاء",
+  "@membersCount": {},
+  "retrying": "تتم إعادة المحاولة …",
+  "@retrying": {},
+  "includeScreenshot": "إدراج لقطة شاشة",
+  "@includeScreenshot": {},
+  "jumpTo": "الانتقال إلى",
+  "@jumpTo": {},
+  "taskList": "قائمة المهام",
+  "@taskList": {},
+  "fatalError": "خطأ مهلك",
+  "@fatalError": {},
+  "reportBug": "الإبلاغ عن خلل",
+  "@reportBug": {},
+  "showStacktrace": "عرض تعقب التكديس (Stacktrace)",
+  "@showStacktrace": {},
+  "hideStacktrace": "إخفاء تتبع المكدس (Stacktrace)",
+  "@hideStacktrace": {},
+  "review": "مراجعة",
+  "@review": {},
+  "activities": "النشاطات",
+  "@activities": {},
+  "joining": "الانضمام",
+  "@joining": {},
+  "rejecting": "رفض",
+  "@rejecting": {},
+  "rejected": "رفض",
+  "@rejected": {},
+  "update": "تحديث",
+  "@update": {},
+  "event": "الفعالية",
+  "@event": {},
+  "pin": "دبوس",
+  "@pin": {},
+  "poll": "استبيان",
+  "@poll": {},
+  "discussion": "النقاش",
+  "@discussion": {},
+  "changingSettings": "تغيير الإعدادات…",
+  "@changingSettings": {},
+  "assigningSelf": "تعيين ذاتي…",
+  "@assigningSelf": {},
+  "unassigningSelf": "إلغاء التعيين الذاتي…",
+  "@unassigningSelf": {},
+  "jumpToTabTutorialTitle": "الانتقال إلى",
+  "@jumpToTabTutorialTitle": {},
+  "spaceOverviewTutorialTitle": "تفاصيل الفضاء",
+  "@spaceOverviewTutorialTitle": {},
+  "homeTabTutorialTitle": "لوحة المتابعة",
+  "@homeTabTutorialTitle": {},
+  "updatesTabTutorialTitle": "التحديثات",
+  "@updatesTabTutorialTitle": {},
+  "chatsTabTutorialTitle": "المحادثات",
+  "@chatsTabTutorialTitle": {},
+  "activityTabTutorialTitle": "النشاط",
+  "@activityTabTutorialTitle": {},
+  "previous": "السابقة",
+  "@previous": {},
+  "finish": "إنهاء",
+  "@finish": {},
+  "wizzardContinue": "أكمل",
+  "@wizzardContinue": {},
+  "emailOptional": "البريد الإلكتروني (اختياري)",
+  "@emailOptional": {},
+  "sendEmail": "إرسال رسالة إلكترونية",
+  "@sendEmail": {},
+  "pendingInvites": "الدعوات المعلقة",
+  "@pendingInvites": {},
+  "appUnavailable": "التطبيق غير متاح",
+  "@appUnavailable": {},
+  "editLink": "تعديل الرابط",
+  "@editLink": {},
+  "done": "تم",
+  "@done": {},
+  "otherSpaces": "فضاءات أخرى",
+  "@otherSpaces": {},
+  "selectVisibility": "حدد قابلية الظهور",
+  "@selectVisibility": {},
+  "confirmPassword": "تأكيد كلمة المرور",
+  "@confirmPassword": {},
+  "taskName": "اسم المهمة",
+  "@taskName": {},
+  "addingTask": "إضافة مهمة",
+  "@addingTask": {},
+  "countTasksCompleted": "{count} أنجزت",
+  "@countTasksCompleted": {},
+  "showCompleted": "عرض المنجزة",
+  "@showCompleted": {},
+  "hideCompleted": "إخفاء المنجزة",
+  "@hideCompleted": {},
+  "noAssignment": "لا يوجد تعيينات",
+  "@noAssignment": {},
+  "assignMyself": "تكليف نفسي",
+  "@assignMyself": {},
+  "removeMyself": "إزالة نفسي",
+  "@removeMyself": {},
+  "updateTask": "تحديث المهمة",
+  "@updateTask": {},
+  "updatingTask": "تحديث المهمة",
+  "@updatingTask": {},
+  "editTitle": "تعديل العنوان",
+  "@editTitle": {},
+  "updatingDescription": "تحديث الوصف",
+  "@updatingDescription": {},
+  "visibilityTitle": "مستوى الرؤية",
+  "@visibilityTitle": {},
+  "public": "عمومي",
+  "@public": {},
+  "limited": "محدودة",
+  "@limited": {},
+  "assignment": "التعيين",
+  "@assignment": {},
+  "revoke": "إلغاء",
+  "@revoke": {},
+  "updatingLinking": "تحديث الرابط",
+  "@updatingLinking": {},
+  "seeAll": "عرض الكل",
+  "@seeAll": {},
+  "addPin": "إضافة دبوس",
+  "@addPin": {},
+  "addEvent": "إضافة حدث",
+  "@addEvent": {},
+  "linkChat": "ربط المحادثة",
+  "@linkChat": {},
+  "linkSpace": "ربط الفضاء",
+  "@linkSpace": {},
+  "eventStarts": "البدء",
+  "@eventStarts": {},
+  "eventEnded": "انتهت",
+  "@eventEnded": {},
+  "live": "مباشر",
+  "@live": {},
+  "ongoing": "مستمر",
+  "@ongoing": {},
+  "myEvents": "الأحداث الخاصة بي",
+  "@myEvents": {},
+  "eventStarted": "بدأت",
+  "@eventStarted": {},
+  "happeningNow": "يحدث الآن",
+  "@happeningNow": {}
 }
diff --git a/app/lib/l10n/app_da.arb b/app/lib/l10n/app_da.arb
index bcc06e351450..3160ae61bd30 100644
--- a/app/lib/l10n/app_da.arb
+++ b/app/lib/l10n/app_da.arb
@@ -387,8 +387,6 @@
   "@error": {},
   "errorCreatingChat": "Fejl under oprettelse af chat: {error}",
   "@errorCreatingChat": {},
-  "errorLoading": "Fejl med loading {error}",
-  "@errorLoading": {},
   "errorSubmittingComment": "Fejl ved oprettelse af kommentar: {error}",
   "@errorSubmittingComment": {},
   "eventDescriptionsData": "Beskrivelse af begivenhed data",
@@ -401,8 +399,6 @@
   "@eventTitleData": {},
   "experimentalActerFeatures": "Eksperimentelle Acter funktioner",
   "@experimentalActerFeatures": {},
-  "failed": "Fejl",
-  "@failed": {},
   "file": "Fil",
   "@file": {},
   "forgotPassword": "Glemt kodeord?",
@@ -513,8 +509,6 @@
   "@encryptionBackupEnabledExplainer": {},
   "encryptionBackupRecoverExplainer": "Angiv din gendannelsesnøgle til at dekryptere krypteringssikkerhedskopien",
   "@encryptionBackupRecoverExplainer": {},
-  "failedToLoad": "Kunne ikke indlæse: {error}",
-  "@failedToLoad": {},
   "hintMessageUsername": "Unikt brugernavn til login og identifikation",
   "@hintMessageUsername": {},
   "deletionFailed": "Sletning mislykkedes: {error}",
diff --git a/app/lib/l10n/app_de.arb b/app/lib/l10n/app_de.arb
index 817c3e3bc280..f362edbb3c39 100644
--- a/app/lib/l10n/app_de.arb
+++ b/app/lib/l10n/app_de.arb
@@ -219,8 +219,6 @@
   "@failedToAdd": {},
   "failedToConfirmToken": "Kode-Bestätigung fehlgeschlagen: {error}",
   "@failedToConfirmToken": {},
-  "failedToLoad": "Laden fehlgeschlagen: {error}",
-  "@failedToLoad": {},
   "failedToLoadInviteCodes": "Invite-Codes laden fehlgeschlagen: {error}",
   "@failedToLoadInviteCodes": {},
   "failedToSubmitEmail": "Fehler beim Übermitteln der Email: {error}",
@@ -811,8 +809,6 @@
   "@someErrorOccurredLeavingRoom": {},
   "errorCreatingChat": "Chat erstellen fehlgeschlagen: {error}",
   "@errorCreatingChat": {},
-  "errorLoading": "Ladefehler: {error}",
-  "@errorLoading": {},
   "eventDescriptionsData": "Eventbeschreibung",
   "@eventDescriptionsData": {},
   "foundUsers": "User gefunden",
@@ -849,8 +845,6 @@
   "@noMembersFound": {},
   "on": "auf",
   "@on": {},
-  "failed": "fehlgeschlagen",
-  "@failed": {},
   "parentSpace": "Elternspace",
   "@parentSpace": {},
   "parentSpaceMustBeSelected": "Elternspace muss gewählt werden",
diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb
index c89e52f797eb..dd4c3513b7fd 100644
--- a/app/lib/l10n/app_en.arb
+++ b/app/lib/l10n/app_en.arb
@@ -40,10 +40,15 @@
   "alreadyConfirmed": "Already confirmed",
   "@alreadyConfirmed": {},
   "analyticsTitle": "Help us help you",
+  "@analyticsTitle": {},
   "analyticsDescription1": "By sharing crash analytics and error reports with us.",
+  "@analyticsDescription1": {},
   "analyticsDescription2": "These are of course anonymized and do not contain any private information",
+  "@analyticsDescription2": {},
   "sendCrashReportsTitle": "Send crash & error reports",
+  "@sendCrashReportsTitle": {},
   "sendCrashReportsInfo": "Share crash tracebacks via sentry with the Acter team automatically",
+  "@sendCrashReportsInfo": {},
   "and": "and",
   "@and": {},
   "anInviteCodeYouWantToRedeem": "An invite code you want to redeem",
@@ -179,16 +184,27 @@
   "closeSessionAndDeleteData": "Close this session, deleting local data",
   "@closeSessionAndDeleteData": {},
   "closeSpace": "Close Space",
+  "@closeSpace": {},
   "closeChat": "Close Chat",
+  "@closeChat": {},
   "closingRoomTitle": "Close this Room",
+  "@closingRoomTitle": {},
   "closingRoomTitleDescription": "When closing this room, we will :\n\n - Kick everyone with a lower permission level then yours from it\n - Remove it as a child from the parent spaces (where you have the permissions to do so),\n - Set the invite rule to 'private'\n - You will leave the room.\n\nThis can not be undone. Are you sure you want to close this?",
+  "@closingRoomTitleDescription": {},
   "closingRoom": "Closing ...",
+  "@closingRoom": {},
   "closingRoomRemovingMembers": "Closing in process. Kicking member {kicked} / {total}",
+  "@closingRoomRemovingMembers": {},
   "closingRoomMatrixMsg": "The room was closed",
+  "@closingRoomMatrixMsg": {},
   "closingRoomRemovingFromParents": "Closing in process. Removing room from parent {currentParent} / {totalParents}",
+  "@closingRoomRemovingFromParents": {},
   "closingRoomDoneBut": "Closed and you've left. But was unable to remove {skipped} other Users and remove it as child from {skippedParents} Spaces due to lack of permission. Others might still have access to it.",
+  "@closingRoomDoneBut": {},
   "closingRoomDone": "Closed successfully.",
+  "@closingRoomDone": {},
   "closingRoomFailed": "Closing failed: {error}",
+  "@closingRoomFailed": {},
   "coBudget": "CoBudget",
   "@coBudget": {},
   "code": "Code",
@@ -244,6 +260,7 @@
   "createDefaultChat": "Create default chat room, too",
   "@createDefaultChat": {},
   "defaultChatName": "{name} chat",
+  "@defaultChatName": {},
   "createDMWhenRedeeming": "Create DM when redeeming",
   "@createDMWhenRedeeming": {},
   "createEventAndBringYourCommunity": "Create new event and bring your community together",
@@ -450,8 +467,6 @@
   "@errorCreatingCalendarEvent": {},
   "errorCreatingChat": "Error creating chat: {error}",
   "@errorCreatingChat": {},
-  "errorLoading": "Error loading {error}",
-  "@errorLoading": {},
   "errorSubmittingComment": "Error submitting comment: {error}",
   "@errorSubmittingComment": {},
   "errorUpdatingEvent": "Error updating event: {error}",
@@ -466,12 +481,8 @@
   "@eventTitleData": {},
   "experimentalActerFeatures": "Experimental Acter features",
   "@experimentalActerFeatures": {},
-  "failed": "failed",
-  "@failed": {},
   "failedToAcceptInvite": "Failed to accept invite: {error}",
   "@failedToAcceptInvite": {},
-  "failedToLoad": "Failed to load: {error}",
-  "@failedToLoad": {},
   "failedToRejectInvite": "Failed to reject invite: {error}",
   "@failedToRejectInvite": {},
   "file": "File",
@@ -956,6 +967,12 @@
   "@sasVerified": {},
   "save": "Save",
   "@save": {},
+  "saveFileAs": "Save file as",
+  "@saveFileAs" : {},
+  "openFile": "Open",
+  "@openFile" : {},
+  "shareFile": "Share",
+  "@shareFile" : {},
   "saveChanges": "Save Changes",
   "@saveChanges": {},
   "savingCode": "Saving code",
@@ -1092,7 +1109,7 @@
   "@addSuggested": {},
   "removeSuggested": "Remove suggestion",
   "@removeSuggested": {},
-  "superInvitations": "Super Invitations",
+  "superInvitations": "Invitation Codes",
   "@superInvitations": {},
   "superInvites": "Invitation Codes",
   "@superInvites": {},
@@ -1866,6 +1883,7 @@
   "avatarUploadFailed": "Failed to upload user avatar: {error}",
   "@avatarUploadFailed": {},
   "sendEmail": "Send email",
+  "@sendEmail": {},
   "inviteCopiedToClipboard": "Invite code copied to clipboard",
   "@inviteCopiedToClipboard": {},
   "updateName": "Updating name",
@@ -2043,23 +2061,41 @@
   "addEvent": "Add Event",
   "@addEvent": {},
   "linkChat": "Link Chat",
+  "@linkChat": {},
   "linkSpace": "Link Space",
+  "@linkSpace": {},
   "failedToUploadAvatar": "Failed to upload avatar: {error}",
+  "@failedToUploadAvatar": {},
   "noMatchingTasksListFound": "No matching tasks list found",
+  "@noMatchingTasksListFound": {},
   "noTasksListAvailableYet": "No tasks list available yet",
+  "@noTasksListAvailableYet": {},
   "noTasksListAvailableDescription": "Share and manage important task with your community such as any TO-DO list so everyone is updated.",
+  "@noTasksListAvailableDescription": {},
   "loadingMembersFailed": "Loading members failed: {error}",
+  "@loadingMembersFailed": {},
   "ongoing": "Ongoing",
+  "@ongoing": {},
   "noMatchingEventsFound": "No matching events found",
+  "@noMatchingEventsFound": {},
   "noEventsFound": "No events found",
+  "@noEventsFound": {},
   "noEventAvailableDescription": "Create new event and bring your community together.",
+  "@noEventAvailableDescription": {},
   "myEvents": "My Events",
+  "@myEvents": {},
   "eventStarted": "Started",
+  "@eventStarted": {},
   "eventStarts": "Starts",
+  "@eventStarts": {},
   "eventEnded": "Ended",
+  "@eventEnded": {},
   "happeningNow": "Happening Now",
+  "@happeningNow": {},
   "myUpcomingEvents": "My Upcoming Events",
+  "@myUpcomingEvents": {},
   "live": "Live",
+  "@live": {},
   "changeDate": "Change Date",
   "updatingDate": "Updating Date",
   "pleaseEnterALink": "Please enter a link",
diff --git a/app/lib/l10n/app_es.arb b/app/lib/l10n/app_es.arb
index 4ca8090d22d0..7a0dae888fac 100644
--- a/app/lib/l10n/app_es.arb
+++ b/app/lib/l10n/app_es.arb
@@ -455,8 +455,6 @@
   "@errorCreatingCalendarEvent": {},
   "errorCreatingChat": "Error al crear chat: {error}",
   "@errorCreatingChat": {},
-  "errorLoading": "Error al cargar {error}",
-  "@errorLoading": {},
   "errorUpdatingEvent": "Error al actualizar el evento: {error}",
   "@errorUpdatingEvent": {},
   "eventDescriptionsData": "Datos de las descripciones de los eventos",
@@ -467,12 +465,8 @@
   "@events": {},
   "experimentalActerFeatures": "Características de Acter Experimental",
   "@experimentalActerFeatures": {},
-  "failed": "fallido",
-  "@failed": {},
   "failedToAcceptInvite": "No se ha podido aceptar la invitación: {error}",
   "@failedToAcceptInvite": {},
-  "failedToLoad": "No se ha podido cargar: {error}",
-  "@failedToLoad": {},
   "failedToRejectInvite": "No se ha podido rechazar la invitación: {error}",
   "@failedToRejectInvite": {},
   "file": "Archivo",
diff --git a/app/lib/l10n/app_fr.arb b/app/lib/l10n/app_fr.arb
index f5b072513706..f05504636f20 100644
--- a/app/lib/l10n/app_fr.arb
+++ b/app/lib/l10n/app_fr.arb
@@ -931,8 +931,6 @@
   "@errorCreatingChat": {},
   "errorSubmittingComment": "Erreur lors de l'envoi du commentaire : {error}",
   "@errorSubmittingComment": {},
-  "failedToLoad": "Échec du chargement : {error}",
-  "@failedToLoad": {},
   "getInTouchWithOtherChangeMakers": "Entrez en contact avec d'autres acteurs du changement, organisateurs ou activistes et discutez directement avec eux.",
   "@getInTouchWithOtherChangeMakers": {},
   "formatMustBe": "Le format doit être @user:server.tld",
@@ -997,8 +995,6 @@
   "@encryptionBackupResetting": {},
   "encryptionBackupRecoverInputHint": "Clé de récupération",
   "@encryptionBackupRecoverInputHint": {},
-  "errorLoading": "Erreur de chargement {error}",
-  "@errorLoading": {},
   "eventDescriptionsData": "Données relatives à la description des événements",
   "@eventDescriptionsData": {},
   "eventTitleData": "Données sur le titre de l'événement",
@@ -1489,8 +1485,6 @@
   "@encryptionBackupRecoverRecovering": {},
   "events": "Evénements",
   "@events": {},
-  "failed": "échoué",
-  "@failed": {},
   "file": "Fichier",
   "@file": {},
   "from": "de",
diff --git a/app/lib/l10n/app_pl.arb b/app/lib/l10n/app_pl.arb
index 26b4a779d095..27c1f8e7a509 100644
--- a/app/lib/l10n/app_pl.arb
+++ b/app/lib/l10n/app_pl.arb
@@ -693,8 +693,6 @@
   "@errorCreatingCalendarEvent": {},
   "errorCreatingChat": "Błąd podczas tworzenia czatu: {error}",
   "@errorCreatingChat": {},
-  "errorLoading": "Błąd ładowania {error}",
-  "@errorLoading": {},
   "errorSubmittingComment": "Błąd przesyłania komentarza: {error}",
   "@errorSubmittingComment": {},
   "eventDescriptionsData": "Dane opisów zdarzeń",
@@ -707,10 +705,6 @@
   "@eventTitleData": {},
   "experimentalActerFeatures": "Funkcje Experimental Acter",
   "@experimentalActerFeatures": {},
-  "failed": "nieudany",
-  "@failed": {},
-  "failedToLoad": "Nie udało się załadować: {error}",
-  "@failedToLoad": {},
   "file": "Plik",
   "@file": {},
   "formatMustBe": "Format musi być następujący: @user:server.tld",
diff --git a/app/pubspec.lock b/app/pubspec.lock
index e5190791301c..b1635ba2287c 100644
--- a/app/pubspec.lock
+++ b/app/pubspec.lock
@@ -1509,6 +1509,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.0.0"
+  open_filex:
+    dependency: "direct main"
+    description:
+      name: open_filex
+      sha256: ba425ea49affd0a98a234aa9344b9ea5d4c4f7625a1377961eae9fe194c3d523
+      url: "https://pub.dev"
+    source: hosted
+    version: "4.5.0"
   package_config:
     dependency: transitive
     description:
@@ -1621,6 +1629,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "6.0.2"
+  phosphor_flutter:
+    dependency: "direct main"
+    description:
+      name: phosphor_flutter
+      sha256: "8a14f238f28a0b54842c5a4dc20676598dd4811fcba284ed828bd5a262c11fde"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.0"
   photo_view:
     dependency: transitive
     description:
diff --git a/app/pubspec.yaml b/app/pubspec.yaml
index f37edac3c80a..8a8bc3ab1dd2 100644
--- a/app/pubspec.yaml
+++ b/app/pubspec.yaml
@@ -132,6 +132,8 @@ dependencies:
 
   shake_detector:
     path: ../packages/shake_detector
+  open_filex: ^4.5.0
+  phosphor_flutter: ^2.1.0
 
 dev_dependencies:
   flutter_test:
diff --git a/native/acter/api.rsh b/native/acter/api.rsh
index 2a636dfbf920..6be8747987c6 100644
--- a/native/acter/api.rsh
+++ b/native/acter/api.rsh
@@ -234,6 +234,11 @@ object OptionRsvpStatus {
     fn status_str() -> Option<string>;
 }
 
+object OptionComposeDraft {
+    /// get compose draft object
+    fn draft() -> Option<ComposeDraft>;
+}
+
 object UserProfile {
     /// get user id
     fn user_id() -> UserId;
@@ -330,6 +335,21 @@ object MxcUri {
     fn to_string() -> string;
 }
 
+object ComposeDraft {
+    /// plain body text, always available
+    fn plain_text() -> string;
+
+    /// formatted text
+    fn html_text() -> Option<string>;
+
+    /// event id, only valid for edit and reply states
+    fn event_id() -> Option<string>;
+
+    /// compose message state type.
+    /// One of `new`, `edit`, `reply`.
+    fn draft_type() -> string;
+}
+
 object RoomId {
     fn to_string() -> string;
 }
@@ -1098,7 +1118,6 @@ object Room {
 
     /// leave this room
     fn leave() -> Future<Result<bool>>;
-
 }
 
 
@@ -1356,6 +1375,15 @@ object Convo {
     fn redact_content(event_id: string, reason: Option<string>) -> Future<Result<EventId>>;
 
     fn is_joined() -> bool;
+
+    /// compose message state of the room
+    fn msg_draft() -> Future<Result<OptionComposeDraft>>;
+
+    /// save composed message state of the room
+    fn save_msg_draft(text: string, html: Option<string>, draft_type: string, event_id: Option<string>) -> Future<Result<bool>>;
+
+    /// clear composed message state of the room
+    fn clear_msg_draft() -> Future<Result<bool>>;
 }
 
 
diff --git a/native/acter/src/api.rs b/native/acter/src/api.rs
index 0ad7c4781f01..99beb7c5402b 100644
--- a/native/acter/src/api.rs
+++ b/native/acter/src/api.rs
@@ -84,8 +84,8 @@ pub use comments::{Comment, CommentDraft, CommentsManager};
 pub use common::{
     duration_from_secs, new_calendar_event_ref_builder, new_colorize_builder, new_link_ref_builder,
     new_obj_ref_builder, new_task_list_ref_builder, new_task_ref_builder, new_thumb_size,
-    DeviceRecord, MediaSource, MsgContent, OptionBuffer, OptionRsvpStatus, OptionString,
-    ReactionRecord, ThumbnailInfo, ThumbnailSize,
+    ComposeDraft, DeviceRecord, MediaSource, MsgContent, OptionBuffer, OptionComposeDraft,
+    OptionRsvpStatus, OptionString, ReactionRecord, ThumbnailInfo, ThumbnailSize,
 };
 pub use convo::{
     new_convo_settings_builder, Convo, ConvoDiff, CreateConvoSettings, CreateConvoSettingsBuilder,
diff --git a/native/acter/src/api/common.rs b/native/acter/src/api/common.rs
index fd57265e556b..6ca916476586 100644
--- a/native/acter/src/api/common.rs
+++ b/native/acter/src/api/common.rs
@@ -5,10 +5,15 @@ use acter_core::events::{
 };
 use anyhow::{Context, Result};
 use core::time::Duration;
-use matrix_sdk::media::{MediaFormat, MediaThumbnailSettings, MediaThumbnailSize};
+use matrix_sdk::{
+    media::{MediaFormat, MediaThumbnailSettings, MediaThumbnailSize},
+    ComposerDraft, ComposerDraftType,
+};
 use ruma::UInt;
 use ruma_client_api::media::get_content_thumbnail;
-use ruma_common::{EventId, MilliSecondsSinceUnixEpoch, OwnedDeviceId, OwnedMxcUri, OwnedUserId};
+use ruma_common::{
+    EventId, MilliSecondsSinceUnixEpoch, OwnedDeviceId, OwnedEventId, OwnedMxcUri, OwnedUserId,
+};
 use ruma_events::room::{
     message::{
         AudioInfo, AudioMessageEventContent, EmoteMessageEventContent, FileInfo,
@@ -73,6 +78,20 @@ impl OptionRsvpStatus {
         self.status.as_ref().map(|x| x.to_string())
     }
 }
+#[derive(Clone)]
+pub struct OptionComposeDraft {
+    draft: Option<ComposeDraft>,
+}
+
+impl OptionComposeDraft {
+    pub(crate) fn new(draft: Option<ComposeDraft>) -> Self {
+        OptionComposeDraft { draft }
+    }
+
+    pub fn draft(&self) -> Option<ComposeDraft> {
+        self.draft.clone()
+    }
+}
 
 pub struct MediaSource {
     inner: SdkMediaSource,
@@ -468,6 +487,65 @@ impl MsgContent {
     }
 }
 
+#[derive(Clone)]
+pub struct ComposeDraft {
+    inner: ComposerDraft,
+}
+
+impl ComposeDraft {
+    pub fn new(
+        plain_text: String,
+        html_text: Option<String>,
+        msg_type: String,
+        event_id: Option<OwnedEventId>,
+    ) -> Self {
+        let m_type = msg_type.clone();
+        let draft_type = match (m_type.as_str(), event_id) {
+            ("new", None) => ComposerDraftType::NewMessage,
+            ("edit", Some(id)) => ComposerDraftType::Edit { event_id: id },
+            ("reply", Some(id)) => ComposerDraftType::Reply { event_id: id },
+            _ => ComposerDraftType::NewMessage,
+        };
+
+        ComposeDraft {
+            inner: ComposerDraft {
+                plain_text,
+                html_text,
+                draft_type,
+            },
+        }
+    }
+
+    pub fn inner(&self) -> ComposerDraft {
+        self.inner.clone()
+    }
+
+    pub fn plain_text(&self) -> String {
+        self.inner.plain_text.clone()
+    }
+
+    pub fn html_text(&self) -> Option<String> {
+        self.inner.html_text.clone()
+    }
+
+    // only valid for reply and edit drafts
+    pub fn event_id(&self) -> Option<String> {
+        match &(self.inner.draft_type) {
+            ComposerDraftType::Edit { event_id } => Some(event_id.to_string()),
+            ComposerDraftType::Reply { event_id } => Some(event_id.to_string()),
+            ComposerDraftType::NewMessage => None,
+        }
+    }
+
+    pub fn draft_type(&self) -> String {
+        match &(self.inner.draft_type) {
+            ComposerDraftType::NewMessage => "new".to_string(),
+            ComposerDraftType::Edit { event_id } => "edit".to_string(),
+            ComposerDraftType::Reply { event_id } => "reply".to_string(),
+        }
+    }
+}
+
 #[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct ReactionRecord {
     sender_id: OwnedUserId,
diff --git a/native/acter/src/api/convo.rs b/native/acter/src/api/convo.rs
index eff3e2410163..62717da52098 100644
--- a/native/acter/src/api/convo.rs
+++ b/native/acter/src/api/convo.rs
@@ -2,13 +2,13 @@ use acter_core::{statics::default_acter_convo_states, Error};
 use anyhow::{bail, Context, Result};
 use derive_builder::Builder;
 use futures::stream::{Stream, StreamExt};
-use matrix_sdk::{executor::JoinHandle, RoomMemberships};
+use matrix_sdk::{executor::JoinHandle, ComposerDraft, ComposerDraftType, RoomMemberships};
 use matrix_sdk_ui::{timeline::RoomExt, Timeline};
 use ruma::assign;
 use ruma_client_api::room::{create_room, Visibility};
 use ruma_common::{
-    serde::Raw, MxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, RoomAliasId, RoomId,
-    RoomOrAliasId, ServerName, UserId,
+    serde::Raw, MxcUri, OwnedEventId, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, RoomAliasId,
+    RoomId, RoomOrAliasId, ServerName, UserId,
 };
 use ruma_events::{
     receipt::{ReceiptThread, ReceiptType},
@@ -35,7 +35,7 @@ use super::{
     receipt::ReceiptRecord,
     room::Room,
     utils::{remap_for_diff, ApiVectorDiff},
-    RUNTIME,
+    ComposeDraft, OptionComposeDraft, RUNTIME,
 };
 
 pub type ConvoDiff = ApiVectorDiff<Convo>;
@@ -313,6 +313,90 @@ impl Convo {
             })
             .await?
     }
+
+    pub async fn msg_draft(&self) -> Result<OptionComposeDraft> {
+        if !self.is_joined() {
+            bail!("Unable to fetch composer draft of a room we are not in");
+        }
+        let room = self.room.clone();
+        RUNTIME
+            .spawn(async move {
+                let draft = room.load_composer_draft().await?;
+
+                Ok(OptionComposeDraft::new(draft.map(|composer_draft| {
+                    let (msg_type, event_id) = match composer_draft.draft_type {
+                        ComposerDraftType::NewMessage => ("new".to_string(), None),
+                        ComposerDraftType::Edit { event_id } => {
+                            ("edit".to_string(), Some(event_id))
+                        }
+                        ComposerDraftType::Reply { event_id } => {
+                            ("reply".to_string(), Some(event_id))
+                        }
+                    };
+                    ComposeDraft::new(
+                        composer_draft.plain_text,
+                        composer_draft.html_text,
+                        msg_type,
+                        event_id,
+                    )
+                })))
+            })
+            .await?
+    }
+
+    pub async fn save_msg_draft(
+        &self,
+        text: String,
+        html: Option<String>,
+        draft_type: String,
+        event_id: Option<String>,
+    ) -> Result<bool> {
+        if !self.is_joined() {
+            bail!("Unable to save composer draft of a room we are not in");
+        }
+        let room = self.room.clone();
+
+        let draft_type = match (draft_type.as_str(), event_id) {
+            ("new", None) => ComposerDraftType::NewMessage,
+            ("edit", Some(id)) => ComposerDraftType::Edit {
+                event_id: OwnedEventId::try_from(id)?,
+            },
+
+            ("reply", Some(id)) => ComposerDraftType::Reply {
+                event_id: OwnedEventId::try_from(id)?,
+            },
+
+            ("reply", _) | ("edit", _) => bail!("Invalid event id"),
+
+            (draft_type, _) => bail!("Invalid draft type {draft_type}"),
+        };
+
+        let msg_draft = ComposerDraft {
+            plain_text: text,
+            html_text: html,
+            draft_type,
+        };
+
+        RUNTIME
+            .spawn(async move {
+                room.save_composer_draft(msg_draft).await?;
+                Ok(true)
+            })
+            .await?
+    }
+
+    pub async fn clear_msg_draft(&self) -> Result<bool> {
+        if !self.is_joined() {
+            bail!("Unable to remove composer draft of a room we are not in");
+        }
+        let room = self.room.clone();
+        RUNTIME
+            .spawn(async move {
+                let draft = room.clear_composer_draft();
+                Ok(true)
+            })
+            .await?
+    }
 }
 
 impl Deref for Convo {
diff --git a/packages/acter_notifify/lib/platform/android.dart b/packages/acter_notifify/lib/platform/android.dart
index 831978ee1dd1..708774ce57ec 100644
--- a/packages/acter_notifify/lib/platform/android.dart
+++ b/packages/acter_notifify/lib/platform/android.dart
@@ -1,10 +1,9 @@
 import 'dart:async';
 
+import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
 import 'package:acter_notifify/local.dart';
-import 'package:acter_notifify/util.dart';
-
 import 'package:acter_notifify/matrix.dart';
-import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
+import 'package:acter_notifify/util.dart';
 import 'package:flutter_local_notifications/flutter_local_notifications.dart';
 import 'package:logging/logging.dart';
 
diff --git a/packages/rust_sdk/lib/acter_flutter_sdk.dart b/packages/rust_sdk/lib/acter_flutter_sdk.dart
index a83c10d8f8f1..42aa40a0139e 100644
--- a/packages/rust_sdk/lib/acter_flutter_sdk.dart
+++ b/packages/rust_sdk/lib/acter_flutter_sdk.dart
@@ -116,8 +116,8 @@ Future<ImageProvider<Object>?> remapToImage(
       return ResizeImage(image, width: cacheWidth, height: cacheHeight);
     }
     return image;
-  } catch (e) {
-    _log.severe('Error fetching avatar: $e');
+  } catch (e, st) {
+    _log.severe('Error fetching avatar', e, st);
     return null;
   }
 }
diff --git a/packages/rust_sdk/lib/acter_flutter_sdk_ffi.dart b/packages/rust_sdk/lib/acter_flutter_sdk_ffi.dart
index 9cc4e580f17c..932184b0a930 100644
--- a/packages/rust_sdk/lib/acter_flutter_sdk_ffi.dart
+++ b/packages/rust_sdk/lib/acter_flutter_sdk_ffi.dart
@@ -7035,6 +7035,141 @@ class Api {
     return tmp7;
   }
 
+  OptionComposeDraft? __convoMsgDraftFuturePoll(
+    int boxed,
+    int postCobject,
+    int port,
+  ) {
+    final tmp0 = boxed;
+    final tmp2 = postCobject;
+    final tmp4 = port;
+    var tmp1 = 0;
+    var tmp3 = 0;
+    var tmp5 = 0;
+    tmp1 = tmp0;
+    tmp3 = tmp2;
+    tmp5 = tmp4;
+    final tmp6 = _convoMsgDraftFuturePoll(
+      tmp1,
+      tmp3,
+      tmp5,
+    );
+    final tmp8 = tmp6.arg0;
+    final tmp9 = tmp6.arg1;
+    final tmp10 = tmp6.arg2;
+    final tmp11 = tmp6.arg3;
+    final tmp12 = tmp6.arg4;
+    final tmp13 = tmp6.arg5;
+    if (tmp8 == 0) {
+      return null;
+    }
+    if (tmp9 == 0) {
+      debugAllocation("handle error", tmp10, tmp11);
+      final ffi.Pointer<ffi.Uint8> tmp10_0 = ffi.Pointer.fromAddress(tmp10);
+      final tmp9_0 =
+          utf8.decode(tmp10_0.asTypedList(tmp11), allowMalformed: true);
+      if (tmp11 > 0) {
+        final ffi.Pointer<ffi.Void> tmp10_0;
+        tmp10_0 = ffi.Pointer.fromAddress(tmp10);
+        this.__deallocate(tmp10_0, tmp12, 1);
+      }
+      throw tmp9_0;
+    }
+    final ffi.Pointer<ffi.Void> tmp13_0 = ffi.Pointer.fromAddress(tmp13);
+    final tmp13_1 = _Box(this, tmp13_0, "drop_box_OptionComposeDraft");
+    tmp13_1._finalizer = this._registerFinalizer(tmp13_1);
+    final tmp7 = OptionComposeDraft._(this, tmp13_1);
+    return tmp7;
+  }
+
+  bool? __convoSaveMsgDraftFuturePoll(
+    int boxed,
+    int postCobject,
+    int port,
+  ) {
+    final tmp0 = boxed;
+    final tmp2 = postCobject;
+    final tmp4 = port;
+    var tmp1 = 0;
+    var tmp3 = 0;
+    var tmp5 = 0;
+    tmp1 = tmp0;
+    tmp3 = tmp2;
+    tmp5 = tmp4;
+    final tmp6 = _convoSaveMsgDraftFuturePoll(
+      tmp1,
+      tmp3,
+      tmp5,
+    );
+    final tmp8 = tmp6.arg0;
+    final tmp9 = tmp6.arg1;
+    final tmp10 = tmp6.arg2;
+    final tmp11 = tmp6.arg3;
+    final tmp12 = tmp6.arg4;
+    final tmp13 = tmp6.arg5;
+    if (tmp8 == 0) {
+      return null;
+    }
+    if (tmp9 == 0) {
+      debugAllocation("handle error", tmp10, tmp11);
+      final ffi.Pointer<ffi.Uint8> tmp10_0 = ffi.Pointer.fromAddress(tmp10);
+      final tmp9_0 =
+          utf8.decode(tmp10_0.asTypedList(tmp11), allowMalformed: true);
+      if (tmp11 > 0) {
+        final ffi.Pointer<ffi.Void> tmp10_0;
+        tmp10_0 = ffi.Pointer.fromAddress(tmp10);
+        this.__deallocate(tmp10_0, tmp12, 1);
+      }
+      throw tmp9_0;
+    }
+    final tmp7 = tmp13 > 0;
+    return tmp7;
+  }
+
+  bool? __convoClearMsgDraftFuturePoll(
+    int boxed,
+    int postCobject,
+    int port,
+  ) {
+    final tmp0 = boxed;
+    final tmp2 = postCobject;
+    final tmp4 = port;
+    var tmp1 = 0;
+    var tmp3 = 0;
+    var tmp5 = 0;
+    tmp1 = tmp0;
+    tmp3 = tmp2;
+    tmp5 = tmp4;
+    final tmp6 = _convoClearMsgDraftFuturePoll(
+      tmp1,
+      tmp3,
+      tmp5,
+    );
+    final tmp8 = tmp6.arg0;
+    final tmp9 = tmp6.arg1;
+    final tmp10 = tmp6.arg2;
+    final tmp11 = tmp6.arg3;
+    final tmp12 = tmp6.arg4;
+    final tmp13 = tmp6.arg5;
+    if (tmp8 == 0) {
+      return null;
+    }
+    if (tmp9 == 0) {
+      debugAllocation("handle error", tmp10, tmp11);
+      final ffi.Pointer<ffi.Uint8> tmp10_0 = ffi.Pointer.fromAddress(tmp10);
+      final tmp9_0 =
+          utf8.decode(tmp10_0.asTypedList(tmp11), allowMalformed: true);
+      if (tmp11 > 0) {
+        final ffi.Pointer<ffi.Void> tmp10_0;
+        tmp10_0 = ffi.Pointer.fromAddress(tmp10);
+        this.__deallocate(tmp10_0, tmp12, 1);
+      }
+      throw tmp9_0;
+    }
+    final tmp7 = tmp13 > 0;
+    return tmp7;
+  }
+
   EventId? __commentDraftSendFuturePoll(
     int boxed,
     int postCobject,
@@ -16878,6 +17013,16 @@ class Api {
           _OptionRsvpStatusStatusStrReturn Function(
             int,
           )>();
+  late final _optionComposeDraftDraftPtr = _lookup<
+      ffi.NativeFunction<
+          _OptionComposeDraftDraftReturn Function(
+            ffi.IntPtr,
+          )>>("__OptionComposeDraft_draft");
+
+  late final _optionComposeDraftDraft = _optionComposeDraftDraftPtr.asFunction<
+      _OptionComposeDraftDraftReturn Function(
+        int,
+      )>();
   late final _userProfileUserIdPtr = _lookup<
       ffi.NativeFunction<
           ffi.IntPtr Function(
@@ -17138,6 +17283,46 @@ class Api {
       _MxcUriToStringReturn Function(
         int,
       )>();
+  late final _composeDraftPlainTextPtr = _lookup<
+      ffi.NativeFunction<
+          _ComposeDraftPlainTextReturn Function(
+            ffi.IntPtr,
+          )>>("__ComposeDraft_plain_text");
+
+  late final _composeDraftPlainText = _composeDraftPlainTextPtr.asFunction<
+      _ComposeDraftPlainTextReturn Function(
+        int,
+      )>();
+  late final _composeDraftHtmlTextPtr = _lookup<
+      ffi.NativeFunction<
+          _ComposeDraftHtmlTextReturn Function(
+            ffi.IntPtr,
+          )>>("__ComposeDraft_html_text");
+
+  late final _composeDraftHtmlText = _composeDraftHtmlTextPtr.asFunction<
+      _ComposeDraftHtmlTextReturn Function(
+        int,
+      )>();
+  late final _composeDraftEventIdPtr = _lookup<
+      ffi.NativeFunction<
+          _ComposeDraftEventIdReturn Function(
+            ffi.IntPtr,
+          )>>("__ComposeDraft_event_id");
+
+  late final _composeDraftEventId = _composeDraftEventIdPtr.asFunction<
+      _ComposeDraftEventIdReturn Function(
+        int,
+      )>();
+  late final _composeDraftDraftTypePtr = _lookup<
+      ffi.NativeFunction<
+          _ComposeDraftDraftTypeReturn Function(
+            ffi.IntPtr,
+          )>>("__ComposeDraft_draft_type");
+
+  late final _composeDraftDraftType = _composeDraftDraftTypePtr.asFunction<
+      _ComposeDraftDraftTypeReturn Function(
+        int,
+      )>();
   late final _roomIdToStringPtr = _lookup<
       ffi.NativeFunction<
           _RoomIdToStringReturn Function(
@@ -20907,6 +21092,64 @@ class Api {
       int Function(
         int,
       )>();
+  late final _convoMsgDraftPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.IntPtr Function(
+            ffi.IntPtr,
+          )>>("__Convo_msg_draft");
+
+  late final _convoMsgDraft = _convoMsgDraftPtr.asFunction<
+      int Function(
+        int,
+      )>();
+  late final _convoSaveMsgDraftPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.IntPtr Function(
+            ffi.IntPtr,
+            ffi.IntPtr,
+            ffi.UintPtr,
+            ffi.UintPtr,
+            ffi.Uint8,
+            ffi.IntPtr,
+            ffi.UintPtr,
+            ffi.UintPtr,
+            ffi.IntPtr,
+            ffi.UintPtr,
+            ffi.UintPtr,
+            ffi.Uint8,
+            ffi.IntPtr,
+            ffi.UintPtr,
+            ffi.UintPtr,
+          )>>("__Convo_save_msg_draft");
+
+  late final _convoSaveMsgDraft = _convoSaveMsgDraftPtr.asFunction<
+      int Function(
+        int,
+        int,
+        int,
+        int,
+        int,
+        int,
+        int,
+        int,
+        int,
+        int,
+        int,
+        int,
+        int,
+        int,
+        int,
+      )>();
+  late final _convoClearMsgDraftPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.IntPtr Function(
+            ffi.IntPtr,
+          )>>("__Convo_clear_msg_draft");
+
+  late final _convoClearMsgDraft = _convoClearMsgDraftPtr.asFunction<
+      int Function(
+        int,
+      )>();
   late final _commentDraftContentTextPtr = _lookup<
       ffi.NativeFunction<
           ffi.Void Function(
@@ -29318,6 +29561,50 @@ class Api {
             int,
             int,
           )>();
+  late final _convoMsgDraftFuturePollPtr = _lookup<
+      ffi.NativeFunction<
+          _ConvoMsgDraftFuturePollReturn Function(
+            ffi.IntPtr,
+            ffi.IntPtr,
+            ffi.Int64,
+          )>>("__Convo_msg_draft_future_poll");
+
+  late final _convoMsgDraftFuturePoll = _convoMsgDraftFuturePollPtr.asFunction<
+      _ConvoMsgDraftFuturePollReturn Function(
+        int,
+        int,
+        int,
+      )>();
+  late final _convoSaveMsgDraftFuturePollPtr = _lookup<
+      ffi.NativeFunction<
+          _ConvoSaveMsgDraftFuturePollReturn Function(
+            ffi.IntPtr,
+            ffi.IntPtr,
+            ffi.Int64,
+          )>>("__Convo_save_msg_draft_future_poll");
+
+  late final _convoSaveMsgDraftFuturePoll =
+      _convoSaveMsgDraftFuturePollPtr.asFunction<
+          _ConvoSaveMsgDraftFuturePollReturn Function(
+            int,
+            int,
+            int,
+          )>();
+  late final _convoClearMsgDraftFuturePollPtr = _lookup<
+      ffi.NativeFunction<
+          _ConvoClearMsgDraftFuturePollReturn Function(
+            ffi.IntPtr,
+            ffi.IntPtr,
+            ffi.Int64,
+          )>>("__Convo_clear_msg_draft_future_poll");
+
+  late final _convoClearMsgDraftFuturePoll =
+      _convoClearMsgDraftFuturePollPtr.asFunction<
+          _ConvoClearMsgDraftFuturePollReturn Function(
+            int,
+            int,
+            int,
+          )>();
   late final _commentDraftSendFuturePollPtr = _lookup<
       ffi.NativeFunction<
           _CommentDraftSendFuturePollReturn Function(
@@ -34823,6 +35110,37 @@ class OptionRsvpStatus {
   }
 }
 
+class OptionComposeDraft {
+  final Api _api;
+  final _Box _box;
+
+  OptionComposeDraft._(this._api, this._box);
+
+  /// get compose draft object
+  ComposeDraft? draft() {
+    var tmp0 = 0;
+    tmp0 = _box.borrow();
+    final tmp1 = _api._optionComposeDraftDraft(
+      tmp0,
+    );
+    final tmp3 = tmp1.arg0;
+    final tmp4 = tmp1.arg1;
+    if (tmp3 == 0) {
+      return null;
+    }
+    final ffi.Pointer<ffi.Void> tmp4_0 = ffi.Pointer.fromAddress(tmp4);
+    final tmp4_1 = _Box(_api, tmp4_0, "drop_box_ComposeDraft");
+    tmp4_1._finalizer = _api._registerFinalizer(tmp4_1);
+    final tmp2 = ComposeDraft._(_api, tmp4_1);
+    return tmp2;
+  }
+
+  /// Manually drops the object and unregisters the FinalizableHandle.
+  void drop() {
+    _box.drop();
+  }
+}
+
 class UserProfile {
   final Api _api;
   final _Box _box;
@@ -35452,16 +35770,99 @@ class DeviceId {
   }
 }
 
-class EventId {
+class EventId {
+  final Api _api;
+  final _Box _box;
+
+  EventId._(this._api, this._box);
+
+  String toString() {
+    var tmp0 = 0;
+    tmp0 = _box.borrow();
+    final tmp1 = _api._eventIdToString(
+      tmp0,
+    );
+    final tmp3 = tmp1.arg0;
+    final tmp4 = tmp1.arg1;
+    final tmp5 = tmp1.arg2;
+    if (tmp4 == 0) {
+      print("returning empty string");
+      return "";
+    }
+    final ffi.Pointer<ffi.Uint8> tmp3_ptr = ffi.Pointer.fromAddress(tmp3);
+    List<int> tmp3_buf = [];
+    final tmp3_precast = tmp3_ptr.cast<ffi.Uint8>();
+    for (int i = 0; i < tmp4; i++) {
+      int char = tmp3_precast.elementAt(i).value;
+      tmp3_buf.add(char);
+    }
+    final tmp2 = utf8.decode(tmp3_buf, allowMalformed: true);
+    if (tmp5 > 0) {
+      final ffi.Pointer<ffi.Void> tmp3_0;
+      tmp3_0 = ffi.Pointer.fromAddress(tmp3);
+      _api.__deallocate(tmp3_0, tmp5 * 1, 1);
+    }
+    return tmp2;
+  }
+
+  /// Manually drops the object and unregisters the FinalizableHandle.
+  void drop() {
+    _box.drop();
+  }
+}
+
+class MxcUri {
+  final Api _api;
+  final _Box _box;
+
+  MxcUri._(this._api, this._box);
+
+  String toString() {
+    var tmp0 = 0;
+    tmp0 = _box.borrow();
+    final tmp1 = _api._mxcUriToString(
+      tmp0,
+    );
+    final tmp3 = tmp1.arg0;
+    final tmp4 = tmp1.arg1;
+    final tmp5 = tmp1.arg2;
+    if (tmp4 == 0) {
+      print("returning empty string");
+      return "";
+    }
+    final ffi.Pointer<ffi.Uint8> tmp3_ptr = ffi.Pointer.fromAddress(tmp3);
+    List<int> tmp3_buf = [];
+    final tmp3_precast = tmp3_ptr.cast<ffi.Uint8>();
+    for (int i = 0; i < tmp4; i++) {
+      int char = tmp3_precast.elementAt(i).value;
+      tmp3_buf.add(char);
+    }
+    final tmp2 = utf8.decode(tmp3_buf, allowMalformed: true);
+    if (tmp5 > 0) {
+      final ffi.Pointer<ffi.Void> tmp3_0;
+      tmp3_0 = ffi.Pointer.fromAddress(tmp3);
+      _api.__deallocate(tmp3_0, tmp5 * 1, 1);
+    }
+    return tmp2;
+  }
+
+  /// Manually drops the object and unregisters the FinalizableHandle.
+  void drop() {
+    _box.drop();
+  }
+}
+
+class ComposeDraft {
   final Api _api;
   final _Box _box;
 
-  EventId._(this._api, this._box);
+  ComposeDraft._(this._api, this._box);
 
-  String toString() {
+  /// plain body text, always available
+  String plainText() {
     var tmp0 = 0;
     tmp0 = _box.borrow();
-    final tmp1 = _api._eventIdToString(
+    final tmp1 = _api._composeDraftPlainText(
       tmp0,
     );
     final tmp3 = tmp1.arg0;
@@ -35487,22 +35888,80 @@ class EventId {
     return tmp2;
   }
 
-  /// Manually drops the object and unregisters the FinalizableHandle.
-  void drop() {
-    _box.drop();
+  /// formatted text
+  String? htmlText() {
+    var tmp0 = 0;
+    tmp0 = _box.borrow();
+    final tmp1 = _api._composeDraftHtmlText(
+      tmp0,
+    );
+    final tmp3 = tmp1.arg0;
+    final tmp4 = tmp1.arg1;
+    final tmp5 = tmp1.arg2;
+    final tmp6 = tmp1.arg3;
+    if (tmp3 == 0) {
+      return null;
+    }
+    if (tmp5 == 0) {
+      print("returning empty string");
+      return "";
+    }
+    final ffi.Pointer<ffi.Uint8> tmp4_ptr = ffi.Pointer.fromAddress(tmp4);
+    List<int> tmp4_buf = [];
+    final tmp4_precast = tmp4_ptr.cast<ffi.Uint8>();
+    for (int i = 0; i < tmp5; i++) {
+      int char = tmp4_precast.elementAt(i).value;
+      tmp4_buf.add(char);
+    }
+    final tmp2 = utf8.decode(tmp4_buf, allowMalformed: true);
+    if (tmp6 > 0) {
+      final ffi.Pointer<ffi.Void> tmp4_0;
+      tmp4_0 = ffi.Pointer.fromAddress(tmp4);
+      _api.__deallocate(tmp4_0, tmp6 * 1, 1);
+    }
+    return tmp2;
   }
-}
-
-class MxcUri {
-  final Api _api;
-  final _Box _box;
 
-  MxcUri._(this._api, this._box);
+  /// event id, only valid for edit and reply states
+  String? eventId() {
+    var tmp0 = 0;
+    tmp0 = _box.borrow();
+    final tmp1 = _api._composeDraftEventId(
+      tmp0,
+    );
+    final tmp3 = tmp1.arg0;
+    final tmp4 = tmp1.arg1;
+    final tmp5 = tmp1.arg2;
+    final tmp6 = tmp1.arg3;
+    if (tmp3 == 0) {
+      return null;
+    }
+    if (tmp5 == 0) {
+      print("returning empty string");
+      return "";
+    }
+    final ffi.Pointer<ffi.Uint8> tmp4_ptr = ffi.Pointer.fromAddress(tmp4);
+    List<int> tmp4_buf = [];
+    final tmp4_precast = tmp4_ptr.cast<ffi.Uint8>();
+    for (int i = 0; i < tmp5; i++) {
+      int char = tmp4_precast.elementAt(i).value;
+      tmp4_buf.add(char);
+    }
+    final tmp2 = utf8.decode(tmp4_buf, allowMalformed: true);
+    if (tmp6 > 0) {
+      final ffi.Pointer<ffi.Void> tmp4_0;
+      tmp4_0 = ffi.Pointer.fromAddress(tmp4);
+      _api.__deallocate(tmp4_0, tmp6 * 1, 1);
+    }
+    return tmp2;
+  }
 
-  String toString() {
+  /// compose message state type.
+  /// One of `new`, `edit`, `reply`.
+  String draftType() {
     var tmp0 = 0;
     tmp0 = _box.borrow();
-    final tmp1 = _api._mxcUriToString(
+    final tmp1 = _api._composeDraftDraftType(
       tmp0,
     );
     final tmp3 = tmp1.arg0;
@@ -43428,6 +43887,132 @@ class Convo {
     return tmp2;
   }
 
+  /// compose message state of the room
+  Future<OptionComposeDraft> msgDraft() {
+    var tmp0 = 0;
+    tmp0 = _box.borrow();
+    final tmp1 = _api._convoMsgDraft(
+      tmp0,
+    );
+    final tmp3 = tmp1;
+    final ffi.Pointer<ffi.Void> tmp3_0 = ffi.Pointer.fromAddress(tmp3);
+    final tmp3_1 = _Box(_api, tmp3_0, "__Convo_msg_draft_future_drop");
+    tmp3_1._finalizer = _api._registerFinalizer(tmp3_1);
+    final tmp2 = _nativeFuture(tmp3_1, _api.__convoMsgDraftFuturePoll);
+    return tmp2;
+  }
+
+  /// save composed message state of the room
+  Future<bool> saveMsgDraft(
+    String text,
+    String? html,
+    String draftType,
+    String? eventId,
+  ) {
+    final tmp1 = text;
+    final tmp5 = html;
+    final tmp11 = draftType;
+    final tmp15 = eventId;
+    var tmp0 = 0;
+    var tmp2 = 0;
+    var tmp3 = 0;
+    var tmp4 = 0;
+    var tmp6 = 0;
+    var tmp8 = 0;
+    var tmp9 = 0;
+    var tmp10 = 0;
+    var tmp12 = 0;
+    var tmp13 = 0;
+    var tmp14 = 0;
+    var tmp16 = 0;
+    var tmp18 = 0;
+    var tmp19 = 0;
+    var tmp20 = 0;
+    tmp0 = _box.borrow();
+    final tmp1_0 = utf8.encode(tmp1);
+    tmp3 = tmp1_0.length;
+
+    final ffi.Pointer<ffi.Uint8> tmp2_0 = _api.__allocate(tmp3 * 1, 1);
+    final Uint8List tmp2_1 = tmp2_0.asTypedList(tmp3);
+    tmp2_1.setAll(0, tmp1_0);
+    tmp2 = tmp2_0.address;
+    tmp4 = tmp3;
+    if (tmp5 == null) {
+      tmp6 = 0;
+    } else {
+      tmp6 = 1;
+      final tmp7 = tmp5;
+      final tmp7_0 = utf8.encode(tmp7);
+      tmp9 = tmp7_0.length;
+
+      final ffi.Pointer<ffi.Uint8> tmp8_0 = _api.__allocate(tmp9 * 1, 1);
+      final Uint8List tmp8_1 = tmp8_0.asTypedList(tmp9);
+      tmp8_1.setAll(0, tmp7_0);
+      tmp8 = tmp8_0.address;
+      tmp10 = tmp9;
+    }
+    final tmp11_0 = utf8.encode(tmp11);
+    tmp13 = tmp11_0.length;
+
+    final ffi.Pointer<ffi.Uint8> tmp12_0 = _api.__allocate(tmp13 * 1, 1);
+    final Uint8List tmp12_1 = tmp12_0.asTypedList(tmp13);
+    tmp12_1.setAll(0, tmp11_0);
+    tmp12 = tmp12_0.address;
+    tmp14 = tmp13;
+    if (tmp15 == null) {
+      tmp16 = 0;
+    } else {
+      tmp16 = 1;
+      final tmp17 = tmp15;
+      final tmp17_0 = utf8.encode(tmp17);
+      tmp19 = tmp17_0.length;
+
+      final ffi.Pointer<ffi.Uint8> tmp18_0 = _api.__allocate(tmp19 * 1, 1);
+      final Uint8List tmp18_1 = tmp18_0.asTypedList(tmp19);
+      tmp18_1.setAll(0, tmp17_0);
+      tmp18 = tmp18_0.address;
+      tmp20 = tmp19;
+    }
+    final tmp21 = _api._convoSaveMsgDraft(
+      tmp0,
+      tmp2,
+      tmp3,
+      tmp4,
+      tmp6,
+      tmp8,
+      tmp9,
+      tmp10,
+      tmp12,
+      tmp13,
+      tmp14,
+      tmp16,
+      tmp18,
+      tmp19,
+      tmp20,
+    );
+    final tmp23 = tmp21;
+    final ffi.Pointer<ffi.Void> tmp23_0 = ffi.Pointer.fromAddress(tmp23);
+    final tmp23_1 = _Box(_api, tmp23_0, "__Convo_save_msg_draft_future_drop");
+    tmp23_1._finalizer = _api._registerFinalizer(tmp23_1);
+    final tmp22 = _nativeFuture(tmp23_1, _api.__convoSaveMsgDraftFuturePoll);
+    return tmp22;
+  }
+
+  /// clear composed message state of the room
+  Future<bool> clearMsgDraft() {
+    var tmp0 = 0;
+    tmp0 = _box.borrow();
+    final tmp1 = _api._convoClearMsgDraft(
+      tmp0,
+    );
+    final tmp3 = tmp1;
+    final ffi.Pointer<ffi.Void> tmp3_0 = ffi.Pointer.fromAddress(tmp3);
+    final tmp3_1 = _Box(_api, tmp3_0, "__Convo_clear_msg_draft_future_drop");
+    tmp3_1._finalizer = _api._registerFinalizer(tmp3_1);
+    final tmp2 = _nativeFuture(tmp3_1, _api.__convoClearMsgDraftFuturePoll);
+    return tmp2;
+  }
+
   /// Manually drops the object and unregisters the FinalizableHandle.
   void drop() {
     _box.drop();
@@ -57601,6 +58186,13 @@ class _OptionRsvpStatusStatusStrReturn extends ffi.Struct {
   external int arg3;
 }
 
+class _OptionComposeDraftDraftReturn extends ffi.Struct {
+  @ffi.Uint8()
+  external int arg0;
+  @ffi.IntPtr()
+  external int arg1;
+}
+
 class _UserProfileGetDisplayNameReturn extends ffi.Struct {
   @ffi.Uint8()
   external int arg0;
@@ -57741,6 +58333,46 @@ class _MxcUriToStringReturn extends ffi.Struct {
   external int arg2;
 }
 
+class _ComposeDraftPlainTextReturn extends ffi.Struct {
+  @ffi.IntPtr()
+  external int arg0;
+  @ffi.UintPtr()
+  external int arg1;
+  @ffi.UintPtr()
+  external int arg2;
+}
+
+class _ComposeDraftHtmlTextReturn extends ffi.Struct {
+  @ffi.Uint8()
+  external int arg0;
+  @ffi.IntPtr()
+  external int arg1;
+  @ffi.UintPtr()
+  external int arg2;
+  @ffi.UintPtr()
+  external int arg3;
+}
+
+class _ComposeDraftEventIdReturn extends ffi.Struct {
+  @ffi.Uint8()
+  external int arg0;
+  @ffi.IntPtr()
+  external int arg1;
+  @ffi.UintPtr()
+  external int arg2;
+  @ffi.UintPtr()
+  external int arg3;
+}
+
+class _ComposeDraftDraftTypeReturn extends ffi.Struct {
+  @ffi.IntPtr()
+  external int arg0;
+  @ffi.UintPtr()
+  external int arg1;
+  @ffi.UintPtr()
+  external int arg2;
+}
+
 class _RoomIdToStringReturn extends ffi.Struct {
   @ffi.IntPtr()
   external int arg0;
@@ -61482,6 +62114,51 @@ class _ConvoRedactContentFuturePollReturn extends ffi.Struct {
   external int arg5;
 }
 
+class _ConvoMsgDraftFuturePollReturn extends ffi.Struct {
+  @ffi.Uint8()
+  external int arg0;
+  @ffi.Uint8()
+  external int arg1;
+  @ffi.IntPtr()
+  external int arg2;
+  @ffi.UintPtr()
+  external int arg3;
+  @ffi.UintPtr()
+  external int arg4;
+  @ffi.IntPtr()
+  external int arg5;
+}
+
+class _ConvoSaveMsgDraftFuturePollReturn extends ffi.Struct {
+  @ffi.Uint8()
+  external int arg0;
+  @ffi.Uint8()
+  external int arg1;
+  @ffi.IntPtr()
+  external int arg2;
+  @ffi.UintPtr()
+  external int arg3;
+  @ffi.UintPtr()
+  external int arg4;
+  @ffi.Uint8()
+  external int arg5;
+}
+
+class _ConvoClearMsgDraftFuturePollReturn extends ffi.Struct {
+  @ffi.Uint8()
+  external int arg0;
+  @ffi.Uint8()
+  external int arg1;
+  @ffi.IntPtr()
+  external int arg2;
+  @ffi.UintPtr()
+  external int arg3;
+  @ffi.UintPtr()
+  external int arg4;
+  @ffi.Uint8()
+  external int arg5;
+}
+
 class _CommentDraftSendFuturePollReturn extends ffi.Struct {
   @ffi.Uint8()
   external int arg0;