Compare commits

...

4 Commits

Author SHA1 Message Date
16047a7d57 🚀 Launch 1.2.5+1 2024-09-27 00:20:04 +08:00
fdc68fc5e1 💄 Optimize attachment editor controls 2024-09-27 00:12:30 +08:00
bbee825cf4 ♻️ Refactor profile page code 2024-09-27 00:02:08 +08:00
2673c11046 Able to block anyone
💄 Optimize user profile page
2024-09-26 23:47:19 +08:00
11 changed files with 319 additions and 147 deletions

View File

@ -98,6 +98,8 @@
"accountFriendBlocked": "Friend blocklist", "accountFriendBlocked": "Friend blocklist",
"accountFriendListHint": "Swipe left to decline, right to approve", "accountFriendListHint": "Swipe left to decline, right to approve",
"accountFriendRequestSent": "Friend request sent, waiting for processing...", "accountFriendRequestSent": "Friend request sent, waiting for processing...",
"accountBlocked": "Account has been blocked",
"accountUnblocked": "Account has been unblocked",
"accountSuspended": "Account was suspended", "accountSuspended": "Account was suspended",
"accountSuspendedAt": "Account was suspended since @date", "accountSuspendedAt": "Account was suspended since @date",
"aspectRatio": "Aspect Ratio", "aspectRatio": "Aspect Ratio",
@ -457,5 +459,9 @@
"serviceStatus": "Status of Service", "serviceStatus": "Status of Service",
"firstBootTime": "First boot at @time", "firstBootTime": "First boot at @time",
"rateTheApp": "Rate the app", "rateTheApp": "Rate the app",
"rateTheAppDesc": "Rate Solar Network on the App Store to let us serve you better!" "rateTheAppDesc": "Rate Solar Network on the App Store to let us serve you better!",
"friendAdd": "Add as friend",
"blockUser": "Block user",
"unblockUser": "Unblock user",
"learnMoreAboutPerson": "Learn more about that person"
} }

View File

@ -98,6 +98,8 @@
"accountFriendBlocked": "好友黑名单", "accountFriendBlocked": "好友黑名单",
"accountFriendListHint": "左滑来拒绝,右滑来接受", "accountFriendListHint": "左滑来拒绝,右滑来接受",
"accountFriendRequestSent": "好友请求已发送,等待处理对方中……", "accountFriendRequestSent": "好友请求已发送,等待处理对方中……",
"accountBlocked": "已屏蔽账号",
"accountUnblocked": "已解除屏蔽账号",
"accountSuspended": "帐号被停用", "accountSuspended": "帐号被停用",
"accountSuspendedAt": "该帐号自 @date 起被停用", "accountSuspendedAt": "该帐号自 @date 起被停用",
"aspectRatio": "纵横比", "aspectRatio": "纵横比",
@ -453,5 +455,9 @@
"serviceStatus": "服务状态", "serviceStatus": "服务状态",
"firstBootTime": "首次启动于 @time", "firstBootTime": "首次启动于 @time",
"rateTheApp": "给应用评分", "rateTheApp": "给应用评分",
"rateTheAppDesc": "在 App Store 上给 Solar Network 评分,让我们更好地为您服务吧!" "rateTheAppDesc": "在 App Store 上给 Solar Network 评分,让我们更好地为您服务吧!",
"friendAdd": "添加好友",
"blockUser": "屏蔽用户",
"unblockUser": "解除屏蔽用户",
"learnMoreAboutPerson": "了解关于 TA 的更多"
} }

View File

