Compare commits
	
		
			4 Commits
		
	
	
		
			d4fbdd397e
			...
			7fbd4e9647
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7fbd4e9647 | |||
| 95d926b29f | |||
| f6cf6d0440 | |||
| e503c3f02f | 
| @@ -458,6 +458,7 @@ | ||||
|   "accountJoinedAt": "Joined at {}", | ||||
|   "accountBirthday": "Born on {}", | ||||
|   "accountBadge": "Badge", | ||||
|   "accountCheckInNoRecords": "No check-in records", | ||||
|   "badgeCompanyStaff": "Solsynth Staff", | ||||
|   "badgeSiteMigration": "Solar Network Native", | ||||
|   "accountStatus": "Status", | ||||
|   | ||||
| @@ -456,6 +456,7 @@ | ||||
|   "accountJoinedAt": "加入于 {}", | ||||
|   "accountBirthday": "出生于 {}", | ||||
|   "accountBadge": "徽章", | ||||
|   "accountCheckInNoRecords": "暂无运势记录", | ||||
|   "badgeCompanyStaff": "索尔辛茨士大夫 · 员工", | ||||
|   "badgeSiteMigration": "Solar Network 原住民", | ||||
|   "accountStatus": "状态", | ||||
|   | ||||
| @@ -173,7 +173,7 @@ PODS: | ||||
|   - in_app_review (2.0.0): | ||||
|     - Flutter | ||||
|   - Kingfisher (8.1.3) | ||||
|   - livekit_client (2.3.3): | ||||
|   - livekit_client (2.3.4): | ||||
|     - Flutter | ||||
|     - flutter_webrtc | ||||
|     - WebRTC-SDK (= 125.6422.06) | ||||
| @@ -391,7 +391,7 @@ SPEC CHECKSUMS: | ||||
|   image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 | ||||
|   in_app_review: a31b5257259646ea78e0e35fc914979b0031d011 | ||||
|   Kingfisher: f2af9028b16baf9dc6c07c570072bc41cbf009ef | ||||
|   livekit_client: 02cf2cc4357a655af12ccee70ff5596ae4e6feef | ||||
|   livekit_client: 4eaa7a2968fc7e7c57888f43d90394547cc8d9e9 | ||||
|   media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1 | ||||
|   media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a | ||||
|   media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e | ||||
|   | ||||
| @@ -247,6 +247,7 @@ class PostWriteController extends ChangeNotifier { | ||||
|       media.toFile()!, | ||||
|       place.$1, | ||||
|       place.$2, | ||||
|       analyzeNow: media.type == SnMediaType.image, | ||||
|       onProgress: (value) { | ||||
|         progress = value; | ||||
|         notifyListeners(); | ||||
|   | ||||
| @@ -154,10 +154,12 @@ class SnAttachmentProvider { | ||||
|     String rid, | ||||
|     String cid, { | ||||
|     Function(double progress)? onProgress, | ||||
|     bool analyzeNow = false, | ||||
|   }) async { | ||||
|     final resp = await _sn.client.post( | ||||
|       '/cgi/uc/fragments/$rid/$cid', | ||||
|       data: data, | ||||
|       queryParameters: {'analyzeNow': analyzeNow}, | ||||
|       options: Options(headers: {'Content-Type': 'application/octet-stream'}), | ||||
|       onSendProgress: (count, total) { | ||||
|         if (onProgress != null) { | ||||
| @@ -178,6 +180,7 @@ class SnAttachmentProvider { | ||||
|     SnAttachmentFragment place, | ||||
|     int chunkSize, { | ||||
|     Function(double progress)? onProgress, | ||||
|     bool analyzeNow = false, | ||||
|   }) async { | ||||
|     final Map<String, dynamic> chunks = place.fileChunks; | ||||
|     var completedTasks = 0; | ||||
| @@ -200,6 +203,7 @@ class SnAttachmentProvider { | ||||
|           data, | ||||
|           place.rid, | ||||
|           entry.key, | ||||
|           analyzeNow: analyzeNow, | ||||
|           onProgress: (progress) { | ||||
|             final overallProgress = (completedTasks + progress) / chunks.length; | ||||
|             onProgress?.call(overallProgress); | ||||
|   | ||||
| @@ -517,6 +517,12 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM | ||||
|               future: _getCheckInRecords(), | ||||
|               builder: (context, snapshot) { | ||||
|                 if (!snapshot.hasData) return const SizedBox.shrink(); | ||||
|                 if (snapshot.data!.length <= 1) { | ||||
|                   return Text( | ||||
|                     'accountCheckInNoRecords', | ||||
|                     textAlign: TextAlign.center, | ||||
|                   ).tr().fontWeight(FontWeight.bold).center().padding(horizontal: 20, vertical: 8); | ||||
|                 } | ||||
|                 final records = snapshot.data!; | ||||
|                 return SizedBox( | ||||
|                   width: double.infinity, | ||||
|   | ||||
| @@ -20,9 +20,11 @@ import 'package:uuid/uuid.dart'; | ||||
| class AttachmentItem extends StatelessWidget { | ||||
|   final SnAttachment? data; | ||||
|   final String? heroTag; | ||||
|   final BoxFit fit; | ||||
|  | ||||
|   const AttachmentItem({ | ||||
|     super.key, | ||||
|     this.fit = BoxFit.cover, | ||||
|     required this.data, | ||||
|     required this.heroTag, | ||||
|   }); | ||||
| @@ -43,7 +45,7 @@ class AttachmentItem extends StatelessWidget { | ||||
|           child: AutoResizeUniversalImage( | ||||
|             sn.getAttachmentUrl(data!.rid), | ||||
|             key: Key('attachment-${data!.rid}-$tag'), | ||||
|             fit: BoxFit.cover, | ||||
|             fit: fit, | ||||
|           ), | ||||
|         ); | ||||
|       case 'video': | ||||
| @@ -322,7 +324,9 @@ class _AttachmentItemContentVideoState extends State<_AttachmentItemContentVideo | ||||
|           MaterialDesktopCustomButton( | ||||
|             iconSize: 24, | ||||
|             onPressed: _toggleOriginal, | ||||
|             icon: _showOriginal ? const Icon(Symbols.high_quality, size: 24) : const Icon(Symbols.sd, size: 24), | ||||
|             icon: Builder(builder: (context) { | ||||
|               return _showOriginal ? const Icon(Symbols.high_quality, size: 24) : const Icon(Symbols.sd, size: 24); | ||||
|             }), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|   | ||||
| @@ -4,8 +4,8 @@ import 'package:collection/collection.dart'; | ||||
| import 'package:dismissible_page/dismissible_page.dart'; | ||||
| import 'package:flutter/gestures.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; | ||||
| import 'package:gap/gap.dart'; | ||||
| import 'package:responsive_framework/responsive_framework.dart'; | ||||
| import 'package:surface/types/attachment.dart'; | ||||
| import 'package:surface/widgets/attachment/attachment_zoom.dart'; | ||||
| import 'package:surface/widgets/attachment/attachment_item.dart'; | ||||
| @@ -14,8 +14,9 @@ import 'package:uuid/uuid.dart'; | ||||
| class AttachmentList extends StatefulWidget { | ||||
|   final List<SnAttachment?> data; | ||||
|   final bool bordered; | ||||
|   final bool gridded; | ||||
|   final bool noGrow; | ||||
|   final bool isFlatted; | ||||
|   final BoxFit fit; | ||||
|   final double? maxHeight; | ||||
|   final EdgeInsets? listPadding; | ||||
|  | ||||
| @@ -23,8 +24,9 @@ class AttachmentList extends StatefulWidget { | ||||
|     super.key, | ||||
|     required this.data, | ||||
|     this.bordered = false, | ||||
|     this.gridded = false, | ||||
|     this.noGrow = false, | ||||
|     this.isFlatted = false, | ||||
|     this.fit = BoxFit.cover, | ||||
|     this.maxHeight, | ||||
|     this.listPadding, | ||||
|   }); | ||||
| @@ -53,7 +55,6 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|         final constraints = BoxConstraints( | ||||
|           minWidth: 80, | ||||
|           maxHeight: widget.maxHeight ?? double.infinity, | ||||
|           maxWidth: layoutConstraints.maxWidth - 20, | ||||
|         ); | ||||
|  | ||||
|         if (widget.data.isEmpty) return const SizedBox.shrink(); | ||||
| @@ -66,52 +67,29 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|               } | ||||
|                   .toDouble(); | ||||
|  | ||||
|           return Container( | ||||
|             constraints: ResponsiveBreakpoints.of(context).largerThan(MOBILE) | ||||
|                 ? constraints.copyWith( | ||||
|                     maxWidth: math.min( | ||||
|                       constraints.maxWidth, | ||||
|                       kAttachmentMaxWidth, | ||||
|                     ), | ||||
|                   ) | ||||
|                 : null, | ||||
|             child: AspectRatio( | ||||
|               aspectRatio: singleAspectRatio, | ||||
|           return Padding( | ||||
|             padding: widget.listPadding ?? EdgeInsets.zero, | ||||
|             child: Container( | ||||
|               constraints: constraints, | ||||
|               width: double.infinity, | ||||
|               child: GestureDetector( | ||||
|                 child: Builder( | ||||
|                   builder: (context) { | ||||
|                     if (ResponsiveBreakpoints.of(context).largerThan(MOBILE) || widget.noGrow) { | ||||
|                       return Padding( | ||||
|                         // Single child list-like displaying | ||||
|                         padding: widget.listPadding ?? EdgeInsets.zero, | ||||
|                         child: Container( | ||||
|                           decoration: BoxDecoration( | ||||
|                             color: backgroundColor, | ||||
|                             border: Border(top: borderSide, bottom: borderSide), | ||||
|                             borderRadius: AttachmentList.kDefaultRadius, | ||||
|                           ), | ||||
|                           child: ClipRRect( | ||||
|                             borderRadius: AttachmentList.kDefaultRadius, | ||||
|                             child: AttachmentItem( | ||||
|                               data: widget.data[0], | ||||
|                               heroTag: heroTags[0], | ||||
|                             ), | ||||
|                           ), | ||||
|                         ), | ||||
|                       ); | ||||
|                     } | ||||
|  | ||||
|                     return Container( | ||||
|                       decoration: BoxDecoration( | ||||
|                         color: backgroundColor, | ||||
|                         border: Border(top: borderSide, bottom: borderSide), | ||||
|                       ), | ||||
|                 child: AspectRatio( | ||||
|                   aspectRatio: singleAspectRatio, | ||||
|                   child: Container( | ||||
|                     decoration: BoxDecoration( | ||||
|                       color: backgroundColor, | ||||
|                       border: Border.fromBorderSide(borderSide), | ||||
|                       borderRadius: AttachmentList.kDefaultRadius, | ||||
|                     ), | ||||
|                     child: ClipRRect( | ||||
|                       borderRadius: AttachmentList.kDefaultRadius, | ||||
|                       child: AttachmentItem( | ||||
|                         data: widget.data[0], | ||||
|                         heroTag: heroTags.first, | ||||
|                         heroTag: heroTags[0], | ||||
|                         fit: widget.fit, | ||||
|                       ), | ||||
|                     ); | ||||
|                   }, | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|                 onTap: () { | ||||
|                   if (widget.data.firstOrNull?.mediaType != SnMediaType.image) return; | ||||
| @@ -130,34 +108,53 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|           ); | ||||
|         } | ||||
|  | ||||
|         if (widget.isFlatted) { | ||||
|           return Wrap( | ||||
|             spacing: 4, | ||||
|             runSpacing: 4, | ||||
|             children: widget.data | ||||
|                 .mapIndexed( | ||||
|                   (idx, ele) => AspectRatio( | ||||
|                     aspectRatio: (ele?.data['ratio'] ?? 1).toDouble(), | ||||
|                     child: Container( | ||||
|                       decoration: BoxDecoration( | ||||
|                         color: backgroundColor, | ||||
|                         border: Border( | ||||
|                           top: borderSide, | ||||
|                           bottom: borderSide, | ||||
|         if (widget.gridded) { | ||||
|           return Padding( | ||||
|             padding: widget.listPadding ?? EdgeInsets.zero, | ||||
|             child: Container( | ||||
|               decoration: BoxDecoration( | ||||
|                 color: backgroundColor, | ||||
|                 border: Border( | ||||
|                   top: borderSide, | ||||
|                   bottom: borderSide, | ||||
|                 ), | ||||
|                 borderRadius: AttachmentList.kDefaultRadius, | ||||
|               ), | ||||
|               child: ClipRRect( | ||||
|                 borderRadius: AttachmentList.kDefaultRadius, | ||||
|                 child: StaggeredGrid.count( | ||||
|                   crossAxisCount: math.min(widget.data.length, 2), | ||||
|                   crossAxisSpacing: 4, | ||||
|                   mainAxisSpacing: 4, | ||||
|                   children: widget.data | ||||
|                       .mapIndexed( | ||||
|                         (idx, ele) => GestureDetector( | ||||
|                           child: Container( | ||||
|                             constraints: constraints, | ||||
|                             child: AttachmentItem( | ||||
|                               data: ele, | ||||
|                               heroTag: heroTags[idx], | ||||
|                               fit: widget.fit, | ||||
|                             ), | ||||
|                           ), | ||||
|                           onTap: () { | ||||
|                             if (widget.data[idx]!.mediaType != SnMediaType.image) return; | ||||
|                             context.pushTransparentRoute( | ||||
|                               AttachmentZoomView( | ||||
|                                 data: widget.data.where((ele) => ele != null).cast(), | ||||
|                                 initialIndex: idx, | ||||
|                                 heroTags: heroTags, | ||||
|                               ), | ||||
|                               backgroundColor: Colors.black.withOpacity(0.7), | ||||
|                               rootNavigator: true, | ||||
|                             ); | ||||
|                           }, | ||||
|                         ), | ||||
|                         borderRadius: AttachmentList.kDefaultRadius, | ||||
|                       ), | ||||
|                       child: ClipRRect( | ||||
|                         borderRadius: AttachmentList.kDefaultRadius, | ||||
|                         child: AttachmentItem( | ||||
|                           data: ele, | ||||
|                           heroTag: heroTags[idx], | ||||
|                         ), | ||||
|                       ), | ||||
|                     ), | ||||
|                   ), | ||||
|                 ) | ||||
|                 .toList(), | ||||
|                       ) | ||||
|                       .toList(), | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|           ); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -159,6 +159,7 @@ class ChatMessage extends StatelessWidget { | ||||
|               AttachmentList( | ||||
|                 data: data.preload!.attachments!, | ||||
|                 bordered: true, | ||||
|                 gridded: true, | ||||
|                 noGrow: true, | ||||
|                 maxHeight: 520, | ||||
|                 listPadding: const EdgeInsets.only(top: 8), | ||||
|   | ||||
| @@ -83,6 +83,7 @@ class ChatMessageInputState extends State<ChatMessageInput> { | ||||
|           media.toFile()!, | ||||
|           place.$1, | ||||
|           place.$2, | ||||
|           analyzeNow: media.type == SnMediaType.image, | ||||
|           onProgress: (progress) { | ||||
|             // Calculate overall progress for attachments | ||||
|             setState(() { | ||||
|   | ||||
| @@ -251,7 +251,9 @@ class PostItem extends StatelessWidget { | ||||
|           AttachmentList( | ||||
|             data: data.preload!.attachments!, | ||||
|             bordered: true, | ||||
|             maxHeight: 560, | ||||
|             gridded: true, | ||||
|             maxHeight: showFullPost ? null : 480, | ||||
|             fit: showFullPost ? BoxFit.cover : BoxFit.contain, | ||||
|             listPadding: const EdgeInsets.symmetric(horizontal: 12), | ||||
|           ), | ||||
|         if (data.body['content'] != null) | ||||
| @@ -332,12 +334,11 @@ class PostShareImageWidget extends StatelessWidget { | ||||
|             _PostQuoteContent( | ||||
|               child: data.repostTo!, | ||||
|               isRelativeDate: false, | ||||
|               isFlatted: true, | ||||
|             ).padding(horizontal: 16, bottom: 8), | ||||
|           if (data.type != 'article' && (data.preload?.attachments?.isNotEmpty ?? false)) | ||||
|             AttachmentList( | ||||
|               data: data.preload!.attachments!, | ||||
|               isFlatted: true, | ||||
|               gridded: true, | ||||
|             ).padding(horizontal: 16, bottom: 8), | ||||
|           Column( | ||||
|             crossAxisAlignment: CrossAxisAlignment.start, | ||||
| @@ -884,11 +885,9 @@ class _PostContentBody extends StatelessWidget { | ||||
| class _PostQuoteContent extends StatelessWidget { | ||||
|   final SnPost child; | ||||
|   final bool isRelativeDate; | ||||
|   final bool isFlatted; | ||||
|  | ||||
|   const _PostQuoteContent({ | ||||
|     this.isRelativeDate = true, | ||||
|     this.isFlatted = false, | ||||
|     required this.child, | ||||
|   }); | ||||
|  | ||||
| @@ -930,12 +929,14 @@ class _PostQuoteContent extends StatelessWidget { | ||||
|                 ), | ||||
|                 child: AttachmentList( | ||||
|                   data: child.preload!.attachments!, | ||||
|                   isFlatted: isFlatted, | ||||
|                   maxHeight: 360, | ||||
|                   fit: BoxFit.contain, | ||||
|                   gridded: true, | ||||
|                   listPadding: const EdgeInsets.symmetric(horizontal: 12), | ||||
|                 ), | ||||
|               ).padding( | ||||
|                 top: 8, | ||||
|                 bottom: (child.preload?.attachments?.length ?? 0) > 1 ? 12 : 0, | ||||
|                 bottom: 12, | ||||
|               ) | ||||
|             else | ||||
|               const Gap(8), | ||||
|   | ||||
| @@ -134,7 +134,7 @@ PODS: | ||||
|     - GoogleUtilities/Privacy | ||||
|   - in_app_review (2.0.0): | ||||
|     - FlutterMacOS | ||||
|   - livekit_client (2.3.3): | ||||
|   - livekit_client (2.3.4): | ||||
|     - flutter_webrtc | ||||
|     - FlutterMacOS | ||||
|     - WebRTC-SDK (= 125.6422.06) | ||||
| @@ -304,7 +304,7 @@ SPEC CHECKSUMS: | ||||
|   GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 | ||||
|   GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d | ||||
|   in_app_review: a6a031b9acd03c7d103e341aa334adf2c493fb93 | ||||
|   livekit_client: 8b1b90a6f2445d127a018ce93cc8cf6d8ab62982 | ||||
|   livekit_client: b7ab91e79e657d7d40da16cb2f90d517cb72d406 | ||||
|   media_kit_libs_macos_video: b3e2bbec2eef97c285f2b1baa7963c67c753fb82 | ||||
|   media_kit_native_event_loop: 81fd5b45192b72f8b5b69eaf5b540f45777eb8d5 | ||||
|   media_kit_video: c75b07f14d59706c775778e4dd47dd027de8d1e5 | ||||
|   | ||||
| @@ -1086,10 +1086,10 @@ packages: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: livekit_client | ||||
|       sha256: a3ff529fe6745ee40cdedcd021d81c4a6ad946dd495e782596f2856eeeabc739 | ||||
|       sha256: "7cdeb3eaeec7fb70a4cf88d9caabccbef9e3bd5f0b23c086320bc5c9acb2770b" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.3.3" | ||||
|     version: "2.3.4" | ||||
|   logging: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|   | ||||
| @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev | ||||
| # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html | ||||
| # In Windows, build-name is used as the major, minor, and patch parts | ||||
| # of the product and file versions while build-number is used as the build suffix. | ||||
| version: 2.2.1+40 | ||||
| version: 2.2.1+41 | ||||
|  | ||||
| environment: | ||||
|   sdk: ^3.5.4 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user