✨ Post reactions
This commit is contained in:
parent
db7fef4a72
commit
e4e562918c
@ -94,5 +94,14 @@
|
|||||||
"edited": "Edited",
|
"edited": "Edited",
|
||||||
"addVideo": "Add video",
|
"addVideo": "Add video",
|
||||||
"addPhoto": "Add photo",
|
"addPhoto": "Add photo",
|
||||||
"createDirectMessage": "New direct message"
|
"createDirectMessage": "New direct message",
|
||||||
|
"react": "React",
|
||||||
|
"reactions": {
|
||||||
|
"zero": "Reactions",
|
||||||
|
"one": "{} reaction",
|
||||||
|
"other": "{} reactions"
|
||||||
|
},
|
||||||
|
"reactionPositive": "Postive",
|
||||||
|
"reactionNegative": "Negative",
|
||||||
|
"reactionNeutral": "Neutral"
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,6 @@ PODS:
|
|||||||
- flutter_inappwebview_ios/Core (0.0.1):
|
- flutter_inappwebview_ios/Core (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- OrderedSet (~> 6.0.3)
|
- OrderedSet (~> 6.0.3)
|
||||||
- flutter_keyboard_visibility_temp_fork (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- flutter_platform_alert (0.0.1):
|
- flutter_platform_alert (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_udid (0.0.1):
|
- flutter_udid (0.0.1):
|
||||||
@ -130,8 +128,6 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- PromisesObjC (2.4.0)
|
- PromisesObjC (2.4.0)
|
||||||
- quill_native_bridge_ios (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- SAMKeychain (1.5.3)
|
- SAMKeychain (1.5.3)
|
||||||
- SDWebImage (5.21.0):
|
- SDWebImage (5.21.0):
|
||||||
- SDWebImage/Core (= 5.21.0)
|
- SDWebImage/Core (= 5.21.0)
|
||||||
@ -181,7 +177,6 @@ DEPENDENCIES:
|
|||||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
||||||
- flutter_keyboard_visibility_temp_fork (from `.symlinks/plugins/flutter_keyboard_visibility_temp_fork/ios`)
|
|
||||||
- flutter_platform_alert (from `.symlinks/plugins/flutter_platform_alert/ios`)
|
- flutter_platform_alert (from `.symlinks/plugins/flutter_platform_alert/ios`)
|
||||||
- flutter_udid (from `.symlinks/plugins/flutter_udid/ios`)
|
- flutter_udid (from `.symlinks/plugins/flutter_udid/ios`)
|
||||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||||
@ -191,7 +186,6 @@ DEPENDENCIES:
|
|||||||
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
|
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
|
||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
- quill_native_bridge_ios (from `.symlinks/plugins/quill_native_bridge_ios/ios`)
|
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
||||||
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
||||||
@ -233,8 +227,6 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_inappwebview_ios:
|
flutter_inappwebview_ios:
|
||||||
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
||||||
flutter_keyboard_visibility_temp_fork:
|
|
||||||
:path: ".symlinks/plugins/flutter_keyboard_visibility_temp_fork/ios"
|
|
||||||
flutter_platform_alert:
|
flutter_platform_alert:
|
||||||
:path: ".symlinks/plugins/flutter_platform_alert/ios"
|
:path: ".symlinks/plugins/flutter_platform_alert/ios"
|
||||||
flutter_udid:
|
flutter_udid:
|
||||||
@ -251,8 +243,6 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||||
path_provider_foundation:
|
path_provider_foundation:
|
||||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
quill_native_bridge_ios:
|
|
||||||
:path: ".symlinks/plugins/quill_native_bridge_ios/ios"
|
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
sqflite_darwin:
|
sqflite_darwin:
|
||||||
@ -282,7 +272,6 @@ SPEC CHECKSUMS:
|
|||||||
FirebaseMessaging: 2b9f56aa4ed286e1f0ce2ee1d413aabb8f9f5cb9
|
FirebaseMessaging: 2b9f56aa4ed286e1f0ce2ee1d413aabb8f9f5cb9
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||||
flutter_keyboard_visibility_temp_fork: 95b2d534bacf6ac62e7fcbe5c2a9e2c2a17ce06f
|
|
||||||
flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3
|
flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3
|
||||||
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
@ -297,7 +286,6 @@ SPEC CHECKSUMS:
|
|||||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
quill_native_bridge_ios: f47af4b14e7757968486641656c5d23250cee521
|
|
||||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||||
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
|
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
|
||||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||||
|
@ -6,7 +6,6 @@ import 'package:firebase_core/firebase_core.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:flutter_quill/flutter_quill.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:image_picker_android/image_picker_android.dart';
|
import 'package:image_picker_android/image_picker_android.dart';
|
||||||
import 'package:island/firebase_options.dart';
|
import 'package:island/firebase_options.dart';
|
||||||
@ -101,7 +100,6 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
supportedLocales: context.supportedLocales,
|
supportedLocales: context.supportedLocales,
|
||||||
localizationsDelegates: [
|
localizationsDelegates: [
|
||||||
...context.localizationDelegates,
|
...context.localizationDelegates,
|
||||||
FlutterQuillLocalizations.delegate,
|
|
||||||
], // this contains the cupertino one
|
], // this contains the cupertino one
|
||||||
locale: context.locale,
|
locale: context.locale,
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
|
@ -14,7 +14,7 @@ abstract class SnPost with _$SnPost {
|
|||||||
required DateTime? editedAt,
|
required DateTime? editedAt,
|
||||||
required DateTime publishedAt,
|
required DateTime publishedAt,
|
||||||
required int visibility,
|
required int visibility,
|
||||||
required List<dynamic>? content,
|
required String? content,
|
||||||
required int type,
|
required int type,
|
||||||
required Map<String, dynamic>? meta,
|
required Map<String, dynamic>? meta,
|
||||||
required int viewsUnique,
|
required int viewsUnique,
|
||||||
@ -29,6 +29,7 @@ abstract class SnPost with _$SnPost {
|
|||||||
required dynamic forwardedPost,
|
required dynamic forwardedPost,
|
||||||
required List<SnCloudFile> attachments,
|
required List<SnCloudFile> attachments,
|
||||||
required SnPublisher publisher,
|
required SnPublisher publisher,
|
||||||
|
@Default({}) Map<String, int> reactionsCount,
|
||||||
required List<dynamic> reactions,
|
required List<dynamic> reactions,
|
||||||
required List<dynamic> tags,
|
required List<dynamic> tags,
|
||||||
required List<dynamic> categories,
|
required List<dynamic> categories,
|
||||||
@ -62,3 +63,23 @@ abstract class SnPublisher with _$SnPublisher {
|
|||||||
factory SnPublisher.fromJson(Map<String, dynamic> json) =>
|
factory SnPublisher.fromJson(Map<String, dynamic> json) =>
|
||||||
_$SnPublisherFromJson(json);
|
_$SnPublisherFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class ReactInfo with _$ReactInfo {
|
||||||
|
const factory ReactInfo({required String icon, required int attitude}) =
|
||||||
|
_ReactInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Map<String, ReactInfo> kReactionTemplates = {
|
||||||
|
'thumb_up': ReactInfo(icon: '👍', attitude: 0),
|
||||||
|
'thumb_down': ReactInfo(icon: '👎', attitude: 2),
|
||||||
|
'just_okay': ReactInfo(icon: '😅', attitude: 1),
|
||||||
|
'cry': ReactInfo(icon: '😭', attitude: 1),
|
||||||
|
'confuse': ReactInfo(icon: '🧐', attitude: 1),
|
||||||
|
'clap': ReactInfo(icon: '👏', attitude: 0),
|
||||||
|
'laugh': ReactInfo(icon: '😂', attitude: 0),
|
||||||
|
'angry': ReactInfo(icon: '😡', attitude: 2),
|
||||||
|
'party': ReactInfo(icon: '🎉', attitude: 0),
|
||||||
|
'pray': ReactInfo(icon: '🙏', attitude: 0),
|
||||||
|
'heart': ReactInfo(icon: '❤️', attitude: 0),
|
||||||
|
};
|
||||||
|
@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnPost {
|
mixin _$SnPost {
|
||||||
|
|
||||||
int get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime get publishedAt; int get visibility; List<dynamic>? get content; int get type; Map<String, dynamic>? get meta; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; dynamic get threadedPostId; dynamic get threadedPost; dynamic get repliedPostId; dynamic get repliedPost; dynamic get forwardedPostId; dynamic get forwardedPost; List<SnCloudFile> get attachments; SnPublisher get publisher; List<dynamic> get reactions; List<dynamic> get tags; List<dynamic> get categories; List<dynamic> get collections; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
int get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime get publishedAt; int get visibility; String? get content; int get type; Map<String, dynamic>? get meta; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; dynamic get threadedPostId; dynamic get threadedPost; dynamic get repliedPostId; dynamic get repliedPost; dynamic get forwardedPostId; dynamic get forwardedPost; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; List<dynamic> get reactions; List<dynamic> get tags; List<dynamic> get categories; List<dynamic> get collections; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnPost
|
/// Create a copy of SnPost
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@ -29,16 +29,16 @@ $SnPostCopyWith<SnPost> get copyWith => _$SnPostCopyWithImpl<SnPost>(this as SnP
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&const DeepCollectionEquality().equals(other.content, content)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&const DeepCollectionEquality().equals(other.threadedPostId, threadedPostId)&&const DeepCollectionEquality().equals(other.threadedPost, threadedPost)&&const DeepCollectionEquality().equals(other.repliedPostId, repliedPostId)&&const DeepCollectionEquality().equals(other.repliedPost, repliedPost)&&const DeepCollectionEquality().equals(other.forwardedPostId, forwardedPostId)&&const DeepCollectionEquality().equals(other.forwardedPost, forwardedPost)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&const DeepCollectionEquality().equals(other.threadedPostId, threadedPostId)&&const DeepCollectionEquality().equals(other.threadedPost, threadedPost)&&const DeepCollectionEquality().equals(other.repliedPostId, repliedPostId)&&const DeepCollectionEquality().equals(other.repliedPost, repliedPost)&&const DeepCollectionEquality().equals(other.forwardedPostId, forwardedPostId)&&const DeepCollectionEquality().equals(other.forwardedPost, forwardedPost)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,const DeepCollectionEquality().hash(content),type,const DeepCollectionEquality().hash(meta),viewsUnique,viewsTotal,upvotes,downvotes,const DeepCollectionEquality().hash(threadedPostId),const DeepCollectionEquality().hash(threadedPost),const DeepCollectionEquality().hash(repliedPostId),const DeepCollectionEquality().hash(repliedPost),const DeepCollectionEquality().hash(forwardedPostId),const DeepCollectionEquality().hash(forwardedPost),const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),createdAt,updatedAt,deletedAt]);
|
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,type,const DeepCollectionEquality().hash(meta),viewsUnique,viewsTotal,upvotes,downvotes,const DeepCollectionEquality().hash(threadedPostId),const DeepCollectionEquality().hash(threadedPost),const DeepCollectionEquality().hash(repliedPostId),const DeepCollectionEquality().hash(repliedPost),const DeepCollectionEquality().hash(forwardedPostId),const DeepCollectionEquality().hash(forwardedPost),const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),createdAt,updatedAt,deletedAt]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, attachments: $attachments, publisher: $publisher, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ abstract mixin class $SnPostCopyWith<$Res> {
|
|||||||
factory $SnPostCopyWith(SnPost value, $Res Function(SnPost) _then) = _$SnPostCopyWithImpl;
|
factory $SnPostCopyWith(SnPost value, $Res Function(SnPost) _then) = _$SnPostCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
int id, String? title, String? description, String? language, DateTime? editedAt, DateTime publishedAt, int visibility, List<dynamic>? content, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, dynamic threadedPostId, dynamic threadedPost, dynamic repliedPostId, dynamic repliedPost, dynamic forwardedPostId, dynamic forwardedPost, List<SnCloudFile> attachments, SnPublisher publisher, List<dynamic> reactions, List<dynamic> tags, List<dynamic> categories, List<dynamic> collections, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
int id, String? title, String? description, String? language, DateTime? editedAt, DateTime publishedAt, int visibility, String? content, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, dynamic threadedPostId, dynamic threadedPost, dynamic repliedPostId, dynamic repliedPost, dynamic forwardedPostId, dynamic forwardedPost, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, List<dynamic> reactions, List<dynamic> tags, List<dynamic> categories, List<dynamic> collections, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ class _$SnPostCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPost
|
/// Create a copy of SnPost
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = null,Object? visibility = null,Object? content = freezed,Object? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? attachments = null,Object? publisher = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = null,Object? visibility = null,Object? content = freezed,Object? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as int,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
as int,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||||
@ -76,7 +76,7 @@ as String?,editedAt: freezed == editedAt ? _self.editedAt : editedAt // ignore:
|
|||||||
as DateTime?,publishedAt: null == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime?,publishedAt: null == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
as DateTime,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
||||||
as int,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
as int,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
as int,meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, dynamic>?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
as Map<String, dynamic>?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
||||||
as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore: cast_nullable_to_non_nullable
|
as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore: cast_nullable_to_non_nullable
|
||||||
@ -90,7 +90,8 @@ as dynamic,forwardedPostId: freezed == forwardedPostId ? _self.forwardedPostId :
|
|||||||
as dynamic,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwardedPost // ignore: cast_nullable_to_non_nullable
|
as dynamic,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwardedPost // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
as dynamic,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPublisher,reactions: null == reactions ? _self.reactions : reactions // ignore: cast_nullable_to_non_nullable
|
as SnPublisher,reactionsCount: null == reactionsCount ? _self.reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, int>,reactions: null == reactions ? _self.reactions : reactions // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,tags: null == tags ? _self.tags : tags // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,tags: null == tags ? _self.tags : tags // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,categories: null == categories ? _self.categories : categories // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,categories: null == categories ? _self.categories : categories // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,collections: null == collections ? _self.collections : collections // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,collections: null == collections ? _self.collections : collections // ignore: cast_nullable_to_non_nullable
|
||||||
@ -117,7 +118,7 @@ $SnPublisherCopyWith<$Res> get publisher {
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnPost implements SnPost {
|
class _SnPost implements SnPost {
|
||||||
const _SnPost({required this.id, required this.title, required this.description, required this.language, required this.editedAt, required this.publishedAt, required this.visibility, required final List<dynamic>? content, required this.type, required final Map<String, dynamic>? meta, required this.viewsUnique, required this.viewsTotal, required this.upvotes, required this.downvotes, required this.threadedPostId, required this.threadedPost, required this.repliedPostId, required this.repliedPost, required this.forwardedPostId, required this.forwardedPost, required final List<SnCloudFile> attachments, required this.publisher, required final List<dynamic> reactions, required final List<dynamic> tags, required final List<dynamic> categories, required final List<dynamic> collections, required this.createdAt, required this.updatedAt, required this.deletedAt}): _content = content,_meta = meta,_attachments = attachments,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
|
const _SnPost({required this.id, required this.title, required this.description, required this.language, required this.editedAt, required this.publishedAt, required this.visibility, required this.content, required this.type, required final Map<String, dynamic>? meta, required this.viewsUnique, required this.viewsTotal, required this.upvotes, required this.downvotes, required this.threadedPostId, required this.threadedPost, required this.repliedPostId, required this.repliedPost, required this.forwardedPostId, required this.forwardedPost, required final List<SnCloudFile> attachments, required this.publisher, final Map<String, int> reactionsCount = const {}, required final List<dynamic> reactions, required final List<dynamic> tags, required final List<dynamic> categories, required final List<dynamic> collections, required this.createdAt, required this.updatedAt, required this.deletedAt}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
|
||||||
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
|
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
|
||||||
|
|
||||||
@override final int id;
|
@override final int id;
|
||||||
@ -127,15 +128,7 @@ class _SnPost implements SnPost {
|
|||||||
@override final DateTime? editedAt;
|
@override final DateTime? editedAt;
|
||||||
@override final DateTime publishedAt;
|
@override final DateTime publishedAt;
|
||||||
@override final int visibility;
|
@override final int visibility;
|
||||||
final List<dynamic>? _content;
|
@override final String? content;
|
||||||
@override List<dynamic>? get content {
|
|
||||||
final value = _content;
|
|
||||||
if (value == null) return null;
|
|
||||||
if (_content is EqualUnmodifiableListView) return _content;
|
|
||||||
// ignore: implicit_dynamic_type
|
|
||||||
return EqualUnmodifiableListView(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override final int type;
|
@override final int type;
|
||||||
final Map<String, dynamic>? _meta;
|
final Map<String, dynamic>? _meta;
|
||||||
@override Map<String, dynamic>? get meta {
|
@override Map<String, dynamic>? get meta {
|
||||||
@ -164,6 +157,13 @@ class _SnPost implements SnPost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override final SnPublisher publisher;
|
@override final SnPublisher publisher;
|
||||||
|
final Map<String, int> _reactionsCount;
|
||||||
|
@override@JsonKey() Map<String, int> get reactionsCount {
|
||||||
|
if (_reactionsCount is EqualUnmodifiableMapView) return _reactionsCount;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(_reactionsCount);
|
||||||
|
}
|
||||||
|
|
||||||
final List<dynamic> _reactions;
|
final List<dynamic> _reactions;
|
||||||
@override List<dynamic> get reactions {
|
@override List<dynamic> get reactions {
|
||||||
if (_reactions is EqualUnmodifiableListView) return _reactions;
|
if (_reactions is EqualUnmodifiableListView) return _reactions;
|
||||||
@ -209,16 +209,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&const DeepCollectionEquality().equals(other._content, _content)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&const DeepCollectionEquality().equals(other.threadedPostId, threadedPostId)&&const DeepCollectionEquality().equals(other.threadedPost, threadedPost)&&const DeepCollectionEquality().equals(other.repliedPostId, repliedPostId)&&const DeepCollectionEquality().equals(other.repliedPost, repliedPost)&&const DeepCollectionEquality().equals(other.forwardedPostId, forwardedPostId)&&const DeepCollectionEquality().equals(other.forwardedPost, forwardedPost)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&const DeepCollectionEquality().equals(other.threadedPostId, threadedPostId)&&const DeepCollectionEquality().equals(other.threadedPost, threadedPost)&&const DeepCollectionEquality().equals(other.repliedPostId, repliedPostId)&&const DeepCollectionEquality().equals(other.repliedPost, repliedPost)&&const DeepCollectionEquality().equals(other.forwardedPostId, forwardedPostId)&&const DeepCollectionEquality().equals(other.forwardedPost, forwardedPost)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,const DeepCollectionEquality().hash(_content),type,const DeepCollectionEquality().hash(_meta),viewsUnique,viewsTotal,upvotes,downvotes,const DeepCollectionEquality().hash(threadedPostId),const DeepCollectionEquality().hash(threadedPost),const DeepCollectionEquality().hash(repliedPostId),const DeepCollectionEquality().hash(repliedPost),const DeepCollectionEquality().hash(forwardedPostId),const DeepCollectionEquality().hash(forwardedPost),const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),createdAt,updatedAt,deletedAt]);
|
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,type,const DeepCollectionEquality().hash(_meta),viewsUnique,viewsTotal,upvotes,downvotes,const DeepCollectionEquality().hash(threadedPostId),const DeepCollectionEquality().hash(threadedPost),const DeepCollectionEquality().hash(repliedPostId),const DeepCollectionEquality().hash(repliedPost),const DeepCollectionEquality().hash(forwardedPostId),const DeepCollectionEquality().hash(forwardedPost),const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),createdAt,updatedAt,deletedAt]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, attachments: $attachments, publisher: $publisher, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -229,7 +229,7 @@ abstract mixin class _$SnPostCopyWith<$Res> implements $SnPostCopyWith<$Res> {
|
|||||||
factory _$SnPostCopyWith(_SnPost value, $Res Function(_SnPost) _then) = __$SnPostCopyWithImpl;
|
factory _$SnPostCopyWith(_SnPost value, $Res Function(_SnPost) _then) = __$SnPostCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
int id, String? title, String? description, String? language, DateTime? editedAt, DateTime publishedAt, int visibility, List<dynamic>? content, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, dynamic threadedPostId, dynamic threadedPost, dynamic repliedPostId, dynamic repliedPost, dynamic forwardedPostId, dynamic forwardedPost, List<SnCloudFile> attachments, SnPublisher publisher, List<dynamic> reactions, List<dynamic> tags, List<dynamic> categories, List<dynamic> collections, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
int id, String? title, String? description, String? language, DateTime? editedAt, DateTime publishedAt, int visibility, String? content, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, dynamic threadedPostId, dynamic threadedPost, dynamic repliedPostId, dynamic repliedPost, dynamic forwardedPostId, dynamic forwardedPost, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, List<dynamic> reactions, List<dynamic> tags, List<dynamic> categories, List<dynamic> collections, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -246,7 +246,7 @@ class __$SnPostCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPost
|
/// Create a copy of SnPost
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = null,Object? visibility = null,Object? content = freezed,Object? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? attachments = null,Object? publisher = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = null,Object? visibility = null,Object? content = freezed,Object? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_SnPost(
|
return _then(_SnPost(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as int,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
as int,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||||
@ -255,8 +255,8 @@ as String?,language: freezed == language ? _self.language : language // ignore:
|
|||||||
as String?,editedAt: freezed == editedAt ? _self.editedAt : editedAt // ignore: cast_nullable_to_non_nullable
|
as String?,editedAt: freezed == editedAt ? _self.editedAt : editedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,publishedAt: null == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime?,publishedAt: null == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
as DateTime,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
||||||
as int,content: freezed == content ? _self._content : content // ignore: cast_nullable_to_non_nullable
|
as int,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,meta: freezed == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable
|
as int,meta: freezed == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, dynamic>?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
as Map<String, dynamic>?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
||||||
as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore: cast_nullable_to_non_nullable
|
as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore: cast_nullable_to_non_nullable
|
||||||
@ -270,7 +270,8 @@ as dynamic,forwardedPostId: freezed == forwardedPostId ? _self.forwardedPostId :
|
|||||||
as dynamic,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwardedPost // ignore: cast_nullable_to_non_nullable
|
as dynamic,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwardedPost // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
as dynamic,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPublisher,reactions: null == reactions ? _self._reactions : reactions // ignore: cast_nullable_to_non_nullable
|
as SnPublisher,reactionsCount: null == reactionsCount ? _self._reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, int>,reactions: null == reactions ? _self._reactions : reactions // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,tags: null == tags ? _self._tags : tags // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,tags: null == tags ? _self._tags : tags // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,categories: null == categories ? _self._categories : categories // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,categories: null == categories ? _self._categories : categories // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,collections: null == collections ? _self._collections : collections // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,collections: null == collections ? _self._collections : collections // ignore: cast_nullable_to_non_nullable
|
||||||
@ -510,4 +511,134 @@ $SnCloudFileCopyWith<$Res>? get background {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$ReactInfo {
|
||||||
|
|
||||||
|
String get icon; int get attitude;
|
||||||
|
/// Create a copy of ReactInfo
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$ReactInfoCopyWith<ReactInfo> get copyWith => _$ReactInfoCopyWithImpl<ReactInfo>(this as ReactInfo, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is ReactInfo&&(identical(other.icon, icon) || other.icon == icon)&&(identical(other.attitude, attitude) || other.attitude == attitude));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,icon,attitude);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ReactInfo(icon: $icon, attitude: $attitude)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $ReactInfoCopyWith<$Res> {
|
||||||
|
factory $ReactInfoCopyWith(ReactInfo value, $Res Function(ReactInfo) _then) = _$ReactInfoCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String icon, int attitude
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$ReactInfoCopyWithImpl<$Res>
|
||||||
|
implements $ReactInfoCopyWith<$Res> {
|
||||||
|
_$ReactInfoCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final ReactInfo _self;
|
||||||
|
final $Res Function(ReactInfo) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ReactInfo
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? icon = null,Object? attitude = null,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
icon: null == icon ? _self.icon : icon // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _ReactInfo implements ReactInfo {
|
||||||
|
const _ReactInfo({required this.icon, required this.attitude});
|
||||||
|
|
||||||
|
|
||||||
|
@override final String icon;
|
||||||
|
@override final int attitude;
|
||||||
|
|
||||||
|
/// Create a copy of ReactInfo
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$ReactInfoCopyWith<_ReactInfo> get copyWith => __$ReactInfoCopyWithImpl<_ReactInfo>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ReactInfo&&(identical(other.icon, icon) || other.icon == icon)&&(identical(other.attitude, attitude) || other.attitude == attitude));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,icon,attitude);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ReactInfo(icon: $icon, attitude: $attitude)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$ReactInfoCopyWith<$Res> implements $ReactInfoCopyWith<$Res> {
|
||||||
|
factory _$ReactInfoCopyWith(_ReactInfo value, $Res Function(_ReactInfo) _then) = __$ReactInfoCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String icon, int attitude
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$ReactInfoCopyWithImpl<$Res>
|
||||||
|
implements _$ReactInfoCopyWith<$Res> {
|
||||||
|
__$ReactInfoCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _ReactInfo _self;
|
||||||
|
final $Res Function(_ReactInfo) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ReactInfo
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? icon = null,Object? attitude = null,}) {
|
||||||
|
return _then(_ReactInfo(
|
||||||
|
icon: null == icon ? _self.icon : icon // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// dart format on
|
// dart format on
|
||||||
|
@ -17,7 +17,7 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
|||||||
: DateTime.parse(json['edited_at'] as String),
|
: DateTime.parse(json['edited_at'] as String),
|
||||||
publishedAt: DateTime.parse(json['published_at'] as String),
|
publishedAt: DateTime.parse(json['published_at'] as String),
|
||||||
visibility: (json['visibility'] as num).toInt(),
|
visibility: (json['visibility'] as num).toInt(),
|
||||||
content: json['content'] as List<dynamic>?,
|
content: json['content'] as String?,
|
||||||
type: (json['type'] as num).toInt(),
|
type: (json['type'] as num).toInt(),
|
||||||
meta: json['meta'] as Map<String, dynamic>?,
|
meta: json['meta'] as Map<String, dynamic>?,
|
||||||
viewsUnique: (json['views_unique'] as num).toInt(),
|
viewsUnique: (json['views_unique'] as num).toInt(),
|
||||||
@ -35,6 +35,11 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
|||||||
.map((e) => SnCloudFile.fromJson(e as Map<String, dynamic>))
|
.map((e) => SnCloudFile.fromJson(e as Map<String, dynamic>))
|
||||||
.toList(),
|
.toList(),
|
||||||
publisher: SnPublisher.fromJson(json['publisher'] as Map<String, dynamic>),
|
publisher: SnPublisher.fromJson(json['publisher'] as Map<String, dynamic>),
|
||||||
|
reactionsCount:
|
||||||
|
(json['reactions_count'] as Map<String, dynamic>?)?.map(
|
||||||
|
(k, e) => MapEntry(k, (e as num).toInt()),
|
||||||
|
) ??
|
||||||
|
const {},
|
||||||
reactions: json['reactions'] as List<dynamic>,
|
reactions: json['reactions'] as List<dynamic>,
|
||||||
tags: json['tags'] as List<dynamic>,
|
tags: json['tags'] as List<dynamic>,
|
||||||
categories: json['categories'] as List<dynamic>,
|
categories: json['categories'] as List<dynamic>,
|
||||||
@ -70,6 +75,7 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
|||||||
'forwarded_post': instance.forwardedPost,
|
'forwarded_post': instance.forwardedPost,
|
||||||
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
||||||
'publisher': instance.publisher.toJson(),
|
'publisher': instance.publisher.toJson(),
|
||||||
|
'reactions_count': instance.reactionsCount,
|
||||||
'reactions': instance.reactions,
|
'reactions': instance.reactions,
|
||||||
'tags': instance.tags,
|
'tags': instance.tags,
|
||||||
'categories': instance.categories,
|
'categories': instance.categories,
|
||||||
|
@ -30,7 +30,8 @@ class CreateAccountScreen extends HookConsumerWidget {
|
|||||||
final passwordController = useTextEditingController();
|
final passwordController = useTextEditingController();
|
||||||
|
|
||||||
void showPostCreateModal() {
|
void showPostCreateModal() {
|
||||||
showCupertinoModalBottomSheet(
|
showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => _PostCreateModal(),
|
builder: (context) => _PostCreateModal(),
|
||||||
);
|
);
|
||||||
@ -265,48 +266,45 @@ class _PostCreateModal extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Material(
|
child: ConstrainedBox(
|
||||||
color: Colors.transparent,
|
constraints: const BoxConstraints(maxWidth: 280),
|
||||||
child: ConstrainedBox(
|
child: Column(
|
||||||
constraints: const BoxConstraints(maxWidth: 280),
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
child: Column(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
Text('🎉').fontSize(32),
|
||||||
children: [
|
Text(
|
||||||
Text('🎉').fontSize(32),
|
'postCreateAccountTitle'.tr(),
|
||||||
Text(
|
textAlign: TextAlign.center,
|
||||||
'postCreateAccountTitle'.tr(),
|
).fontSize(17),
|
||||||
textAlign: TextAlign.center,
|
const Gap(18),
|
||||||
).fontSize(17),
|
Text('postCreateAccountNext').tr().fontSize(19).bold(),
|
||||||
const Gap(18),
|
const Gap(4),
|
||||||
Text('postCreateAccountNext').tr().fontSize(19).bold(),
|
Row(
|
||||||
const Gap(4),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Row(
|
spacing: 6,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
spacing: 6,
|
Text('\u2022'),
|
||||||
children: [
|
Expanded(child: Text('postCreateAccountNext1').tr()),
|
||||||
Text('\u2022'),
|
],
|
||||||
Expanded(child: Text('postCreateAccountNext1').tr()),
|
),
|
||||||
],
|
Row(
|
||||||
),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Row(
|
spacing: 6,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
spacing: 6,
|
Text('\u2022'),
|
||||||
children: [
|
Expanded(child: Text('postCreateAccountNext2').tr()),
|
||||||
Text('\u2022'),
|
],
|
||||||
Expanded(child: Text('postCreateAccountNext2').tr()),
|
),
|
||||||
],
|
const Gap(6),
|
||||||
),
|
TextButton(
|
||||||
const Gap(6),
|
onPressed: () {
|
||||||
TextButton(
|
Navigator.pop(context);
|
||||||
onPressed: () {
|
context.router.replace(LoginRoute());
|
||||||
Navigator.pop(context);
|
},
|
||||||
context.router.replace(LoginRoute());
|
child: Text('login'.tr()),
|
||||||
},
|
),
|
||||||
child: Text('login'.tr()),
|
],
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -45,7 +45,7 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
final fabKey = useMemoized(() => GlobalKey<ExpandableFabState>(), []);
|
final fabKey = useMemoized(() => GlobalKey<ExpandableFabState>(), []);
|
||||||
|
|
||||||
Future<void> createDirectMessage() async {
|
Future<void> createDirectMessage() async {
|
||||||
final result = await showCupertinoModalBottomSheet(
|
final result = await showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AccountPickerSheet(),
|
builder: (context) => AccountPickerSheet(),
|
||||||
);
|
);
|
||||||
@ -66,7 +66,8 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.email),
|
icon: const Icon(Symbols.email),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showCupertinoModalBottomSheet(
|
showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => _ChatInvitesSheet(),
|
builder: (context) => _ChatInvitesSheet(),
|
||||||
);
|
);
|
||||||
@ -436,102 +437,90 @@ class _ChatInvitesSheet extends HookConsumerWidget {
|
|||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
||||||
),
|
),
|
||||||
child: Material(
|
child: Column(
|
||||||
color: Colors.transparent,
|
mainAxisSize: MainAxisSize.min,
|
||||||
child: Column(
|
children: [
|
||||||
mainAxisSize: MainAxisSize.min,
|
Padding(
|
||||||
children: [
|
padding: EdgeInsets.only(top: 16, left: 20, right: 16, bottom: 12),
|
||||||
Padding(
|
child: Row(
|
||||||
padding: EdgeInsets.only(
|
children: [
|
||||||
top: 16,
|
Text(
|
||||||
left: 20,
|
'invites'.tr(),
|
||||||
right: 16,
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||||
bottom: 12,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
letterSpacing: -0.5,
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'invites'.tr(),
|
|
||||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: -0.5,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Spacer(),
|
),
|
||||||
IconButton(
|
const Spacer(),
|
||||||
icon: const Icon(Symbols.refresh),
|
IconButton(
|
||||||
style: IconButton.styleFrom(
|
icon: const Icon(Symbols.refresh),
|
||||||
minimumSize: const Size(36, 36),
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
),
|
onPressed: () {
|
||||||
onPressed: () {
|
ref.invalidate(chatroomInvitesProvider);
|
||||||
ref.invalidate(chatroomInvitesProvider);
|
},
|
||||||
},
|
),
|
||||||
),
|
IconButton(
|
||||||
IconButton(
|
icon: const Icon(Symbols.close),
|
||||||
icon: const Icon(Symbols.close),
|
onPressed: () => Navigator.pop(context),
|
||||||
onPressed: () => Navigator.pop(context),
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
style: IconButton.styleFrom(
|
),
|
||||||
minimumSize: const Size(36, 36),
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
),
|
||||||
Expanded(
|
const Divider(height: 1),
|
||||||
child: invites.when(
|
Expanded(
|
||||||
data:
|
child: invites.when(
|
||||||
(items) =>
|
data:
|
||||||
items.isEmpty
|
(items) =>
|
||||||
? Center(
|
items.isEmpty
|
||||||
child:
|
? Center(
|
||||||
Text(
|
child:
|
||||||
'invitesEmpty',
|
Text(
|
||||||
textAlign: TextAlign.center,
|
'invitesEmpty',
|
||||||
).tr(),
|
textAlign: TextAlign.center,
|
||||||
)
|
).tr(),
|
||||||
: ListView.builder(
|
)
|
||||||
shrinkWrap: true,
|
: ListView.builder(
|
||||||
itemCount: items.length,
|
shrinkWrap: true,
|
||||||
itemBuilder: (context, index) {
|
itemCount: items.length,
|
||||||
final invite = items[index];
|
itemBuilder: (context, index) {
|
||||||
return ListTile(
|
final invite = items[index];
|
||||||
leading: ProfilePictureWidget(
|
return ListTile(
|
||||||
fileId: invite.chatRoom!.pictureId,
|
leading: ProfilePictureWidget(
|
||||||
radius: 24,
|
fileId: invite.chatRoom!.pictureId,
|
||||||
fallbackIcon: Symbols.group,
|
radius: 24,
|
||||||
),
|
fallbackIcon: Symbols.group,
|
||||||
title: Text(invite.chatRoom!.name),
|
),
|
||||||
subtitle:
|
title: Text(invite.chatRoom!.name),
|
||||||
Text(
|
subtitle:
|
||||||
invite.role >= 100
|
Text(
|
||||||
? 'permissionOwner'
|
invite.role >= 100
|
||||||
: invite.role >= 50
|
? 'permissionOwner'
|
||||||
? 'permissionModerator'
|
: invite.role >= 50
|
||||||
: 'permissionMember',
|
? 'permissionModerator'
|
||||||
).tr(),
|
: 'permissionMember',
|
||||||
trailing: Row(
|
).tr(),
|
||||||
mainAxisSize: MainAxisSize.min,
|
trailing: Row(
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
IconButton(
|
children: [
|
||||||
icon: const Icon(Symbols.check),
|
IconButton(
|
||||||
onPressed: () => acceptInvite(invite),
|
icon: const Icon(Symbols.check),
|
||||||
),
|
onPressed: () => acceptInvite(invite),
|
||||||
IconButton(
|
),
|
||||||
icon: const Icon(Symbols.close),
|
IconButton(
|
||||||
onPressed: () => declineInvite(invite),
|
icon: const Icon(Symbols.close),
|
||||||
),
|
onPressed: () => declineInvite(invite),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
);
|
),
|
||||||
},
|
);
|
||||||
),
|
},
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
),
|
||||||
error: (error, stack) => Center(child: Text('Error: $error')),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
),
|
error: (error, stack) => Center(child: Text('Error: $error')),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,8 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.people, shadows: [iconShadow]),
|
icon: const Icon(Icons.people, shadows: [iconShadow]),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showCupertinoModalBottomSheet(
|
showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder:
|
builder:
|
||||||
(context) => _ChatMemberListSheet(roomId: id),
|
(context) => _ChatMemberListSheet(roomId: id),
|
||||||
@ -263,7 +264,8 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
Future<void> invitePerson() async {
|
Future<void> invitePerson() async {
|
||||||
final result = await showCupertinoModalBottomSheet(
|
final result = await showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => const AccountPickerSheet(),
|
builder: (context) => const AccountPickerSheet(),
|
||||||
);
|
);
|
||||||
@ -285,111 +287,96 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
|||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
||||||
),
|
),
|
||||||
child: Material(
|
child: Column(
|
||||||
color: Colors.transparent,
|
children: [
|
||||||
child: Column(
|
Padding(
|
||||||
children: [
|
padding: EdgeInsets.only(top: 16, left: 20, right: 16, bottom: 12),
|
||||||
Padding(
|
child: Row(
|
||||||
padding: EdgeInsets.only(
|
children: [
|
||||||
top: 16,
|
Text(
|
||||||
left: 20,
|
'members'.plural(memberState.total),
|
||||||
right: 16,
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||||
bottom: 12,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
letterSpacing: -0.5,
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'members'.plural(memberState.total),
|
|
||||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: -0.5,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Spacer(),
|
),
|
||||||
IconButton(
|
const Spacer(),
|
||||||
icon: const Icon(Symbols.person_add),
|
IconButton(
|
||||||
onPressed: invitePerson,
|
icon: const Icon(Symbols.person_add),
|
||||||
style: IconButton.styleFrom(
|
onPressed: invitePerson,
|
||||||
minimumSize: const Size(36, 36),
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
),
|
),
|
||||||
),
|
IconButton(
|
||||||
IconButton(
|
icon: const Icon(Symbols.refresh),
|
||||||
icon: const Icon(Symbols.refresh),
|
onPressed: () {
|
||||||
onPressed: () {
|
memberNotifier.reset();
|
||||||
memberNotifier.reset();
|
memberNotifier.loadMore();
|
||||||
memberNotifier.loadMore();
|
},
|
||||||
},
|
),
|
||||||
),
|
IconButton(
|
||||||
IconButton(
|
icon: const Icon(Symbols.close),
|
||||||
icon: const Icon(Symbols.close),
|
onPressed: () => Navigator.pop(context),
|
||||||
onPressed: () => Navigator.pop(context),
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
style: IconButton.styleFrom(
|
),
|
||||||
minimumSize: const Size(36, 36),
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
),
|
||||||
Expanded(
|
const Divider(height: 1),
|
||||||
child:
|
Expanded(
|
||||||
memberState.error != null
|
child:
|
||||||
? Center(child: Text(memberState.error!))
|
memberState.error != null
|
||||||
: ListView.builder(
|
? Center(child: Text(memberState.error!))
|
||||||
itemCount: memberState.members.length + 1,
|
: ListView.builder(
|
||||||
itemBuilder: (context, index) {
|
itemCount: memberState.members.length + 1,
|
||||||
if (index == memberState.members.length) {
|
itemBuilder: (context, index) {
|
||||||
if (memberState.isLoading) {
|
if (index == memberState.members.length) {
|
||||||
return const Center(
|
if (memberState.isLoading) {
|
||||||
child: Padding(
|
return const Center(
|
||||||
padding: EdgeInsets.all(16.0),
|
child: Padding(
|
||||||
child: CircularProgressIndicator(),
|
padding: EdgeInsets.all(16.0),
|
||||||
),
|
child: CircularProgressIndicator(),
|
||||||
);
|
),
|
||||||
}
|
);
|
||||||
if (memberState.members.length <
|
|
||||||
memberState.total) {
|
|
||||||
memberNotifier.loadMore(
|
|
||||||
offset: memberState.members.length,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
}
|
||||||
|
if (memberState.members.length < memberState.total) {
|
||||||
|
memberNotifier.loadMore(
|
||||||
|
offset: memberState.members.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
final member = memberState.members[index];
|
final member = memberState.members[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: ProfilePictureWidget(
|
leading: ProfilePictureWidget(
|
||||||
fileId: member.account.profile.pictureId,
|
fileId: member.account.profile.pictureId,
|
||||||
),
|
),
|
||||||
title: Row(
|
title: Row(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
children: [
|
children: [
|
||||||
Flexible(child: Text(member.account.nick)),
|
Flexible(child: Text(member.account.nick)),
|
||||||
if (member.joinedAt == null)
|
if (member.joinedAt == null)
|
||||||
const Icon(Symbols.pending_actions, size: 20),
|
const Icon(Symbols.pending_actions, size: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
subtitle: Row(
|
subtitle: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
member.role >= 100
|
member.role >= 100
|
||||||
? 'permissionOwner'
|
? 'permissionOwner'
|
||||||
: member.role >= 50
|
: member.role >= 50
|
||||||
? 'permissionModerator'
|
? 'permissionModerator'
|
||||||
: 'permissionMember',
|
: 'permissionMember',
|
||||||
).tr(),
|
).tr(),
|
||||||
Text('·').bold().padding(horizontal: 6),
|
Text('·').bold().padding(horizontal: 6),
|
||||||
Expanded(
|
Expanded(child: Text("@${member.account.name}")),
|
||||||
child: Text("@${member.account.name}"),
|
],
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
),
|
},
|
||||||
);
|
),
|
||||||
},
|
),
|
||||||
),
|
],
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@ class ExploreScreen extends ConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final postAsync = ref.watch(postListProvider);
|
final posts = ref.watch(postListProvider);
|
||||||
|
final postsNotifier = ref.watch(postListProvider.notifier);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(title: const Text('Explore')),
|
appBar: AppBar(title: const Text('Explore')),
|
||||||
@ -32,60 +33,48 @@ class ExploreScreen extends ConsumerWidget {
|
|||||||
child: const Icon(Symbols.edit),
|
child: const Icon(Symbols.edit),
|
||||||
),
|
),
|
||||||
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
|
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
|
||||||
body: postAsync.when(
|
body: RefreshIndicator(
|
||||||
data:
|
onRefresh:
|
||||||
(controller) => RefreshIndicator(
|
() => Future.sync((() {
|
||||||
onRefresh:
|
ref.invalidate(postListProvider);
|
||||||
() => Future.sync((() {
|
})),
|
||||||
ref.invalidate(postListProvider);
|
child: InfiniteList(
|
||||||
})),
|
padding: EdgeInsets.only(
|
||||||
child: InfiniteList(
|
bottom: MediaQuery.of(context).padding.bottom,
|
||||||
padding: EdgeInsets.only(
|
),
|
||||||
bottom: MediaQuery.of(context).padding.bottom,
|
itemCount: posts.length,
|
||||||
),
|
isLoading: postsNotifier.isLoading,
|
||||||
itemCount: controller.posts.length,
|
hasReachedMax: postsNotifier.hasReachedMax,
|
||||||
isLoading: controller.isLoading,
|
onFetchData: postsNotifier.fetchMore,
|
||||||
hasReachedMax: controller.hasReachedMax,
|
itemBuilder: (context, index) {
|
||||||
onFetchData: controller.fetchMore,
|
final post = posts[index];
|
||||||
itemBuilder: (context, index) {
|
return PostItem(
|
||||||
final post = controller.posts[index];
|
item: post,
|
||||||
return PostItem(
|
onRefresh: (_) {
|
||||||
item: post,
|
|
||||||
onRefresh: (_) {
|
|
||||||
ref.invalidate(postListProvider);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
separatorBuilder: (_, __) => const Divider(height: 1),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
|
||||||
error:
|
|
||||||
(e, _) => GestureDetector(
|
|
||||||
child: Center(
|
|
||||||
child: Text('Error: $e', textAlign: TextAlign.center),
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
ref.invalidate(postListProvider);
|
ref.invalidate(postListProvider);
|
||||||
},
|
},
|
||||||
),
|
onUpdate: (post) {
|
||||||
|
postsNotifier.updateOne(index, post);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (_, __) => const Divider(height: 1),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final postListProvider = FutureProvider<_PostListController>((ref) async {
|
final postListProvider =
|
||||||
final client = ref.watch(apiClientProvider);
|
StateNotifierProvider<_PostListController, List<SnPost>>((ref) {
|
||||||
final controller = _PostListController(client);
|
final client = ref.watch(apiClientProvider);
|
||||||
await controller.fetchMore();
|
return _PostListController(client);
|
||||||
return controller;
|
});
|
||||||
});
|
|
||||||
|
|
||||||
class _PostListController {
|
class _PostListController extends StateNotifier<List<SnPost>> {
|
||||||
_PostListController(this._dio);
|
_PostListController(this._dio) : super([]);
|
||||||
|
|
||||||
final Dio _dio;
|
final Dio _dio;
|
||||||
final List<SnPost> posts = [];
|
|
||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
bool hasReachedMax = false;
|
bool hasReachedMax = false;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
@ -109,10 +98,16 @@ class _PostListController {
|
|||||||
final headerTotal = int.tryParse(response.headers['x-total']?.first ?? '');
|
final headerTotal = int.tryParse(response.headers['x-total']?.first ?? '');
|
||||||
if (headerTotal != null) total = headerTotal;
|
if (headerTotal != null) total = headerTotal;
|
||||||
|
|
||||||
posts.addAll(fetched);
|
state = [...state, ...fetched];
|
||||||
offset += fetched.length;
|
offset += fetched.length;
|
||||||
if (posts.length >= total) hasReachedMax = true;
|
if (state.length >= total) hasReachedMax = true;
|
||||||
|
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateOne(int index, SnPost post) {
|
||||||
|
final updatedPosts = [...state];
|
||||||
|
updatedPosts[index] = post;
|
||||||
|
state = updatedPosts;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ import 'dart:io';
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:flutter_quill/flutter_quill.dart';
|
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
@ -21,6 +21,7 @@ import 'package:island/widgets/alert.dart';
|
|||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/post/publishers_modal.dart';
|
import 'package:island/widgets/post/publishers_modal.dart';
|
||||||
|
import 'package:markdown_editor_plus/widgets/markdown_auto_preview.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
|
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
@ -88,14 +89,9 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
final descriptionController = useTextEditingController(
|
final descriptionController = useTextEditingController(
|
||||||
text: originalPost?.description,
|
text: originalPost?.description,
|
||||||
);
|
);
|
||||||
final contentController = useMemoized(() => QuillController.basic());
|
final contentController = useTextEditingController(
|
||||||
|
text: originalPost?.content,
|
||||||
useEffect(() {
|
);
|
||||||
if (originalPost?.content != null) {
|
|
||||||
contentController.document = Document.fromJson(originalPost!.content!);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}, [originalPost]);
|
|
||||||
|
|
||||||
final submitting = useState(false);
|
final submitting = useState(false);
|
||||||
|
|
||||||
@ -192,14 +188,14 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
await Future.wait(
|
await Future.wait(
|
||||||
attachments.value
|
attachments.value
|
||||||
.where((e) => e.isOnDevice)
|
.where((e) => e.isOnDevice)
|
||||||
.map((e) => uploadAttachment(e.data)),
|
.mapIndexed((idx, e) => uploadAttachment(idx)),
|
||||||
);
|
);
|
||||||
|
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
await client.request(
|
await client.request(
|
||||||
originalPost == null ? '/posts' : '/posts/${originalPost!.id}',
|
originalPost == null ? '/posts' : '/posts/${originalPost!.id}',
|
||||||
data: {
|
data: {
|
||||||
'content': contentController.document.toDelta().toJson(),
|
'content': contentController.text,
|
||||||
'attachments':
|
'attachments':
|
||||||
attachments.value
|
attachments.value
|
||||||
.where((e) => e.isOnCloud)
|
.where((e) => e.isOnCloud)
|
||||||
@ -255,10 +251,15 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: ProfilePictureWidget(
|
child: ProfilePictureWidget(
|
||||||
fileId: currentPublisher.value?.pictureId,
|
fileId: currentPublisher.value?.pictureId,
|
||||||
radius: 24,
|
radius: 20,
|
||||||
|
fallbackIcon:
|
||||||
|
currentPublisher.value == null
|
||||||
|
? Symbols.question_mark
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showCupertinoModalBottomSheet(
|
showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => PublisherModal(),
|
builder: (context) => PublisherModal(),
|
||||||
).then((value) {
|
).then((value) {
|
||||||
@ -292,11 +293,18 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
FocusManager.instance.primaryFocus?.unfocus(),
|
FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
),
|
),
|
||||||
const Gap(12),
|
const Gap(12),
|
||||||
QuillEditor.basic(
|
TapRegion(
|
||||||
controller: contentController,
|
child: MarkdownAutoPreview(
|
||||||
config: QuillEditorConfig(
|
controller: contentController,
|
||||||
placeholder: 'postPlaceholder'.tr(),
|
emojiConvert: true,
|
||||||
|
hintText: 'postPlaceholder'.tr(),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
onTapOutside:
|
||||||
|
(_) =>
|
||||||
|
FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
),
|
),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
Column(
|
Column(
|
||||||
@ -337,29 +345,17 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
Material(
|
Material(
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
child: Column(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
SingleChildScrollView(
|
IconButton(
|
||||||
scrollDirection: Axis.horizontal,
|
onPressed: pickPhotoMedia,
|
||||||
child: QuillSimpleToolbar(
|
icon: const Icon(Symbols.add_a_photo),
|
||||||
controller: contentController,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
config: QuillSimpleToolbarConfig(showFontFamily: false),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Row(
|
IconButton(
|
||||||
children: [
|
onPressed: pickVideoMedia,
|
||||||
IconButton(
|
icon: const Icon(Symbols.videocam),
|
||||||
onPressed: pickPhotoMedia,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
icon: const Icon(Symbols.add_a_photo),
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: pickVideoMedia,
|
|
||||||
icon: const Icon(Symbols.videocam),
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(
|
).padding(
|
||||||
@ -510,49 +506,46 @@ class AttachmentPreview extends StatelessWidget {
|
|||||||
Positioned(
|
Positioned(
|
||||||
top: 8,
|
top: 8,
|
||||||
right: 8,
|
right: 8,
|
||||||
child: Material(
|
child: InkWell(
|
||||||
color: Colors.transparent,
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: InkWell(
|
onTap: () => onRequestUpload?.call(),
|
||||||
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
onTap: () => onRequestUpload?.call(),
|
child: Container(
|
||||||
child: ClipRRect(
|
color: Colors.black.withOpacity(0.5),
|
||||||
borderRadius: BorderRadius.circular(8),
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
child: Container(
|
child:
|
||||||
color: Colors.black.withOpacity(0.5),
|
(item.isOnCloud)
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
? Row(
|
||||||
child:
|
mainAxisSize: MainAxisSize.min,
|
||||||
(item.isOnCloud)
|
children: [
|
||||||
? Row(
|
Icon(
|
||||||
mainAxisSize: MainAxisSize.min,
|
Symbols.cloud,
|
||||||
children: [
|
size: 16,
|
||||||
Icon(
|
color: Colors.white,
|
||||||
Symbols.cloud,
|
),
|
||||||
size: 16,
|
const Gap(8),
|
||||||
color: Colors.white,
|
Text(
|
||||||
),
|
'On-cloud',
|
||||||
const Gap(8),
|
style: TextStyle(color: Colors.white),
|
||||||
Text(
|
),
|
||||||
'On-cloud',
|
],
|
||||||
style: TextStyle(color: Colors.white),
|
)
|
||||||
),
|
: Row(
|
||||||
],
|
mainAxisSize: MainAxisSize.min,
|
||||||
)
|
children: [
|
||||||
: Row(
|
Icon(
|
||||||
mainAxisSize: MainAxisSize.min,
|
Symbols.cloud_off,
|
||||||
children: [
|
size: 16,
|
||||||
Icon(
|
color: Colors.white,
|
||||||
Symbols.cloud_off,
|
),
|
||||||
size: 16,
|
const Gap(8),
|
||||||
color: Colors.white,
|
Text(
|
||||||
),
|
'On-device',
|
||||||
const Gap(8),
|
style: TextStyle(color: Colors.white),
|
||||||
Text(
|
),
|
||||||
'On-device',
|
],
|
||||||
style: TextStyle(color: Colors.white),
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -80,7 +80,8 @@ class RealmDetailScreen extends HookConsumerWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.people, shadows: [iconShadow]),
|
icon: const Icon(Icons.people, shadows: [iconShadow]),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showCupertinoModalBottomSheet(
|
showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder:
|
builder:
|
||||||
(context) =>
|
(context) =>
|
||||||
@ -236,7 +237,8 @@ class _RealmMemberListSheet extends HookConsumerWidget {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
Future<void> invitePerson() async {
|
Future<void> invitePerson() async {
|
||||||
final result = await showCupertinoModalBottomSheet(
|
final result = await showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => const AccountPickerSheet(),
|
builder: (context) => const AccountPickerSheet(),
|
||||||
);
|
);
|
||||||
@ -258,111 +260,96 @@ class _RealmMemberListSheet extends HookConsumerWidget {
|
|||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
||||||
),
|
),
|
||||||
child: Material(
|
child: Column(
|
||||||
color: Colors.transparent,
|
children: [
|
||||||
child: Column(
|
Padding(
|
||||||
children: [
|
padding: EdgeInsets.only(top: 16, left: 20, right: 16, bottom: 12),
|
||||||
Padding(
|
child: Row(
|
||||||
padding: EdgeInsets.only(
|
children: [
|
||||||
top: 16,
|
Text(
|
||||||
left: 20,
|
'members'.plural(memberState.total),
|
||||||
right: 16,
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||||
bottom: 12,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
letterSpacing: -0.5,
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'members'.plural(memberState.total),
|
|
||||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: -0.5,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Spacer(),
|
),
|
||||||
IconButton(
|
const Spacer(),
|
||||||
icon: const Icon(Symbols.person_add),
|
IconButton(
|
||||||
onPressed: invitePerson,
|
icon: const Icon(Symbols.person_add),
|
||||||
style: IconButton.styleFrom(
|
onPressed: invitePerson,
|
||||||
minimumSize: const Size(36, 36),
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
),
|
),
|
||||||
),
|
IconButton(
|
||||||
IconButton(
|
icon: const Icon(Symbols.refresh),
|
||||||
icon: const Icon(Symbols.refresh),
|
onPressed: () {
|
||||||
onPressed: () {
|
memberNotifier.reset();
|
||||||
memberNotifier.reset();
|
memberNotifier.loadMore();
|
||||||
memberNotifier.loadMore();
|
},
|
||||||
},
|
),
|
||||||
),
|
IconButton(
|
||||||
IconButton(
|
icon: const Icon(Symbols.close),
|
||||||
icon: const Icon(Symbols.close),
|
onPressed: () => Navigator.pop(context),
|
||||||
onPressed: () => Navigator.pop(context),
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
style: IconButton.styleFrom(
|
),
|
||||||
minimumSize: const Size(36, 36),
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
),
|
||||||
Expanded(
|
const Divider(height: 1),
|
||||||
child:
|
Expanded(
|
||||||
memberState.error != null
|
child:
|
||||||
? Center(child: Text(memberState.error!))
|
memberState.error != null
|
||||||
: ListView.builder(
|
? Center(child: Text(memberState.error!))
|
||||||
itemCount: memberState.members.length + 1,
|
: ListView.builder(
|
||||||
itemBuilder: (context, index) {
|
itemCount: memberState.members.length + 1,
|
||||||
if (index == memberState.members.length) {
|
itemBuilder: (context, index) {
|
||||||
if (memberState.isLoading) {
|
if (index == memberState.members.length) {
|
||||||
return const Center(
|
if (memberState.isLoading) {
|
||||||
child: Padding(
|
return const Center(
|
||||||
padding: EdgeInsets.all(16.0),
|
child: Padding(
|
||||||
child: CircularProgressIndicator(),
|
padding: EdgeInsets.all(16.0),
|
||||||
),
|
child: CircularProgressIndicator(),
|
||||||
);
|
),
|
||||||
}
|
);
|
||||||
if (memberState.members.length <
|
|
||||||
memberState.total) {
|
|
||||||
memberNotifier.loadMore(
|
|
||||||
offset: memberState.members.length,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
}
|
||||||
|
if (memberState.members.length < memberState.total) {
|
||||||
|
memberNotifier.loadMore(
|
||||||
|
offset: memberState.members.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
final member = memberState.members[index];
|
final member = memberState.members[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: ProfilePictureWidget(
|
leading: ProfilePictureWidget(
|
||||||
fileId: member.account!.profile.pictureId,
|
fileId: member.account!.profile.pictureId,
|
||||||
),
|
),
|
||||||
title: Row(
|
title: Row(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
children: [
|
children: [
|
||||||
Flexible(child: Text(member.account!.nick)),
|
Flexible(child: Text(member.account!.nick)),
|
||||||
if (member.joinedAt == null)
|
if (member.joinedAt == null)
|
||||||
const Icon(Symbols.pending_actions, size: 20),
|
const Icon(Symbols.pending_actions, size: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
subtitle: Row(
|
subtitle: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
member.role >= 100
|
member.role >= 100
|
||||||
? 'permissionOwner'
|
? 'permissionOwner'
|
||||||
: member.role >= 50
|
: member.role >= 50
|
||||||
? 'permissionModerator'
|
? 'permissionModerator'
|
||||||
: 'permissionMember',
|
: 'permissionMember',
|
||||||
).tr(),
|
).tr(),
|
||||||
Text('·').bold().padding(horizontal: 6),
|
Text('·').bold().padding(horizontal: 6),
|
||||||
Expanded(
|
Expanded(child: Text("@${member.account!.name}")),
|
||||||
child: Text("@${member.account!.name}"),
|
],
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
),
|
},
|
||||||
);
|
),
|
||||||
},
|
),
|
||||||
),
|
],
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -359,102 +359,90 @@ class _RealmInviteSheet extends HookConsumerWidget {
|
|||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
||||||
),
|
),
|
||||||
child: Material(
|
child: Column(
|
||||||
color: Colors.transparent,
|
mainAxisSize: MainAxisSize.min,
|
||||||
child: Column(
|
children: [
|
||||||
mainAxisSize: MainAxisSize.min,
|
Padding(
|
||||||
children: [
|
padding: EdgeInsets.only(top: 16, left: 20, right: 16, bottom: 12),
|
||||||
Padding(
|
child: Row(
|
||||||
padding: EdgeInsets.only(
|
children: [
|
||||||
top: 16,
|
Text(
|
||||||
left: 20,
|
'invites'.tr(),
|
||||||
right: 16,
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||||
bottom: 12,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
letterSpacing: -0.5,
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'invites'.tr(),
|
|
||||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: -0.5,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Spacer(),
|
),
|
||||||
IconButton(
|
const Spacer(),
|
||||||
icon: const Icon(Symbols.refresh),
|
IconButton(
|
||||||
style: IconButton.styleFrom(
|
icon: const Icon(Symbols.refresh),
|
||||||
minimumSize: const Size(36, 36),
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
),
|
onPressed: () {
|
||||||
onPressed: () {
|
ref.invalidate(realmInvitesProvider);
|
||||||
ref.invalidate(realmInvitesProvider);
|
},
|
||||||
},
|
),
|
||||||
),
|
IconButton(
|
||||||
IconButton(
|
icon: const Icon(Symbols.close),
|
||||||
icon: const Icon(Symbols.close),
|
onPressed: () => Navigator.pop(context),
|
||||||
onPressed: () => Navigator.pop(context),
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
style: IconButton.styleFrom(
|
),
|
||||||
minimumSize: const Size(36, 36),
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
),
|
||||||
Expanded(
|
const Divider(height: 1),
|
||||||
child: invites.when(
|
Expanded(
|
||||||
data:
|
child: invites.when(
|
||||||
(items) =>
|
data:
|
||||||
items.isEmpty
|
(items) =>
|
||||||
? Center(
|
items.isEmpty
|
||||||
child:
|
? Center(
|
||||||
Text(
|
child:
|
||||||
'invitesEmpty',
|
Text(
|
||||||
textAlign: TextAlign.center,
|
'invitesEmpty',
|
||||||
).tr(),
|
textAlign: TextAlign.center,
|
||||||
)
|
).tr(),
|
||||||
: ListView.builder(
|
)
|
||||||
shrinkWrap: true,
|
: ListView.builder(
|
||||||
itemCount: items.length,
|
shrinkWrap: true,
|
||||||
itemBuilder: (context, index) {
|
itemCount: items.length,
|
||||||
final invite = items[index];
|
itemBuilder: (context, index) {
|
||||||
return ListTile(
|
final invite = items[index];
|
||||||
leading: ProfilePictureWidget(
|
return ListTile(
|
||||||
fileId: invite.realm!.pictureId,
|
leading: ProfilePictureWidget(
|
||||||
radius: 24,
|
fileId: invite.realm!.pictureId,
|
||||||
fallbackIcon: Symbols.group,
|
radius: 24,
|
||||||
),
|
fallbackIcon: Symbols.group,
|
||||||
title: Text(invite.realm!.name),
|
),
|
||||||
subtitle:
|
title: Text(invite.realm!.name),
|
||||||
Text(
|
subtitle:
|
||||||
invite.role >= 100
|
Text(
|
||||||
? 'permissionOwner'
|
invite.role >= 100
|
||||||
: invite.role >= 50
|
? 'permissionOwner'
|
||||||
? 'permissionModerator'
|
: invite.role >= 50
|
||||||
: 'permissionMember',
|
? 'permissionModerator'
|
||||||
).tr(),
|
: 'permissionMember',
|
||||||
trailing: Row(
|
).tr(),
|
||||||
mainAxisSize: MainAxisSize.min,
|
trailing: Row(
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
IconButton(
|
children: [
|
||||||
icon: const Icon(Symbols.check),
|
IconButton(
|
||||||
onPressed: () => acceptInvite(invite),
|
icon: const Icon(Symbols.check),
|
||||||
),
|
onPressed: () => acceptInvite(invite),
|
||||||
IconButton(
|
),
|
||||||
icon: const Icon(Symbols.close),
|
IconButton(
|
||||||
onPressed: () => declineInvite(invite),
|
icon: const Icon(Symbols.close),
|
||||||
),
|
onPressed: () => declineInvite(invite),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
);
|
),
|
||||||
},
|
);
|
||||||
),
|
},
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
),
|
||||||
error: (error, stack) => Center(child: Text('Error: $error')),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
),
|
error: (error, stack) => Center(child: Text('Error: $error')),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -47,60 +47,56 @@ class AccountPickerSheet extends HookConsumerWidget {
|
|||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: MediaQuery.of(context).size.height * 0.4,
|
maxHeight: MediaQuery.of(context).size.height * 0.4,
|
||||||
),
|
),
|
||||||
child: Material(
|
child: Column(
|
||||||
color: Colors.transparent,
|
children: [
|
||||||
child: Column(
|
Padding(
|
||||||
children: [
|
padding: const EdgeInsets.only(top: 4),
|
||||||
Padding(
|
child: TextField(
|
||||||
padding: const EdgeInsets.only(top: 4),
|
controller: searchController,
|
||||||
child: TextField(
|
onChanged: onSearchChanged,
|
||||||
controller: searchController,
|
decoration: const InputDecoration(
|
||||||
onChanged: onSearchChanged,
|
hintText: 'Search accounts...',
|
||||||
decoration: const InputDecoration(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
hintText: 'Search accounts...',
|
horizontal: 18,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
vertical: 16,
|
||||||
horizontal: 18,
|
|
||||||
vertical: 16,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
autofocus: true,
|
|
||||||
onTapOutside:
|
|
||||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
|
||||||
),
|
),
|
||||||
|
autofocus: true,
|
||||||
|
onTapOutside:
|
||||||
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
),
|
),
|
||||||
Expanded(
|
),
|
||||||
child: Consumer(
|
Expanded(
|
||||||
builder: (context, ref, child) {
|
child: Consumer(
|
||||||
final searchResult = ref.watch(
|
builder: (context, ref, child) {
|
||||||
searchAccountsProvider(query: searchController.text),
|
final searchResult = ref.watch(
|
||||||
);
|
searchAccountsProvider(query: searchController.text),
|
||||||
|
);
|
||||||
|
|
||||||
return searchResult.when(
|
return searchResult.when(
|
||||||
data:
|
data:
|
||||||
(accounts) => ListView.builder(
|
(accounts) => ListView.builder(
|
||||||
itemCount: accounts.length,
|
itemCount: accounts.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final account = accounts[index];
|
final account = accounts[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: ProfilePictureWidget(
|
leading: ProfilePictureWidget(
|
||||||
fileId: account.profile.pictureId,
|
fileId: account.profile.pictureId,
|
||||||
),
|
),
|
||||||
title: Text(account.nick),
|
title: Text(account.nick),
|
||||||
subtitle: Text('@${account.name}'),
|
subtitle: Text('@${account.name}'),
|
||||||
onTap: () => Navigator.of(context).pop(account),
|
onTap: () => Navigator.of(context).pop(account),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
loading:
|
loading:
|
||||||
() => const Center(child: CircularProgressIndicator()),
|
() => const Center(child: CircularProgressIndicator()),
|
||||||
error:
|
error: (error, stack) => Center(child: Text('Error: $error')),
|
||||||
(error, stack) => Center(child: Text('Error: $error')),
|
);
|
||||||
);
|
},
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:flutter_quill/flutter_quill.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
@ -12,7 +11,7 @@ import 'package:island/route.gr.dart';
|
|||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/content/cloud_file_collection.dart';
|
import 'package:island/widgets/content/cloud_file_collection.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/quill_content.dart';
|
import 'package:island/widgets/content/markdown.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:super_context_menu/super_context_menu.dart';
|
import 'package:super_context_menu/super_context_menu.dart';
|
||||||
@ -22,12 +21,14 @@ class PostItem extends HookConsumerWidget {
|
|||||||
final EdgeInsets? padding;
|
final EdgeInsets? padding;
|
||||||
final bool isOpenable;
|
final bool isOpenable;
|
||||||
final Function? onRefresh;
|
final Function? onRefresh;
|
||||||
|
final Function(SnPost)? onUpdate;
|
||||||
const PostItem({
|
const PostItem({
|
||||||
super.key,
|
super.key,
|
||||||
required this.item,
|
required this.item,
|
||||||
this.padding,
|
this.padding,
|
||||||
this.isOpenable = true,
|
this.isOpenable = true,
|
||||||
this.onRefresh,
|
this.onRefresh,
|
||||||
|
this.onUpdate,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -113,9 +114,7 @@ class PostItem extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(item.publisher.nick).bold(),
|
Text(item.publisher.nick).bold(),
|
||||||
if (item.content?.isNotEmpty ?? false)
|
if (item.content?.isNotEmpty ?? false)
|
||||||
QuillContent(
|
MarkdownTextContent(content: item.content!),
|
||||||
document: Document.fromJson(item.content!),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -129,6 +128,19 @@ class PostItem extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
if (item.attachments.isNotEmpty)
|
if (item.attachments.isNotEmpty)
|
||||||
CloudFileList(files: item.attachments),
|
CloudFileList(files: item.attachments),
|
||||||
|
PostReactionList(
|
||||||
|
parentId: item.id,
|
||||||
|
reactions: item.reactionsCount,
|
||||||
|
padding: EdgeInsets.only(left: 48),
|
||||||
|
onReact: (symbol, attitude, delta) {
|
||||||
|
final reactionsCount = Map<String, int>.from(
|
||||||
|
item.reactionsCount,
|
||||||
|
);
|
||||||
|
reactionsCount[symbol] =
|
||||||
|
(reactionsCount[symbol] ?? 0) + delta;
|
||||||
|
onUpdate?.call(item.copyWith(reactionsCount: reactionsCount));
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -136,3 +148,214 @@ class PostItem extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PostReactionList extends HookConsumerWidget {
|
||||||
|
final int parentId;
|
||||||
|
final Map<String, int> reactions;
|
||||||
|
final Function(String symbol, int attitude, int delta) onReact;
|
||||||
|
final EdgeInsets? padding;
|
||||||
|
const PostReactionList({
|
||||||
|
super.key,
|
||||||
|
required this.parentId,
|
||||||
|
required this.reactions,
|
||||||
|
this.padding,
|
||||||
|
required this.onReact,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final submitting = useState(false);
|
||||||
|
|
||||||
|
Future<void> reactPost(String symbol, int attitude) async {
|
||||||
|
final client = ref.watch(apiClientProvider);
|
||||||
|
submitting.value = true;
|
||||||
|
await client
|
||||||
|
.post(
|
||||||
|
'/posts/$parentId/reactions',
|
||||||
|
data: {'symbol': symbol, 'attitude': attitude},
|
||||||
|
)
|
||||||
|
.catchError((err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
return err;
|
||||||
|
})
|
||||||
|
.then((resp) {
|
||||||
|
var isRemoving = resp.statusCode == 204;
|
||||||
|
onReact(symbol, attitude, isRemoving ? -1 : 1);
|
||||||
|
HapticFeedback.heavyImpact();
|
||||||
|
});
|
||||||
|
submitting.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SizedBox(
|
||||||
|
height: 28,
|
||||||
|
child: ListView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
padding: padding ?? EdgeInsets.zero,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8),
|
||||||
|
child: ActionChip(
|
||||||
|
avatar: Icon(Symbols.add_reaction),
|
||||||
|
label: Text('react').tr(),
|
||||||
|
visualDensity: const VisualDensity(
|
||||||
|
horizontal: VisualDensity.minimumDensity,
|
||||||
|
vertical: VisualDensity.minimumDensity,
|
||||||
|
),
|
||||||
|
onPressed:
|
||||||
|
submitting.value
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return _PostReactionSheet(
|
||||||
|
reactionsCount: reactions,
|
||||||
|
onReact: (symbol, attitude) {
|
||||||
|
reactPost(symbol, attitude);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
for (final symbol in reactions.keys)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8),
|
||||||
|
child: ActionChip(
|
||||||
|
avatar: Text(kReactionTemplates[symbol]?.icon ?? '?'),
|
||||||
|
label: Row(
|
||||||
|
spacing: 4,
|
||||||
|
children: [
|
||||||
|
Text(symbol),
|
||||||
|
Text('x${reactions[symbol]}').bold(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onPressed:
|
||||||
|
submitting.value
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
reactPost(
|
||||||
|
symbol,
|
||||||
|
kReactionTemplates[symbol]?.attitude ?? 0,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
visualDensity: const VisualDensity(
|
||||||
|
horizontal: VisualDensity.minimumDensity,
|
||||||
|
vertical: VisualDensity.minimumDensity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PostReactionSheet extends StatelessWidget {
|
||||||
|
final Map<String, int> reactionsCount;
|
||||||
|
final Function(String symbol, int attitude) onReact;
|
||||||
|
const _PostReactionSheet({
|
||||||
|
required this.reactionsCount,
|
||||||
|
required this.onReact,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 16, left: 20, right: 16, bottom: 12),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'reactions'.plural(
|
||||||
|
reactionsCount.isNotEmpty
|
||||||
|
? reactionsCount.values.reduce((a, b) => a + b)
|
||||||
|
: 0,
|
||||||
|
),
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
letterSpacing: -0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.close),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1),
|
||||||
|
Expanded(
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
_buildReactionSection(context, 'Positive Reactions', 0),
|
||||||
|
_buildReactionSection(context, 'Neutral Reactions', 1),
|
||||||
|
_buildReactionSection(context, 'Negative Reactions', 2),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildReactionSection(
|
||||||
|
BuildContext context,
|
||||||
|
String title,
|
||||||
|
int attitude,
|
||||||
|
) {
|
||||||
|
final allReactions =
|
||||||
|
kReactionTemplates.entries
|
||||||
|
.where((entry) => entry.value.attitude == attitude)
|
||||||
|
.map((entry) => entry.key)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(title).fontSize(20).bold().padding(horizontal: 20, vertical: 12),
|
||||||
|
SizedBox(
|
||||||
|
height: 84,
|
||||||
|
child: GridView.builder(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 1,
|
||||||
|
mainAxisExtent: 100,
|
||||||
|
mainAxisSpacing: 8.0,
|
||||||
|
crossAxisSpacing: 8.0,
|
||||||
|
childAspectRatio: 2.0,
|
||||||
|
),
|
||||||
|
itemCount: allReactions.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final symbol = allReactions[index];
|
||||||
|
final count = reactionsCount[symbol] ?? 0;
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
onReact(symbol, attitude);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: GridTile(
|
||||||
|
header: Text(
|
||||||
|
kReactionTemplates[symbol]?.icon ?? '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
).fontSize(24),
|
||||||
|
footer: Text(
|
||||||
|
count > 0 ? 'x$count' : '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
).bold().padding(bottom: 12),
|
||||||
|
child: Center(
|
||||||
|
child: Text(symbol, textAlign: TextAlign.center),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -70,7 +70,8 @@ class PostQuickReply extends HookConsumerWidget {
|
|||||||
radius: 16,
|
radius: 16,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showCupertinoModalBottomSheet(
|
showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => PublisherModal(),
|
builder: (context) => PublisherModal(),
|
||||||
).then((value) {
|
).then((value) {
|
||||||
|
@ -22,66 +22,62 @@ class PublisherModal extends HookConsumerWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Material(
|
child: publishers.when(
|
||||||
color: Colors.transparent,
|
data:
|
||||||
child: publishers.when(
|
(value) =>
|
||||||
data:
|
value.isEmpty
|
||||||
(value) =>
|
? ConstrainedBox(
|
||||||
value.isEmpty
|
constraints: BoxConstraints(maxWidth: 280),
|
||||||
? ConstrainedBox(
|
child:
|
||||||
constraints: BoxConstraints(maxWidth: 280),
|
Column(
|
||||||
child:
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
Column(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment:
|
children: [
|
||||||
CrossAxisAlignment.center,
|
Text(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
'publishersEmpty',
|
||||||
children: [
|
textAlign: TextAlign.center,
|
||||||
Text(
|
).tr().fontSize(17).bold(),
|
||||||
'publishersEmpty',
|
Text(
|
||||||
textAlign: TextAlign.center,
|
'publishersEmptyDescription',
|
||||||
).tr().fontSize(17).bold(),
|
textAlign: TextAlign.center,
|
||||||
Text(
|
).tr(),
|
||||||
'publishersEmptyDescription',
|
const Gap(12),
|
||||||
textAlign: TextAlign.center,
|
ElevatedButton(
|
||||||
).tr(),
|
onPressed: () {
|
||||||
const Gap(12),
|
context.router
|
||||||
ElevatedButton(
|
.push(NewPublisherRoute())
|
||||||
onPressed: () {
|
.then((value) {
|
||||||
context.router
|
if (value != null) {
|
||||||
.push(NewPublisherRoute())
|
ref.invalidate(
|
||||||
.then((value) {
|
publishersManagedProvider,
|
||||||
if (value != null) {
|
);
|
||||||
ref.invalidate(
|
}
|
||||||
publishersManagedProvider,
|
});
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Text('createPublisher').tr(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).center(),
|
|
||||||
)
|
|
||||||
: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
for (final publisher in value)
|
|
||||||
ListTile(
|
|
||||||
leading: ProfilePictureWidget(
|
|
||||||
fileId: publisher.picture?.id,
|
|
||||||
),
|
|
||||||
title: Text(publisher.nick),
|
|
||||||
subtitle: Text('@${publisher.name}'),
|
|
||||||
onTap: () {
|
|
||||||
Navigator.pop(context, publisher);
|
|
||||||
},
|
},
|
||||||
|
child: Text('createPublisher').tr(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
).center(),
|
||||||
|
)
|
||||||
|
: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
for (final publisher in value)
|
||||||
|
ListTile(
|
||||||
|
leading: ProfilePictureWidget(
|
||||||
|
fileId: publisher.picture?.id,
|
||||||
|
),
|
||||||
|
title: Text(publisher.nick),
|
||||||
|
subtitle: Text('@${publisher.name}'),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context, publisher);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
),
|
||||||
error: (e, _) => Text('Error: $e'),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
),
|
error: (e, _) => Text('Error: $e'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
import 'package:flutter_quill/flutter_quill.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
|
|
||||||
class QuillContent extends HookConsumerWidget {
|
|
||||||
final Document document;
|
|
||||||
const QuillContent({super.key, required this.document});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final controller = useMemoized(() => QuillController.basic());
|
|
||||||
|
|
||||||
useEffect(() {
|
|
||||||
controller.document = document;
|
|
||||||
controller.readOnly = true;
|
|
||||||
return null;
|
|
||||||
}, [document]);
|
|
||||||
|
|
||||||
return QuillEditor.basic(
|
|
||||||
controller: controller,
|
|
||||||
config: const QuillEditorConfig(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,7 +19,6 @@ import media_kit_libs_macos_video
|
|||||||
import media_kit_video
|
import media_kit_video
|
||||||
import package_info_plus
|
import package_info_plus
|
||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
import quill_native_bridge_macos
|
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import sqflite_darwin
|
import sqflite_darwin
|
||||||
import sqlite3_flutter_libs
|
import sqlite3_flutter_libs
|
||||||
@ -43,7 +42,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
||||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
QuillNativeBridgePlugin.register(with: registry.registrar(forPlugin: "QuillNativeBridgePlugin"))
|
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin"))
|
Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin"))
|
||||||
|
200
pubspec.lock
200
pubspec.lock
@ -313,14 +313,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.6"
|
version: "3.0.6"
|
||||||
csslib:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: csslib
|
|
||||||
sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.2"
|
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -361,14 +353,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0+7.3.0"
|
version: "1.0.0+7.3.0"
|
||||||
dart_quill_delta:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: dart_quill_delta
|
|
||||||
sha256: bddb0b2948bd5b5a328f1651764486d162c59a8ccffd4c63e8b2c5e44be1dac4
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "10.8.3"
|
|
||||||
dart_style:
|
dart_style:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -401,14 +385,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.2"
|
version: "7.0.2"
|
||||||
diff_match_patch:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: diff_match_patch
|
|
||||||
sha256: "2efc9e6e8f449d0abe15be240e2c2a3bcd977c8d126cfd70598aee60af35c0a4"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.4.1"
|
|
||||||
dio:
|
dio:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -429,18 +405,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: drift
|
name: drift
|
||||||
sha256: "14a61af39d4584faf1d73b5b35e4b758a43008cf4c0fdb0576ec8e7032c0d9a5"
|
sha256: b584ddeb2b74436735dd2cf746d2d021e19a9a6770f409212fd5cbc2814ada85
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.26.0"
|
version: "2.26.1"
|
||||||
drift_dev:
|
drift_dev:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: drift_dev
|
name: drift_dev
|
||||||
sha256: "0d3f8b33b76cf1c6a82ee34d9511c40957549c4674b8f1688609e6d6c7306588"
|
sha256: "54dc207c6e4662741f60e5752678df183957ab907754ffab0372a7082f6d2816"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.26.0"
|
version: "2.26.1"
|
||||||
drift_flutter:
|
drift_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -473,6 +449,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
version: "3.0.0"
|
||||||
|
expandable:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: expandable
|
||||||
|
sha256: "9604d612d4d1146dafa96c6d8eec9c2ff0994658d6d09fed720ab788c7f5afc2"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.1"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -614,14 +598,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.4.1"
|
version: "3.4.1"
|
||||||
flutter_colorpicker:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_colorpicker
|
|
||||||
sha256: "969de5f6f9e2a570ac660fb7b501551451ea2a1ab9e2097e89475f60e07816ea"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.0"
|
|
||||||
flutter_expandable_fab:
|
flutter_expandable_fab:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -710,46 +686,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.0"
|
version: "0.6.0"
|
||||||
flutter_keyboard_visibility_linux:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_keyboard_visibility_linux
|
|
||||||
sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.0"
|
|
||||||
flutter_keyboard_visibility_macos:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_keyboard_visibility_macos
|
|
||||||
sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.0"
|
|
||||||
flutter_keyboard_visibility_platform_interface:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_keyboard_visibility_platform_interface
|
|
||||||
sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.0"
|
|
||||||
flutter_keyboard_visibility_temp_fork:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_keyboard_visibility_temp_fork
|
|
||||||
sha256: e3d02900640fbc1129245540db16944a0898b8be81694f4bf04b6c985bed9048
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.5"
|
|
||||||
flutter_keyboard_visibility_windows:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_keyboard_visibility_windows
|
|
||||||
sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.0"
|
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -803,22 +739,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.28"
|
version: "2.0.28"
|
||||||
flutter_quill:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: flutter_quill
|
|
||||||
sha256: de019f6160023d36ad3e89343da6d740ab66ae7839875c89871fbeabcb9e8f9b
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "11.4.0"
|
|
||||||
flutter_quill_delta_from_html:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_quill_delta_from_html
|
|
||||||
sha256: "4597bd0853a704696837aa6b05cffd851f587b176204c234edddfed1c1862a09"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.5.2"
|
|
||||||
flutter_riverpod:
|
flutter_riverpod:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -853,6 +773,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
font_awesome_flutter:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: font_awesome_flutter
|
||||||
|
sha256: d3a89184101baec7f4600d58840a764d2ef760fe1c5a20ef9e6b0e9b24a07a3a
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "10.8.0"
|
||||||
freezed:
|
freezed:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -933,14 +861,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.3.0"
|
version: "4.3.0"
|
||||||
html:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: html
|
|
||||||
sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.15.6"
|
|
||||||
http:
|
http:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1149,6 +1069,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.3.0"
|
version: "7.3.0"
|
||||||
|
markdown_editor_plus:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: markdown_editor_plus
|
||||||
|
sha256: "8a4749e5b80330674dc20c65281fb2171ff583136a5ffb269802bd8fe818a7ce"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.15"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1437,78 +1365,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.0"
|
version: "1.5.0"
|
||||||
quill_native_bridge:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: quill_native_bridge
|
|
||||||
sha256: "00752aca7d67cbd3254709a47558be78427750cb81aa42cfbed354d4a079bcfa"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "11.0.1"
|
|
||||||
quill_native_bridge_android:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: quill_native_bridge_android
|
|
||||||
sha256: b75c7e6ede362a7007f545118e756b1f19053994144ec9eda932ce5e54a57569
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.1+2"
|
|
||||||
quill_native_bridge_ios:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: quill_native_bridge_ios
|
|
||||||
sha256: d23de3cd7724d482fe2b514617f8eedc8f296e120fb297368917ac3b59d8099f
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.1"
|
|
||||||
quill_native_bridge_linux:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: quill_native_bridge_linux
|
|
||||||
sha256: "5fcc60cab2ab9079e0746941f05c5ca5fec85cc050b738c8c8b9da7c09da17eb"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.1"
|
|
||||||
quill_native_bridge_macos:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: quill_native_bridge_macos
|
|
||||||
sha256: "1c0631bd1e2eee765a8b06017c5286a4e829778f4585736e048eb67c97af8a77"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.1"
|
|
||||||
quill_native_bridge_platform_interface:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: quill_native_bridge_platform_interface
|
|
||||||
sha256: "8264a2bdb8a294c31377a27b46c0f8717fa9f968cf113f7dc52d332ed9c84526"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.2+1"
|
|
||||||
quill_native_bridge_web:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: quill_native_bridge_web
|
|
||||||
sha256: "7c723f6824b0250d7f33e8b6c23f2f8eb0103fe48ee7ebf47ab6786b64d5c05d"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.2"
|
|
||||||
quill_native_bridge_windows:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: quill_native_bridge_windows
|
|
||||||
sha256: "60e50d74238f22ceb43113d9a42b6627451dab9fc27f527b979a32051cf1da45"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.1"
|
|
||||||
quiver:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: quiver
|
|
||||||
sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.2.2"
|
|
||||||
recase:
|
recase:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -83,13 +83,13 @@ dependencies:
|
|||||||
flutter_udid: ^4.0.0
|
flutter_udid: ^4.0.0
|
||||||
firebase_core: ^3.13.0
|
firebase_core: ^3.13.0
|
||||||
web_socket_channel: ^3.0.3
|
web_socket_channel: ^3.0.3
|
||||||
flutter_quill: ^11.4.0
|
|
||||||
material_symbols_icons: ^4.2815.0
|
material_symbols_icons: ^4.2815.0
|
||||||
drift: ^2.26.0
|
drift: ^2.26.0
|
||||||
drift_flutter: ^0.2.4
|
drift_flutter: ^0.2.4
|
||||||
path: ^1.9.1
|
path: ^1.9.1
|
||||||
collection: ^1.19.1
|
collection: ^1.19.1
|
||||||
flutter_expandable_fab: ^2.5.0
|
flutter_expandable_fab: ^2.5.0
|
||||||
|
markdown_editor_plus: ^0.2.15
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user