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