diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index 30e43b6..a7d8f52 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -35,6 +35,7 @@ "createPublisherHint": "To create posts, collections, etc.", "editPublisher": "Edit Publisher", "syncPublisher": "Use Account Data", + "syncPublisherRealm": "Use Realm Data", "create": "Create", "update": "Update", "edit": "Edit", @@ -179,5 +180,7 @@ "uploading": "Uploading", "uploadingProgress": "Uploading {} of {}", "uploadAll": "Upload All", - "stickerCopyPlaceholder": "Copy Placeholder" + "stickerCopyPlaceholder": "Copy Placeholder", + "realmSelection": "Select a Realm", + "publisherIndividual": "Individual Publishers" } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 31f1b2c..d314512 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -165,14 +165,6 @@ PODS: - super_native_extensions (0.0.1): - Flutter - SwiftyGif (5.4.5) - - tencent_rtc_sdk (0.0.1): - - Flutter - - TXCustomBeautyProcesserPlugin (= 1.0.2) - - TXLiteAVSDK_Professional (~> 12.3.16995) - - TXCustomBeautyProcesserPlugin (1.0.2) - - TXLiteAVSDK_Professional (12.3.16995): - - TXLiteAVSDK_Professional/Professional (= 12.3.16995) - - TXLiteAVSDK_Professional/Professional (12.3.16995) - url_launcher_ios (0.0.1): - Flutter - volume_controller (0.0.1): @@ -201,7 +193,6 @@ DEPENDENCIES: - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) - sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`) - super_native_extensions (from `.symlinks/plugins/super_native_extensions/ios`) - - tencent_rtc_sdk (from `.symlinks/plugins/tencent_rtc_sdk/ios`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - volume_controller (from `.symlinks/plugins/volume_controller/ios`) - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) @@ -225,8 +216,6 @@ SPEC REPOS: - SDWebImage - sqlite3 - SwiftyGif - - TXCustomBeautyProcesserPlugin - - TXLiteAVSDK_Professional EXTERNAL SOURCES: croppy: @@ -267,8 +256,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/sqlite3_flutter_libs/darwin" super_native_extensions: :path: ".symlinks/plugins/super_native_extensions/ios" - tencent_rtc_sdk: - :path: ".symlinks/plugins/tencent_rtc_sdk/ios" url_launcher_ios: :path: ".symlinks/plugins/url_launcher_ios/ios" volume_controller: @@ -313,9 +300,6 @@ SPEC CHECKSUMS: sqlite3_flutter_libs: f6acaa2172e6bb3e2e70c771661905080e8ebcf2 super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4 SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 - tencent_rtc_sdk: 13f066e69b87068b4cf3df90ad04097eb8773ae2 - TXCustomBeautyProcesserPlugin: 099393b941cb40eda12b3a80bf6c0319957b1cfd - TXLiteAVSDK_Professional: 6e8fa18eeb0e52e6bbbcd97bab9ec9fbdc828df3 url_launcher_ios: 694010445543906933d732453a59da0a173ae33d volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12 wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556 diff --git a/lib/pods/network.dart b/lib/pods/network.dart index a3b4fdc..d5403d7 100644 --- a/lib/pods/network.dart +++ b/lib/pods/network.dart @@ -83,7 +83,7 @@ final apiClientProvider = Provider((ref) { // ignore } - final userAgent = ref.watch(userAgentProvider); + final userAgent = ref.read(userAgentProvider); if (userAgent.value != null) { options.headers['User-Agent'] = userAgent.value; } diff --git a/lib/screens/account/me/publishers.dart b/lib/screens/account/me/publishers.dart index 2ba58fc..5163d1e 100644 --- a/lib/screens/account/me/publishers.dart +++ b/lib/screens/account/me/publishers.dart @@ -1,17 +1,19 @@ import 'package:auto_route/auto_route.dart'; import 'package:croppy/croppy.dart' hide cropImage; import 'package:dio/dio.dart'; +import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:image_picker/image_picker.dart'; -import 'package:island/models/file.dart'; import 'package:island/models/post.dart'; +import 'package:island/models/realm.dart'; import 'package:island/pods/config.dart'; import 'package:island/pods/network.dart'; import 'package:island/pods/userinfo.dart'; import 'package:island/route.gr.dart'; +import 'package:island/screens/realm/realms.dart'; import 'package:island/services/file.dart'; import 'package:island/widgets/alert.dart'; import 'package:island/widgets/app_scaffold.dart'; @@ -173,15 +175,20 @@ class EditPublisherScreen extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final submitting = useState(false); - final picture = useState(null); - final background = useState(null); + final picture = useState(null); + final background = useState(null); void setPicture(String position) async { + showLoadingModal(context); var result = await ref .read(imagePickerProvider) .pickImage(source: ImageSource.gallery); - if (result == null) return; + if (result == null) { + if (context.mounted) hideLoadingModal(context); + return; + } if (!context.mounted) return; + hideLoadingModal(context); result = await cropImage( context, image: result, @@ -194,6 +201,7 @@ class EditPublisherScreen extends HookConsumerWidget { ); if (result == null) return; if (!context.mounted) return; + showLoadingModal(context); submitting.value = true; try { @@ -220,14 +228,15 @@ class EditPublisherScreen extends HookConsumerWidget { } switch (position) { case 'picture': - picture.value = cloudFile; + picture.value = cloudFile.id; case 'background': - background.value = cloudFile; + background.value = cloudFile.id; } } catch (err) { showErrorAlert(err); } finally { submitting.value = false; + if (context.mounted) hideLoadingModal(context); } } @@ -242,10 +251,13 @@ class EditPublisherScreen extends HookConsumerWidget { ); final bioController = useTextEditingController(text: publisher.value?.bio); + final joinedRealms = ref.watch(realmsJoinedProvider); + final currentRealm = useState(null); + useEffect(() { if (publisher.value != null) { - picture.value = publisher.value!.picture; - background.value = publisher.value!.background; + picture.value = publisher.value!.pictureId; + background.value = publisher.value!.backgroundId; nameController.text = publisher.value!.name; nickController.text = publisher.value!.nick; bioController.text = publisher.value!.bio; @@ -265,8 +277,8 @@ class EditPublisherScreen extends HookConsumerWidget { 'name': nameController.text, 'nick': nickController.text, 'bio': bioController.text, - 'picture_id': picture.value?.id, - 'background_id': background.value?.id, + 'picture_id': picture.value, + 'background_id': background.value, }, options: Options(method: name == null ? 'POST' : 'PATCH'), ); @@ -287,6 +299,55 @@ class EditPublisherScreen extends HookConsumerWidget { ), body: Column( children: [ + DropdownButtonHideUnderline( + child: DropdownButton2( + isExpanded: true, + hint: Text('realmSelection').tr(), + value: currentRealm.value, + items: [ + DropdownMenuItem( + value: null, + child: Row( + spacing: 12, + children: [ + CircleAvatar(radius: 16, child: Icon(Symbols.person)), + Text('publisherIndividual').tr(), + ], + ), + ), + ...joinedRealms.when( + data: + (realms) => + realms + .map( + (realm) => DropdownMenuItem( + value: realm, + child: Row( + spacing: 12, + children: [ + ProfilePictureWidget( + fileId: realm.pictureId, + fallbackIcon: Symbols.workspaces, + radius: 16, + ), + Text(realm.name), + ], + ), + ), + ) + .toList(), + loading: () => [], + error: (_, __) => [], + ), + ], + onChanged: (SnRealm? value) { + currentRealm.value = value; + }, + buttonStyleData: ButtonStyleData( + padding: const EdgeInsets.only(left: 4, right: 16), + ), + ), + ), AspectRatio( aspectRatio: 16 / 7, child: Stack( @@ -298,8 +359,8 @@ class EditPublisherScreen extends HookConsumerWidget { color: Theme.of(context).colorScheme.surfaceContainerHigh, child: background.value != null - ? CloudFileWidget( - item: background.value!, + ? CloudImageWidget( + fileId: background.value!, fit: BoxFit.cover, ) : const SizedBox.shrink(), @@ -313,7 +374,7 @@ class EditPublisherScreen extends HookConsumerWidget { bottom: -32, child: GestureDetector( child: ProfilePictureWidget( - fileId: picture.value?.id, + fileId: picture.value, radius: 40, ), onTap: () { @@ -360,19 +421,32 @@ class EditPublisherScreen extends HookConsumerWidget { children: [ TextButton.icon( onPressed: () { - final user = ref.watch(userInfoProvider); - nameController.text = user.value!.name; - nickController.text = user.value!.nick; - bioController.text = user.value!.profile.bio ?? ''; - picture.value = user.value!.profile.picture; - background.value = user.value!.profile.background; + if (currentRealm.value == null) { + final user = ref.watch(userInfoProvider); + nameController.text = user.value!.name; + nickController.text = user.value!.nick; + bioController.text = user.value!.profile.bio ?? ''; + picture.value = user.value!.profile.pictureId; + background.value = user.value!.profile.backgroundId; + } else { + nameController.text = currentRealm.value!.slug; + nickController.text = currentRealm.value!.name; + bioController.text = currentRealm.value!.description; + picture.value = currentRealm.value!.pictureId; + background.value = currentRealm.value!.backgroundId; + } }, - label: Text('syncPublisher'.tr()), + label: + Text( + currentRealm.value == null + ? 'syncPublisher' + : 'syncPublisherRealm', + ).tr(), icon: const Icon(Symbols.link), ), TextButton.icon( onPressed: submitting.value ? null : performAction, - label: Text('saveChanges'.tr()), + label: Text(name == null ? 'create' : 'saveChanges').tr(), icon: const Icon(Symbols.save), ), ], diff --git a/lib/screens/account/me/update.dart b/lib/screens/account/me/update.dart index 6cf0103..c275457 100644 --- a/lib/screens/account/me/update.dart +++ b/lib/screens/account/me/update.dart @@ -32,6 +32,7 @@ class UpdateProfileScreen extends HookConsumerWidget { .pickImage(source: ImageSource.gallery); if (result == null) return; if (!context.mounted) return; + hideLoadingModal(context); result = await cropImage( context, image: result, @@ -47,6 +48,7 @@ class UpdateProfileScreen extends HookConsumerWidget { return; } if (!context.mounted) return; + showLoadingModal(context); submitting.value = true; try { diff --git a/lib/screens/chat/chat.dart b/lib/screens/chat/chat.dart index 45a953f..52f92a1 100644 --- a/lib/screens/chat/chat.dart +++ b/lib/screens/chat/chat.dart @@ -254,7 +254,7 @@ class EditChatScreen extends HookConsumerWidget { return; } if (!context.mounted) return; - + hideLoadingModal(context); result = await cropImage( context, image: result, @@ -267,6 +267,7 @@ class EditChatScreen extends HookConsumerWidget { ); if (result == null) return; if (!context.mounted) return; + showLoadingModal(context); submitting.value = true; try { diff --git a/lib/screens/realm/realms.dart b/lib/screens/realm/realms.dart index 5874390..eb7fc00 100644 --- a/lib/screens/realm/realms.dart +++ b/lib/screens/realm/realms.dart @@ -165,6 +165,7 @@ class EditRealmScreen extends HookConsumerWidget { .pickImage(source: ImageSource.gallery); if (result == null) return; if (!context.mounted) return; + hideLoadingModal(context); result = await cropImage( context, image: result, @@ -180,7 +181,7 @@ class EditRealmScreen extends HookConsumerWidget { return; } if (!context.mounted) return; - + showLoadingModal(context); submitting.value = true; try { final baseUrl = ref.watch(serverUrlProvider);