@ -26,6 +26,19 @@ class RelationshipProvider extends GetxController {
return _friends.any((x) => x.relatedId == account.id); return _friends.any((x) => x.relatedId == account.id);
} }
Future<Relationship?> getRelationship(int relatedId) async {
final AuthProvider auth = Get.find();
final client = await auth.configureClient('auth');
final resp = await client.get('/users/me/relations/$relatedId');
if (resp.statusCode == 404) {
return null;
} else if (resp.statusCode != 200) {
throw RequestException(resp);
}
return Relationship.fromJson(resp.body);
}
Future<Response> listRelation() async { Future<Response> listRelation() async {
final AuthProvider auth = Get.find(); final AuthProvider auth = Get.find();
final client = await auth.configureClient('auth'); final client = await auth.configureClient('auth');
@ -38,7 +51,19 @@ class RelationshipProvider extends GetxController {
return client.get('/users/me/relations?status=$status'); return client.get('/users/me/relations?status=$status');
} }
Future<Response> makeFriend(String username) async { Future<Relationship?> blockUser(String username) async {
final AuthProvider auth = Get.find();
final client = await auth.configureClient('auth');
final resp =
await client.post('/users/me/relations/block?related=$username', {});
if (resp.statusCode != 200) {
throw RequestException(resp);
}
return Relationship.fromJson(resp.body);
}
Future<Relationship?> makeFriend(String username) async {
final AuthProvider auth = Get.find(); final AuthProvider auth = Get.find();
final client = await auth.configureClient('auth'); final client = await auth.configureClient('auth');
final resp = await client.post('/users/me/relations?related=$username', {}); final resp = await client.post('/users/me/relations?related=$username', {});
@ -46,7 +71,7 @@ class RelationshipProvider extends GetxController {
throw RequestException(resp); throw RequestException(resp);
} }
return resp; return Relationship.fromJson(resp.body);
} }
Future<Response> handleRelation( Future<Response> handleRelation(
@ -64,17 +89,17 @@ class RelationshipProvider extends GetxController {
return resp; return resp;
} }
Future<Response> editRelation(Relationship relationship, int status) async { Future<Relationship?> editRelation(int relatedId, int status) async {
final AuthProvider auth = Get.find(); final AuthProvider auth = Get.find();
final client = await auth.configureClient('auth'); final client = await auth.configureClient('auth');
final resp = await client.patch( final resp = await client.put(
'/users/me/relations/${relationship.relatedId}', '/users/me/relations/$relatedId',
{'status': status}, {'status': status},
); );
if (resp.statusCode != 200) { if (resp.statusCode != 200) {
throw RequestException(resp); throw RequestException(resp);
} }
return resp; return Relationship.fromJson(resp.body);
} }
} }

View File

