From cead09f3aa12129a38dc2aa95811935a1d052b69 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 5 Apr 2025 16:11:09 +0800 Subject: [PATCH] :sparkles: Editable content rating --- android/app/src/main/AndroidManifest.xml | 9 +- assets/translations/en-US.json | 7 +- assets/translations/zh-CN.json | 5 +- ios/Podfile.lock | 4 +- lib/providers/sn_attachment.dart | 17 +++ .../pending_attachment_actions.dart | 19 +++ .../attachment/pending_attachment_rating.dart | 108 ++++++++++++++++++ pubspec.lock | 12 +- pubspec.yaml | 2 +- 9 files changed, 167 insertions(+), 16 deletions(-) create mode 100644 lib/widgets/attachment/pending_attachment_rating.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index e15902f..bdcd15c 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -9,9 +9,10 @@ - - - + + + - + \ No newline at end of file diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json index 35f0db8..61ba31c 100644 --- a/assets/translations/en-US.json +++ b/assets/translations/en-US.json @@ -876,7 +876,7 @@ "appInitNetwork": "Initializing Network", "appInitUserdata": "Initializing User Data", "appInitWebsocket": "Establishing Solar Link", - "appInitNotification": "Initializing Push Notifications", + "appInitNotification": "Initializing Push Notifications", "appInitKeyPair": "Initializing Key Pairs", "appInitStickers": "Initializing Stickers", "appInitUserDirectory": "Initializing User Directory", @@ -951,5 +951,8 @@ "splashScreenCaption": "Trying to establishing connection with HyperNet™", "attachmentEditor": "Attachment editor", "attachmentEditorUnUploadHint": "This attachment is not uploaded, metadata editing is unavailable, and you can crop this attachment.", - "attachmentEditorUploadHint": "This attachment is uploaded." + "attachmentEditorUploadHint": "This attachment is uploaded.", + "attachmentRating": "Rating", + "fieldAttachmentRating": "Content Rating", + "fieldAttachmentQuality": "Quality Rating" } diff --git a/assets/translations/zh-CN.json b/assets/translations/zh-CN.json index edf07ba..11acc9c 100644 --- a/assets/translations/zh-CN.json +++ b/assets/translations/zh-CN.json @@ -948,5 +948,8 @@ "splashScreenCaption": "正在尝试与 HyperNet™ 取得太阳链连接", "attachmentEditor": "附件编辑器", "attachmentEditorUnUploadHint": "该附件未上传,元数据编辑不可用,同时你可以裁剪本附件。", - "attachmentEditorUploadHint": "该附件已上传。" + "attachmentEditorUploadHint": "该附件已上传。", + "attachmentRating": "评级", + "fieldAttachmentRating": "内容分级", + "fieldAttachmentQuality": "质量评分" } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index b97b491..c3cdd4c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -185,7 +185,7 @@ PODS: - in_app_review (2.0.0): - Flutter - Kingfisher (8.3.1) - - livekit_client (2.4.1): + - livekit_client (2.4.2): - Flutter - flutter_webrtc - WebRTC-SDK (= 125.6422.06) @@ -446,7 +446,7 @@ SPEC CHECKSUMS: image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a in_app_review: 5596fe56fab799e8edb3561c03d053363ab13457 Kingfisher: 3204d23de16b5ea53541c44ca5a8efb55741dec3 - livekit_client: 08755cabfa4da4ed455642f460cfbb39bc518070 + livekit_client: 78bb2ff0d409268886804151d4fc9e006093e6ce livekit_noise_filter: a26aeb1c1eae6db0a023fd2f6ea3ff108c3ecbb0 LiveKitKrispNoiseFilter: efe418ceca28163ace0ff222bd2cc02384645d84 media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854 diff --git a/lib/providers/sn_attachment.dart b/lib/providers/sn_attachment.dart index bccb7bd..b3c864e 100644 --- a/lib/providers/sn_attachment.dart +++ b/lib/providers/sn_attachment.dart @@ -311,6 +311,23 @@ class SnAttachmentProvider { return out; } + Future rateOne( + SnAttachment item, { + int? content, + int? quality, + }) async { + final resp = await _sn.client.put( + '/cgi/uc/attachments/${item.id}/rating', + data: { + 'content_rating': content ?? item.contentRating, + 'quality_rating': quality ?? item.qualityRating, + }, + ); + final out = SnAttachment.fromJson(resp.data); + _saveToLocal([out]); + return out; + } + Future _saveToLocal(Iterable out) async { for (final ele in out) { if (!ele.isAnalyzed || ele.destination == 0) continue; diff --git a/lib/widgets/attachment/pending_attachment_actions.dart b/lib/widgets/attachment/pending_attachment_actions.dart index 930cdca..ef4b31a 100644 --- a/lib/widgets/attachment/pending_attachment_actions.dart +++ b/lib/widgets/attachment/pending_attachment_actions.dart @@ -21,6 +21,7 @@ import 'package:surface/widgets/attachment/attachment_zoom.dart'; import 'package:surface/widgets/attachment/pending_attachment_alt.dart'; import 'package:surface/widgets/attachment/pending_attachment_boost.dart'; import 'package:surface/widgets/attachment/pending_attachment_compress.dart'; +import 'package:surface/widgets/attachment/pending_attachment_rating.dart'; import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/loading_indicator.dart'; @@ -146,6 +147,17 @@ class _PendingAttachmentActionSheetState Navigator.pop(context, PostWriteMedia(result)); } + Future _setRating() async { + final result = await showDialog( + context: context, + builder: (context) => PendingAttachmentRateDialog(media: widget.media), + ); + if (result == null) return; + + if (!mounted) return; + Navigator.pop(context, PostWriteMedia(result)); + } + @override Widget build(BuildContext context) { return Column( @@ -288,6 +300,13 @@ class _PendingAttachmentActionSheetState title: Text('attachmentSetAlt').tr(), onTap: () => _setAlt(), ), + ListTile( + minTileHeight: 48, + leading: const Icon(Symbols.star), + contentPadding: EdgeInsets.symmetric(horizontal: 24), + title: Text('attachmentRating').tr(), + onTap: () => _setRating(), + ), ListTile( minTileHeight: 48, leading: const Icon(Symbols.link_off), diff --git a/lib/widgets/attachment/pending_attachment_rating.dart b/lib/widgets/attachment/pending_attachment_rating.dart new file mode 100644 index 0000000..3d558a1 --- /dev/null +++ b/lib/widgets/attachment/pending_attachment_rating.dart @@ -0,0 +1,108 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:surface/controllers/post_write_controller.dart'; +import 'package:surface/providers/sn_attachment.dart'; +import 'package:surface/widgets/dialog.dart'; + +class PendingAttachmentRateDialog extends StatefulWidget { + final PostWriteMedia media; + const PendingAttachmentRateDialog({super.key, required this.media}); + + @override + State createState() => + _PendingAttachmentRateDialogState(); +} + +class _PendingAttachmentRateDialogState + extends State { + final _ratingController = TextEditingController(); + final _qualityController = TextEditingController(); + + @override + void initState() { + super.initState(); + _qualityController.text = widget.media.attachment!.qualityRating.toString(); + _ratingController.text = widget.media.attachment!.contentRating.toString(); + } + + bool _isBusy = false; + + Future _performAction() async { + if (_isBusy) return; + + setState(() => _isBusy = true); + + try { + final attach = context.read(); + final result = await attach.rateOne( + widget.media.attachment!, + quality: int.tryParse(_qualityController.text), + content: int.tryParse(_ratingController.text), + ); + if (!mounted) return; + attach.putCache([result]); + Navigator.pop(context, result); + } catch (err) { + if (!mounted) return; + context.showErrorDialog(err); + setState(() => _isBusy = false); + } + } + + @override + void dispose() { + _qualityController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text('attachmentRating').tr(), + content: Column( + spacing: 12, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextField( + controller: _ratingController, + decoration: InputDecoration( + labelText: 'fieldAttachmentRating'.tr(), + border: const OutlineInputBorder(), + isDense: true, + helperText: '3 - 21', + ), + keyboardType: TextInputType.number, + onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), + ), + TextField( + controller: _qualityController, + decoration: InputDecoration( + labelText: 'fieldAttachmentQuality'.tr(), + border: const OutlineInputBorder(), + isDense: true, + helperText: '0 - 5', + ), + keyboardType: TextInputType.number, + onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), + ), + ], + ), + actions: [ + TextButton( + onPressed: _isBusy + ? null + : () { + Navigator.pop(context); + }, + child: Text('dialogDismiss'.tr()), + ), + TextButton( + onPressed: _isBusy ? null : () => _performAction(), + child: Text('dialogConfirm'.tr()), + ), + ], + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 2f499f7..c671507 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1001,10 +1001,10 @@ packages: dependency: "direct main" description: name: flutter_webrtc - sha256: b832dc76c0d1577f14aaf35e9c38d4ed7667cbc89c492b7bf4505d8d5f62e08b + sha256: "4f0d6e248f178e617f249b6a2f432b5981e3300c2896fc8d476fc2aa1f525547" url: "https://pub.dev" source: hosted - version: "0.12.12+hotfix.1" + version: "0.13.1" freezed: dependency: "direct dev" description: @@ -1377,18 +1377,18 @@ packages: dependency: "direct main" description: name: livekit_client - sha256: "7f489fa415253d8d99c649b7efc95a733c5e5ac38dcfb02362ced99feb139376" + sha256: caff013563dc034b9858380318dd341c8bab453fc1a033405c3ab8677d91225c url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2+hotfix.1" livekit_noise_filter: dependency: "direct main" description: name: livekit_noise_filter - sha256: "398bfd1cc63ada9dee9fd7ea415e2fc1e51e091a6d217aad3649b882c35c7fcb" + sha256: "667fd572bc45f18f09cf9764b6d323ee816905fd3afaf40e1e701ea2de8fd567" url: "https://pub.dev" source: hosted - version: "0.1.0" + version: "0.1.0+hotfix.1" local_notifier: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 3d7f53c..1b109e3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -113,7 +113,7 @@ dependencies: version: ^3.0.2 flutter_colorpicker: ^1.1.0 fl_chart: ^0.70.0 - flutter_webrtc: ^0.12.5+hotfix.1 + flutter_webrtc: ^0.13.1 slide_countdown: ^2.0.2 video_compress: ^3.1.3 cached_network_image: ^3.4.1