@ -13,6 +13,7 @@ import 'package:solian/models/attachment.dart';
import 'package:solian/models/daily_sign.dart'; import 'package:solian/models/daily_sign.dart';
import 'package:solian/models/pagination.dart'; import 'package:solian/models/pagination.dart';
import 'package:solian/models/post.dart'; import 'package:solian/models/post.dart';
import 'package:solian/models/relations.dart';
import 'package:solian/models/subscription.dart'; import 'package:solian/models/subscription.dart';
import 'package:solian/providers/account_status.dart'; import 'package:solian/providers/account_status.dart';
import 'package:solian/providers/relation.dart'; import 'package:solian/providers/relation.dart';
@ -26,6 +27,7 @@ import 'package:solian/widgets/attachments/attachment_list.dart';
import 'package:solian/widgets/daily_sign/history_chart.dart'; import 'package:solian/widgets/daily_sign/history_chart.dart';
import 'package:solian/widgets/posts/post_list.dart'; import 'package:solian/widgets/posts/post_list.dart';
import 'package:solian/widgets/posts/post_warped_list.dart'; import 'package:solian/widgets/posts/post_warped_list.dart';
import 'package:solian/widgets/reports/abuse_report.dart';
import 'package:solian/widgets/sized_container.dart'; import 'package:solian/widgets/sized_container.dart';
class AccountProfilePage extends StatefulWidget { class AccountProfilePage extends StatefulWidget {
@ -50,6 +52,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
Account? _userinfo; Account? _userinfo;
Subscription? _subscription; Subscription? _subscription;
Relationship? _relationship;
List<Post> _pinnedPosts = List.empty(); List<Post> _pinnedPosts = List.empty();
List<DailySignRecord> _dailySignRecords = List.empty(); List<DailySignRecord> _dailySignRecords = List.empty();
int _totalUpvote = 0, _totalDownvote = 0; int _totalUpvote = 0, _totalDownvote = 0;
@ -61,6 +64,15 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
setState(() => _isSubscribing = false); setState(() => _isSubscribing = false);
} }
Future<void> _getRelationship() async {
setState(() => _isBusy = true);
final relations = Get.find<RelationshipProvider>();
_relationship = await relations.getRelationship(_userinfo!.id);
setState(() => _isBusy = false);
}
Future<void> _getUserinfo() async { Future<void> _getUserinfo() async {
setState(() => _isBusy = true); setState(() => _isBusy = true);
@ -120,6 +132,63 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
} }
} }
Future<void> _subscribeToUser() async {
setState(() => _isSubscribing = true);
_subscription =
await Get.find<SubscriptionProvider>().subscribeToUser(_userinfo!.id);
setState(() => _isSubscribing = false);
}
Future<void> _unsubscribeFromUser() async {
setState(() => _isSubscribing = true);
await Get.find<SubscriptionProvider>().unsubscribeFromUser(_userinfo!.id);
_subscription = null;
setState(() => _isSubscribing = false);
}
Future<void> _makeFriend() async {
setState(() => _isMakingFriend = true);
try {
_relationship = await _relationshipProvider.makeFriend(widget.name);
context.showSnackbar(
'accountFriendRequestSent'.tr,
);
} catch (e) {
context.showErrorDialog(e);
} finally {
setState(() => _isMakingFriend = false);
}
}
Future<void> _blockUser() async {
setState(() => _isMakingFriend = true);
try {
_relationship = await _relationshipProvider.blockUser(widget.name);
context.showSnackbar(
'accountBlocked'.tr,
);
} catch (e) {
context.showErrorDialog(e);
} finally {
setState(() => _isMakingFriend = false);
}
}
Future<void> _unblockUser() async {
setState(() => _isMakingFriend = true);
try {
_relationship =
await _relationshipProvider.editRelation(_userinfo!.id, 1);
context.showSnackbar(
'accountUnblocked'.tr,
);
} catch (e) {
context.showErrorDialog(e);
} finally {
setState(() => _isMakingFriend = false);
}
}
int get _userSocialCreditPoints { int get _userSocialCreditPoints {
return _totalUpvote * 2 - _totalDownvote + _postController.postTotal.value; return _totalUpvote * 2 - _totalDownvote + _postController.postTotal.value;
} }
@ -151,29 +220,13 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
}); });
_getUserinfo().then((_) { _getUserinfo().then((_) {
_getRelationship();
_getSubscription(); _getSubscription();
_getPinnedPosts(); _getPinnedPosts();
_getDailySignRecords(); _getDailySignRecords();
}); });
} }
Widget _buildStatisticsEntry(String label, String content) {
return Expanded(
child: Column(
children: [
Text(
label,
style: Theme.of(context).textTheme.bodySmall,
),
Text(
content,
style: Theme.of(context).textTheme.bodyLarge,
),
],
),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_isBusy || _userinfo == null) { if (_isBusy || _userinfo == null) {
@ -221,59 +274,31 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
), ),
), ),
if (_userinfo != null && _subscription == null) if (_userinfo != null && _subscription == null)
OutlinedButton( IconButton(
style: const ButtonStyle( style: const ButtonStyle(
visualDensity: visualDensity:
VisualDensity(horizontal: -4, vertical: -2), VisualDensity(horizontal: -4, vertical: -2),
), ),
onPressed: _isSubscribing onPressed: _isSubscribing ? null : _subscribeToUser,
? null icon: const Icon(Icons.add_circle_outline),
: () async { tooltip: 'subscribe'.tr,
setState(() => _isSubscribing = true);
_subscription =
await Get.find<SubscriptionProvider>()
.subscribeToUser(_userinfo!.id);
setState(() => _isSubscribing = false);
},
child: Text('subscribe'.tr),
) )
else if (_userinfo != null) else if (_userinfo != null)
OutlinedButton( IconButton(
style: const ButtonStyle( style: const ButtonStyle(
visualDensity: visualDensity:
VisualDensity(horizontal: -4, vertical: -2), VisualDensity(horizontal: -4, vertical: -2),
), ),
onPressed: _isSubscribing onPressed:
? null _isSubscribing ? null : _unsubscribeFromUser,
: () async { icon: const Icon(Icons.remove_circle_outline),
setState(() => _isSubscribing = true); tooltip: 'unsubscribe'.tr,
await Get.find<SubscriptionProvider>()
.unsubscribeFromUser(_userinfo!.id);
_subscription = null;
setState(() => _isSubscribing = false);
},
child: Text('unsubscribe'.tr),
), ),
if (_userinfo != null && if (_userinfo != null && _relationship == null)
!_relationshipProvider.hasFriend(_userinfo!))
IconButton( IconButton(
icon: const Icon(Icons.person_add), icon: const Icon(Icons.person_add),
onPressed: _isMakingFriend onPressed: _isMakingFriend ? null : _makeFriend,
? null tooltip: 'friendAdd'.tr,
: () async {
setState(() => _isMakingFriend = true);
try {
await _relationshipProvider
.makeFriend(widget.name);
context.showSnackbar(
'accountFriendRequestSent'.tr,
);
} catch (e) {
context.showErrorDialog(e);
} finally {
setState(() => _isMakingFriend = false);
}
},
) )
else else
const IconButton( const IconButton(
@ -300,8 +325,8 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
children: [ children: [
ListView( ListView(
padding: const EdgeInsets.only(top: 16, bottom: 16),
children: [ children: [
const Gap(16),
CenteredContainer( CenteredContainer(
child: AccountHeadingWidget( child: AccountHeadingWidget(
name: _userinfo!.name, name: _userinfo!.name,
@ -421,9 +446,82 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
), ),
), ),
).marginOnly( ).marginOnly(
right: 24, left: 12, bottom: 8, top: 24), right: 24,
left: 12,
bottom: 8,
top: 24,
),
) )
], ],
appendWidgets: [
Card(
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 4,
horizontal: 8,
),
width: double.maxFinite,
child: Wrap(
alignment: WrapAlignment.spaceAround,
children: [
TextButton.icon(
style: const ButtonStyle(
visualDensity: VisualDensity(
horizontal: -4,
vertical: -2,
),
),
onPressed: () {
showDialog(
context: context,
builder: (context) => AbuseReportDialog(
resourceId: 'user:${_userinfo!.id}',
),
);
},
icon: const Icon(
Icons.flag,
size: 16,
),
label: Text('reportAbuse'.tr),
),
if (_relationship?.status != 2)
TextButton.icon(
style: const ButtonStyle(
visualDensity: VisualDensity(
horizontal: -4,
vertical: -2,
),
),
onPressed:
_isMakingFriend ? null : _blockUser,
icon: const Icon(
Icons.block,
size: 16,
),
label: Text('blockUser'.tr),
)
else
TextButton.icon(
style: const ButtonStyle(
visualDensity: VisualDensity(
horizontal: -4,
vertical: -2,
),
),
onPressed:
_isMakingFriend ? null : _unblockUser,
icon: const Icon(
Icons.add_circle_outline,
size: 16,
),
label: Text('unblockUser'.tr),
),
],
),
),
),
],
), ),
), ),
], ],
@ -440,7 +538,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
_buildStatisticsEntry( _StatsWidget(
'totalSocialCreditPoints'.tr, 'totalSocialCreditPoints'.tr,
_userinfo != null _userinfo != null
? _userSocialCreditPoints.toString() ? _userSocialCreditPoints.toString()
@ -453,16 +551,16 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
Obx( Obx(
() => _buildStatisticsEntry( () => _StatsWidget(
'totalPostCount'.tr, 'totalPostCount'.tr,
_postController.postTotal.value.toString(), _postController.postTotal.value.toString(),
), ),
), ),
_buildStatisticsEntry( _StatsWidget(
'totalUpvote'.tr, 'totalUpvote'.tr,
_totalUpvote.toString(), _totalUpvote.toString(),
), ),
_buildStatisticsEntry( _StatsWidget(
'totalDownvote'.tr, 'totalDownvote'.tr,
_totalDownvote.toString(), _totalDownvote.toString(),
), ),
@ -560,3 +658,28 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
); );
} }
} }
class _StatsWidget extends StatelessWidget {
final String label;
final String content;
const _StatsWidget(this.label, this.content);
@override
Widget build(BuildContext context) {
return Expanded(
child: Column(
children: [
Text(
label,
style: Theme.of(context).textTheme.bodySmall,
),
Text(
content,
style: Theme.of(context).textTheme.bodyLarge,
),
],
),
);
}
}

View File

@ -23,6 +23,7 @@ class AccountHeadingWidget extends StatelessWidget {
final AccountProfile? profile; final AccountProfile? profile;
final List<AccountBadge>? badges; final List<AccountBadge>? badges;
final List<Widget>? extraWidgets; final List<Widget>? extraWidgets;
final List<Widget>? appendWidgets;
final Future<Response>? status; final Future<Response>? status;
final Function? onEditStatus; final Function? onEditStatus;
@ -39,6 +40,7 @@ class AccountHeadingWidget extends StatelessWidget {
this.profile, this.profile,
this.status, this.status,
this.extraWidgets, this.extraWidgets,
this.appendWidgets,
this.onEditStatus, this.onEditStatus,
}); });
@ -257,6 +259,7 @@ class AccountHeadingWidget extends StatelessWidget {
), ),
), ),
).paddingSymmetric(horizontal: 16), ).paddingSymmetric(horizontal: 16),
...?appendWidgets?.map((x) => x.paddingSymmetric(horizontal: 16)),
], ],
), ),
); );

View File

@ -106,10 +106,14 @@ class _AccountProfilePopupState extends State<AccountProfilePopup> {
extraWidgets: [ extraWidgets: [
Card( Card(
child: ListTile( child: ListTile(
leading: const Icon(
Icons.contact_page_outlined,
),
shape: const RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)), borderRadius: BorderRadius.all(Radius.circular(8)),
), ),
title: Text('visitProfilePage'.tr), title: Text('visitProfilePage'.tr),
subtitle: Text('learnMoreAboutPerson'.tr),
visualDensity: visualDensity:
const VisualDensity(horizontal: -4, vertical: -2), const VisualDensity(horizontal: -4, vertical: -2),
trailing: const Icon(Icons.chevron_right), trailing: const Icon(Icons.chevron_right),

View File

@ -28,42 +28,46 @@ class SilverRelativeList extends StatelessWidget {
showModalBottomSheet( showModalBottomSheet(
useRootNavigator: true, useRootNavigator: true,
isScrollControlled: true, isScrollControlled: true,
backgroundColor: Theme backgroundColor: Theme.of(context).colorScheme.surface,
.of(context)
.colorScheme
.surface,
context: context, context: context,
builder: (context) => builder: (context) => AccountProfilePopup(
AccountProfilePopup( name: element.related.name,
name: element.related.name, ),
),
); );
}, },
), ),
trailing: Row( trailing: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if(element.status != 1 && element.status != 3) if (element.status != 1 && element.status != 3)
IconButton( IconButton(
icon: const Icon(Icons.check), icon: const Icon(Icons.check),
onPressed: () { onPressed: () {
final RelationshipProvider provider = Get.find(); final RelationshipProvider provider = Get.find();
if (element.status == 0) { if (element.status == 0) {
provider.handleRelation(element, true).then((_) => onUpdate()); provider
.handleRelation(element, true)
.then((_) => onUpdate());
} else { } else {
provider.editRelation(element, 1).then((_) => onUpdate()); provider
.editRelation(element.relatedId, 1)
.then((_) => onUpdate());
} }
}, },
), ),
if(element.status != 2 && element.status != 3) if (element.status != 2 && element.status != 3)
IconButton( IconButton(
icon: const Icon(Icons.close), icon: const Icon(Icons.close),
onPressed: () { onPressed: () {
final RelationshipProvider provider = Get.find(); final RelationshipProvider provider = Get.find();
if (element.status == 0) { if (element.status == 0) {
provider.handleRelation(element, false).then((_) => onUpdate()); provider
.handleRelation(element, false)
.then((_) => onUpdate());
} else { } else {
provider.editRelation(element, 2).then((_) => onUpdate()); provider
.editRelation(element.relatedId, 2)
.then((_) => onUpdate());
} }
}, },
), ),

View File

@ -744,8 +744,8 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
return IgnorePointer( return IgnorePointer(
ignoring: _uploadController.isUploading.value, ignoring: _uploadController.isUploading.value,
child: Container( child: Container(
height: 64,
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border( border: Border(
top: BorderSide( top: BorderSide(
@ -754,67 +754,72 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
), ),
), ),
), ),
child: SingleChildScrollView( child: Wrap(
scrollDirection: Axis.horizontal, spacing: 8,
child: Wrap( runSpacing: 8,
spacing: 8, alignment: WrapAlignment.center,
runSpacing: 0, runAlignment: WrapAlignment.center,
alignment: WrapAlignment.center, children: [
runAlignment: WrapAlignment.center, if ((PlatformInfo.isDesktop ||
children: [ PlatformInfo.isIOS ||
if ((PlatformInfo.isDesktop || PlatformInfo.isWeb) &&
PlatformInfo.isIOS || !widget.imageOnly)
PlatformInfo.isWeb) && IconButton(
!widget.imageOnly) icon: const Icon(Icons.paste),
ElevatedButton.icon( tooltip: 'attachmentAddClipboard'.tr,
icon: const Icon(Icons.paste),
label: Text('attachmentAddClipboard'.tr),
style: const ButtonStyle(visualDensity: density),
onPressed: () => _pasteFileToUpload(),
),
ElevatedButton.icon(
icon: const Icon(Icons.add_photo_alternate),
label: Text('attachmentAddGalleryPhoto'.tr),
style: const ButtonStyle(visualDensity: density), style: const ButtonStyle(visualDensity: density),
onPressed: () => _pickPhotoToUpload(), color: Theme.of(context).colorScheme.primary,
onPressed: () => _pasteFileToUpload(),
), ),
if (!widget.imageOnly) IconButton(
ElevatedButton.icon( icon: const Icon(Icons.add_photo_alternate),
icon: const Icon(Icons.add_road), tooltip: 'attachmentAddGalleryPhoto'.tr,
label: Text('attachmentAddGalleryVideo'.tr), style: const ButtonStyle(visualDensity: density),
style: const ButtonStyle(visualDensity: density), color: Theme.of(context).colorScheme.primary,
onPressed: () => _pickVideoToUpload(), onPressed: () => _pickPhotoToUpload(),
), ),
ElevatedButton.icon( if (!widget.imageOnly)
icon: const Icon(Icons.photo_camera_back), IconButton(
label: Text('attachmentAddCameraPhoto'.tr), icon: const Icon(Icons.add_road),
tooltip: 'attachmentAddGalleryVideo'.tr,
style: const ButtonStyle(visualDensity: density), style: const ButtonStyle(visualDensity: density),
color: Theme.of(context).colorScheme.primary,
onPressed: () => _pickVideoToUpload(),
),
if (PlatformInfo.isMobile)
IconButton(
icon: const Icon(Icons.photo_camera_back),
tooltip: 'attachmentAddCameraPhoto'.tr,
style: const ButtonStyle(visualDensity: density),
color: Theme.of(context).colorScheme.primary,
onPressed: () => _takeMediaToUpload(false), onPressed: () => _takeMediaToUpload(false),
), ),
if (!widget.imageOnly) if (!widget.imageOnly && PlatformInfo.isMobile)
ElevatedButton.icon( IconButton(
icon: const Icon(Icons.video_camera_back_outlined), icon: const Icon(Icons.video_camera_back_outlined),
label: Text('attachmentAddCameraVideo'.tr), tooltip: 'attachmentAddCameraVideo'.tr,
style: const ButtonStyle(visualDensity: density), style: const ButtonStyle(visualDensity: density),
onPressed: () => _takeMediaToUpload(true), color: Theme.of(context).colorScheme.primary,
), onPressed: () => _takeMediaToUpload(true),
if (!widget.imageOnly) ),
ElevatedButton.icon( if (!widget.imageOnly)
icon: const Icon(Icons.file_present_rounded), IconButton(
label: Text('attachmentAddFile'.tr), icon: const Icon(Icons.file_present_rounded),
style: const ButtonStyle(visualDensity: density), tooltip: 'attachmentAddFile'.tr,
onPressed: () => _pickFileToUpload(), style: const ButtonStyle(visualDensity: density),
), color: Theme.of(context).colorScheme.primary,
if (!widget.imageOnly) onPressed: () => _pickFileToUpload(),
ElevatedButton.icon( ),
icon: const Icon(Icons.link), if (!widget.imageOnly)
label: Text('attachmentAddFile'.tr), IconButton(
style: const ButtonStyle(visualDensity: density), icon: const Icon(Icons.link),
onPressed: () => _linkAttachments(), tooltip: 'attachmentAddLink'.tr,
), style: const ButtonStyle(visualDensity: density),
], color: Theme.of(context).colorScheme.primary,
).paddingSymmetric(horizontal: 12), onPressed: () => _linkAttachments(),
), ),
],
).paddingSymmetric(horizontal: 12),
) )
.animate( .animate(
target: _uploadController.isUploading.value ? 0 : 1, target: _uploadController.isUploading.value ? 0 : 1,

View File

@ -12,8 +12,6 @@
<true/> <true/>
<key>com.apple.security.device.audio-input</key> <key>com.apple.security.device.audio-input</key>
<true/> <true/>
<key>com.apple.security.device.bluetooth</key>
<true/>
<key>com.apple.security.device.camera</key> <key>com.apple.security.device.camera</key>
<true/> <true/>
<key>com.apple.security.files.user-selected.read-only</key> <key>com.apple.security.files.user-selected.read-only</key>

View File

@ -10,8 +10,6 @@
<true/> <true/>
<key>com.apple.security.device.audio-input</key> <key>com.apple.security.device.audio-input</key>
<true/> <true/>
<key>com.apple.security.device.bluetooth</key>
<true/>
<key>com.apple.security.device.camera</key> <key>com.apple.security.device.camera</key>
<true/> <true/>
<key>com.apple.security.files.user-selected.read-only</key> <key>com.apple.security.files.user-selected.read-only</key>

View File

@ -2,7 +2,7 @@ name: solian
description: "The Solar Network App" description: "The Solar Network App"
publish_to: "none" publish_to: "none"
version: 1.2.4+1 version: 1.2.5+1
environment: environment:
sdk: ">=3.3.4 <4.0.0" sdk: ">=3.3.4 <4.0.0"