🐛 Bug fixes on posts writing and etc
This commit is contained in:
parent
13ea182707
commit
f479b9fc8b
@ -690,5 +690,8 @@
|
|||||||
"aboutScreenCopyright": "© {} {}. All rights reserved.",
|
"aboutScreenCopyright": "© {} {}. All rights reserved.",
|
||||||
"aboutScreenFailedToLoadPackageInfo": "Failed to load package info: {error}",
|
"aboutScreenFailedToLoadPackageInfo": "Failed to load package info: {error}",
|
||||||
"copiedToClipboard": "Copied to clipboard",
|
"copiedToClipboard": "Copied to clipboard",
|
||||||
"copyToClipboardTooltip": "Copy to clipboard"
|
"copyToClipboardTooltip": "Copy to clipboard",
|
||||||
|
"postForwardingTo": "Forwarding to",
|
||||||
|
"postReplyingTo": "Replying to",
|
||||||
|
"postEditing": "You are editing an existing post"
|
||||||
}
|
}
|
@ -9,6 +9,7 @@ import 'package:flutter/foundation.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:go_router/go_router.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';
|
||||||
@ -45,6 +46,10 @@ void main() async {
|
|||||||
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (kIsWeb) {
|
||||||
|
GoRouter.optionURLReflectsImperativeAPIs = true;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await EasyLocalization.ensureInitialized();
|
await EasyLocalization.ensureInitialized();
|
||||||
await Firebase.initializeApp(
|
await Firebase.initializeApp(
|
||||||
|
@ -65,6 +65,9 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
builder:
|
builder:
|
||||||
(context, state) => PostComposeScreen(
|
(context, state) => PostComposeScreen(
|
||||||
initialState: state.extra as PostComposeInitialState?,
|
initialState: state.extra as PostComposeInitialState?,
|
||||||
|
type:
|
||||||
|
int.tryParse(state.uri.queryParameters['type'] ?? '0') ??
|
||||||
|
0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
|
@ -108,15 +108,18 @@ class CreatorHubShellScreen extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isWide = isWideScreen(context);
|
final isWide = isWideScreen(context);
|
||||||
if (isWide) {
|
if (isWide) {
|
||||||
return Row(
|
return AppBackground(
|
||||||
|
isRoot: true,
|
||||||
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(width: 360, child: const CreatorHubScreen(isAside: true)),
|
SizedBox(width: 360, child: const CreatorHubScreen(isAside: true)),
|
||||||
const VerticalDivider(width: 1),
|
const VerticalDivider(width: 1),
|
||||||
Expanded(child: child),
|
Expanded(child: child),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return child;
|
return AppBackground(isRoot: true, child: child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +201,6 @@ class CreatorHubScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: false,
|
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: !isWide ? const PageBackButton() : null,
|
leading: !isWide ? const PageBackButton() : null,
|
||||||
title: Text('creatorHub').tr(),
|
title: Text('creatorHub').tr(),
|
||||||
|
@ -26,7 +26,7 @@ class CreatorPostListScreen extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Symbols.edit),
|
leading: const Icon(Symbols.edit),
|
||||||
title: Text('postContent'.tr()),
|
title: Text('Post'),
|
||||||
subtitle: Text('Create a regular post'),
|
subtitle: Text('Create a regular post'),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
@ -47,15 +47,21 @@ class DeveloperHubShellScreen extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isWide = isWideScreen(context);
|
final isWide = isWideScreen(context);
|
||||||
if (isWide) {
|
if (isWide) {
|
||||||
return Row(
|
return AppBackground(
|
||||||
|
isRoot: true,
|
||||||
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(width: 360, child: const DeveloperHubScreen(isAside: true)),
|
SizedBox(
|
||||||
|
width: 360,
|
||||||
|
child: const DeveloperHubScreen(isAside: true),
|
||||||
|
),
|
||||||
const VerticalDivider(width: 1),
|
const VerticalDivider(width: 1),
|
||||||
Expanded(child: child),
|
Expanded(child: child),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return child;
|
return AppBackground(isRoot: true, child: child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@ sealed class PostComposeInitialState with _$PostComposeInitialState {
|
|||||||
String? content,
|
String? content,
|
||||||
@Default([]) List<UniversalFile> attachments,
|
@Default([]) List<UniversalFile> attachments,
|
||||||
int? visibility,
|
int? visibility,
|
||||||
|
SnPost? replyingTo,
|
||||||
|
SnPost? forwardingTo,
|
||||||
}) = _PostComposeInitialState;
|
}) = _PostComposeInitialState;
|
||||||
|
|
||||||
factory PostComposeInitialState.fromJson(Map<String, dynamic> json) =>
|
factory PostComposeInitialState.fromJson(Map<String, dynamic> json) =>
|
||||||
@ -66,23 +68,22 @@ class PostEditScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
class PostComposeScreen extends HookConsumerWidget {
|
class PostComposeScreen extends HookConsumerWidget {
|
||||||
final SnPost? originalPost;
|
final SnPost? originalPost;
|
||||||
final SnPost? repliedPost;
|
|
||||||
final SnPost? forwardedPost;
|
|
||||||
final int? type;
|
final int? type;
|
||||||
final PostComposeInitialState? initialState;
|
final PostComposeInitialState? initialState;
|
||||||
const PostComposeScreen({
|
const PostComposeScreen({
|
||||||
super.key,
|
super.key,
|
||||||
this.originalPost,
|
|
||||||
this.repliedPost,
|
|
||||||
this.forwardedPost,
|
|
||||||
this.type,
|
this.type,
|
||||||
this.initialState,
|
this.initialState,
|
||||||
|
this.originalPost,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
// Determine the compose type: auto-detect from edited post or use query parameter
|
// Determine the compose type: auto-detect from edited post or use query parameter
|
||||||
final composeType = originalPost?.type ?? type ?? 0;
|
final composeType = originalPost?.type ?? type ?? 0;
|
||||||
|
final repliedPost = initialState?.replyingTo ?? originalPost?.repliedPost;
|
||||||
|
final forwardedPost =
|
||||||
|
initialState?.forwardingTo ?? originalPost?.forwardedPost;
|
||||||
|
|
||||||
// If type is 1 (article), return ArticleComposeScreen
|
// If type is 1 (article), return ArticleComposeScreen
|
||||||
if (composeType == 1) {
|
if (composeType == 1) {
|
||||||
@ -136,8 +137,11 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
// Initialize publisher once when data is available
|
// Initialize publisher once when data is available
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
if (publishers.value?.isNotEmpty ?? false) {
|
if (publishers.value?.isNotEmpty ?? false) {
|
||||||
|
if (state.currentPublisher.value == null) {
|
||||||
|
// If no publisher is set, use the first available one
|
||||||
state.currentPublisher.value = publishers.value!.first;
|
state.currentPublisher.value = publishers.value!.first;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}, [publishers]);
|
}, [publishers]);
|
||||||
|
|
||||||
@ -480,8 +484,10 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
Widget _buildInfoBanner(BuildContext context) {
|
Widget _buildInfoBanner(BuildContext context) {
|
||||||
// When editing, preserve the original replied/forwarded post references
|
// When editing, preserve the original replied/forwarded post references
|
||||||
final effectiveRepliedPost = repliedPost ?? originalPost?.repliedPost;
|
final effectiveRepliedPost =
|
||||||
final effectiveForwardedPost = forwardedPost ?? originalPost?.forwardedPost;
|
initialState?.replyingTo ?? originalPost?.repliedPost;
|
||||||
|
final effectiveForwardedPost =
|
||||||
|
initialState?.forwardingTo ?? originalPost?.forwardedPost;
|
||||||
|
|
||||||
// Show editing banner when editing a post
|
// Show editing banner when editing a post
|
||||||
if (originalPost != null) {
|
if (originalPost != null) {
|
||||||
@ -497,15 +503,15 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
size: 16,
|
size: 16,
|
||||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||||
),
|
),
|
||||||
const Gap(4),
|
const Gap(8),
|
||||||
Text(
|
Text(
|
||||||
'edit'.tr(),
|
'postEditing'.tr(),
|
||||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(all: 16),
|
).padding(horizontal: 16, vertical: 8),
|
||||||
),
|
),
|
||||||
// Show reply/forward banners below editing banner if they exist
|
// Show reply/forward banners below editing banner if they exist
|
||||||
if (effectiveRepliedPost != null)
|
if (effectiveRepliedPost != null)
|
||||||
@ -615,6 +621,7 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
builder:
|
builder:
|
||||||
(context) => DraggableScrollableSheet(
|
(context) => DraggableScrollableSheet(
|
||||||
initialChildSize: 0.7,
|
initialChildSize: 0.7,
|
||||||
|
@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$PostComposeInitialState {
|
mixin _$PostComposeInitialState {
|
||||||
|
|
||||||
String? get title; String? get description; String? get content; List<UniversalFile> get attachments; int? get visibility;
|
String? get title; String? get description; String? get content; List<UniversalFile> get attachments; int? get visibility; SnPost? get replyingTo; SnPost? get forwardingTo;
|
||||||
/// Create a copy of PostComposeInitialState
|
/// Create a copy of PostComposeInitialState
|
||||||
/// 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 @@ $PostComposeInitialStateCopyWith<PostComposeInitialState> get copyWith => _$Post
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is PostComposeInitialState&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.visibility, visibility) || other.visibility == visibility));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is PostComposeInitialState&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.replyingTo, replyingTo) || other.replyingTo == replyingTo)&&(identical(other.forwardingTo, forwardingTo) || other.forwardingTo == forwardingTo));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,title,description,content,const DeepCollectionEquality().hash(attachments),visibility);
|
int get hashCode => Object.hash(runtimeType,title,description,content,const DeepCollectionEquality().hash(attachments),visibility,replyingTo,forwardingTo);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'PostComposeInitialState(title: $title, description: $description, content: $content, attachments: $attachments, visibility: $visibility)';
|
return 'PostComposeInitialState(title: $title, description: $description, content: $content, attachments: $attachments, visibility: $visibility, replyingTo: $replyingTo, forwardingTo: $forwardingTo)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -49,11 +49,11 @@ abstract mixin class $PostComposeInitialStateCopyWith<$Res> {
|
|||||||
factory $PostComposeInitialStateCopyWith(PostComposeInitialState value, $Res Function(PostComposeInitialState) _then) = _$PostComposeInitialStateCopyWithImpl;
|
factory $PostComposeInitialStateCopyWith(PostComposeInitialState value, $Res Function(PostComposeInitialState) _then) = _$PostComposeInitialStateCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String? title, String? description, String? content, List<UniversalFile> attachments, int? visibility
|
String? title, String? description, String? content, List<UniversalFile> attachments, int? visibility, SnPost? replyingTo, SnPost? forwardingTo
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$SnPostCopyWith<$Res>? get replyingTo;$SnPostCopyWith<$Res>? get forwardingTo;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -66,17 +66,43 @@ class _$PostComposeInitialStateCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of PostComposeInitialState
|
/// Create a copy of PostComposeInitialState
|
||||||
/// 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? title = freezed,Object? description = freezed,Object? content = freezed,Object? attachments = null,Object? visibility = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? title = freezed,Object? description = freezed,Object? content = freezed,Object? attachments = null,Object? visibility = freezed,Object? replyingTo = freezed,Object? forwardingTo = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
as String?,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
as String?,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||||
as List<UniversalFile>,visibility: freezed == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
as List<UniversalFile>,visibility: freezed == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
||||||
as int?,
|
as int?,replyingTo: freezed == replyingTo ? _self.replyingTo : replyingTo // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnPost?,forwardingTo: freezed == forwardingTo ? _self.forwardingTo : forwardingTo // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnPost?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
/// Create a copy of PostComposeInitialState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnPostCopyWith<$Res>? get replyingTo {
|
||||||
|
if (_self.replyingTo == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnPostCopyWith<$Res>(_self.replyingTo!, (value) {
|
||||||
|
return _then(_self.copyWith(replyingTo: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of PostComposeInitialState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnPostCopyWith<$Res>? get forwardingTo {
|
||||||
|
if (_self.forwardingTo == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnPostCopyWith<$Res>(_self.forwardingTo!, (value) {
|
||||||
|
return _then(_self.copyWith(forwardingTo: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -84,7 +110,7 @@ as int?,
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _PostComposeInitialState implements PostComposeInitialState {
|
class _PostComposeInitialState implements PostComposeInitialState {
|
||||||
const _PostComposeInitialState({this.title, this.description, this.content, final List<UniversalFile> attachments = const [], this.visibility}): _attachments = attachments;
|
const _PostComposeInitialState({this.title, this.description, this.content, final List<UniversalFile> attachments = const [], this.visibility, this.replyingTo, this.forwardingTo}): _attachments = attachments;
|
||||||
factory _PostComposeInitialState.fromJson(Map<String, dynamic> json) => _$PostComposeInitialStateFromJson(json);
|
factory _PostComposeInitialState.fromJson(Map<String, dynamic> json) => _$PostComposeInitialStateFromJson(json);
|
||||||
|
|
||||||
@override final String? title;
|
@override final String? title;
|
||||||
@ -98,6 +124,8 @@ class _PostComposeInitialState implements PostComposeInitialState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override final int? visibility;
|
@override final int? visibility;
|
||||||
|
@override final SnPost? replyingTo;
|
||||||
|
@override final SnPost? forwardingTo;
|
||||||
|
|
||||||
/// Create a copy of PostComposeInitialState
|
/// Create a copy of PostComposeInitialState
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@ -112,16 +140,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PostComposeInitialState&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.visibility, visibility) || other.visibility == visibility));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PostComposeInitialState&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.replyingTo, replyingTo) || other.replyingTo == replyingTo)&&(identical(other.forwardingTo, forwardingTo) || other.forwardingTo == forwardingTo));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,title,description,content,const DeepCollectionEquality().hash(_attachments),visibility);
|
int get hashCode => Object.hash(runtimeType,title,description,content,const DeepCollectionEquality().hash(_attachments),visibility,replyingTo,forwardingTo);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'PostComposeInitialState(title: $title, description: $description, content: $content, attachments: $attachments, visibility: $visibility)';
|
return 'PostComposeInitialState(title: $title, description: $description, content: $content, attachments: $attachments, visibility: $visibility, replyingTo: $replyingTo, forwardingTo: $forwardingTo)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -132,11 +160,11 @@ abstract mixin class _$PostComposeInitialStateCopyWith<$Res> implements $PostCom
|
|||||||
factory _$PostComposeInitialStateCopyWith(_PostComposeInitialState value, $Res Function(_PostComposeInitialState) _then) = __$PostComposeInitialStateCopyWithImpl;
|
factory _$PostComposeInitialStateCopyWith(_PostComposeInitialState value, $Res Function(_PostComposeInitialState) _then) = __$PostComposeInitialStateCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String? title, String? description, String? content, List<UniversalFile> attachments, int? visibility
|
String? title, String? description, String? content, List<UniversalFile> attachments, int? visibility, SnPost? replyingTo, SnPost? forwardingTo
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@override $SnPostCopyWith<$Res>? get replyingTo;@override $SnPostCopyWith<$Res>? get forwardingTo;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -149,18 +177,44 @@ class __$PostComposeInitialStateCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of PostComposeInitialState
|
/// Create a copy of PostComposeInitialState
|
||||||
/// 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? title = freezed,Object? description = freezed,Object? content = freezed,Object? attachments = null,Object? visibility = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? title = freezed,Object? description = freezed,Object? content = freezed,Object? attachments = null,Object? visibility = freezed,Object? replyingTo = freezed,Object? forwardingTo = freezed,}) {
|
||||||
return _then(_PostComposeInitialState(
|
return _then(_PostComposeInitialState(
|
||||||
title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
as String?,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
as String?,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||||
as List<UniversalFile>,visibility: freezed == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
as List<UniversalFile>,visibility: freezed == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
||||||
as int?,
|
as int?,replyingTo: freezed == replyingTo ? _self.replyingTo : replyingTo // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnPost?,forwardingTo: freezed == forwardingTo ? _self.forwardingTo : forwardingTo // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnPost?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a copy of PostComposeInitialState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnPostCopyWith<$Res>? get replyingTo {
|
||||||
|
if (_self.replyingTo == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnPostCopyWith<$Res>(_self.replyingTo!, (value) {
|
||||||
|
return _then(_self.copyWith(replyingTo: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of PostComposeInitialState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnPostCopyWith<$Res>? get forwardingTo {
|
||||||
|
if (_self.forwardingTo == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnPostCopyWith<$Res>(_self.forwardingTo!, (value) {
|
||||||
|
return _then(_self.copyWith(forwardingTo: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dart format on
|
// dart format on
|
||||||
|
@ -18,6 +18,14 @@ _PostComposeInitialState _$PostComposeInitialStateFromJson(
|
|||||||
.toList() ??
|
.toList() ??
|
||||||
const [],
|
const [],
|
||||||
visibility: (json['visibility'] as num?)?.toInt(),
|
visibility: (json['visibility'] as num?)?.toInt(),
|
||||||
|
replyingTo:
|
||||||
|
json['replying_to'] == null
|
||||||
|
? null
|
||||||
|
: SnPost.fromJson(json['replying_to'] as Map<String, dynamic>),
|
||||||
|
forwardingTo:
|
||||||
|
json['forwarding_to'] == null
|
||||||
|
? null
|
||||||
|
: SnPost.fromJson(json['forwarding_to'] as Map<String, dynamic>),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$PostComposeInitialStateToJson(
|
Map<String, dynamic> _$PostComposeInitialStateToJson(
|
||||||
@ -28,4 +36,6 @@ Map<String, dynamic> _$PostComposeInitialStateToJson(
|
|||||||
'content': instance.content,
|
'content': instance.content,
|
||||||
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
||||||
'visibility': instance.visibility,
|
'visibility': instance.visibility,
|
||||||
|
'replying_to': instance.replyingTo?.toJson(),
|
||||||
|
'forwarding_to': instance.forwardingTo?.toJson(),
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,8 @@ Future<SnPost?> post(Ref ref, String id) async {
|
|||||||
return SnPost.fromJson(resp.data);
|
return SnPost.fromJson(resp.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
final postStateProvider = StateNotifierProvider.family<PostState, AsyncValue<SnPost?>, String>(
|
final postStateProvider =
|
||||||
|
StateNotifierProvider.family<PostState, AsyncValue<SnPost?>, String>(
|
||||||
(ref, id) => PostState(ref, id),
|
(ref, id) => PostState(ref, id),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -74,7 +75,9 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
backgroundColor: isWide ? Colors.transparent : null,
|
backgroundColor: isWide ? Colors.transparent : null,
|
||||||
onUpdate: (newItem) {
|
onUpdate: (newItem) {
|
||||||
// Update the local state with the new post data
|
// Update the local state with the new post data
|
||||||
ref.read(postStateProvider(id).notifier).updatePost(newItem);
|
ref
|
||||||
|
.read(postStateProvider(id).notifier)
|
||||||
|
.updatePost(newItem);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
@ -92,16 +95,21 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
right: 0,
|
right: 0,
|
||||||
child: Material(
|
child: Material(
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
child: postState.when(
|
child: postState
|
||||||
data: (post) => PostQuickReply(
|
.when(
|
||||||
|
data:
|
||||||
|
(post) => PostQuickReply(
|
||||||
parent: post!,
|
parent: post!,
|
||||||
onPosted: () {
|
onPosted: () {
|
||||||
ref.invalidate(postRepliesNotifierProvider(id));
|
ref.invalidate(
|
||||||
|
postRepliesNotifierProvider(id),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
loading: () => const SizedBox.shrink(),
|
loading: () => const SizedBox.shrink(),
|
||||||
error: (_, __) => const SizedBox.shrink(),
|
error: (_, _) => const SizedBox.shrink(),
|
||||||
).padding(
|
)
|
||||||
|
.padding(
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 16,
|
bottom: MediaQuery.of(context).padding.bottom + 16,
|
||||||
top: 16,
|
top: 16,
|
||||||
horizontal: 16,
|
horizontal: 16,
|
||||||
|
@ -98,19 +98,11 @@ class ComposeLogic {
|
|||||||
descriptionController: TextEditingController(
|
descriptionController: TextEditingController(
|
||||||
text: originalPost?.description,
|
text: originalPost?.description,
|
||||||
),
|
),
|
||||||
contentController: TextEditingController(
|
contentController: TextEditingController(text: originalPost?.content),
|
||||||
text:
|
|
||||||
originalPost?.content ??
|
|
||||||
(forwardedPost != null
|
|
||||||
? '''> ${forwardedPost.content}
|
|
||||||
|
|
||||||
'''
|
|
||||||
: null),
|
|
||||||
),
|
|
||||||
visibility: ValueNotifier<int>(originalPost?.visibility ?? 0),
|
visibility: ValueNotifier<int>(originalPost?.visibility ?? 0),
|
||||||
submitting: ValueNotifier<bool>(false),
|
submitting: ValueNotifier<bool>(false),
|
||||||
attachmentProgress: ValueNotifier<Map<int, double>>({}),
|
attachmentProgress: ValueNotifier<Map<int, double>>({}),
|
||||||
currentPublisher: ValueNotifier<SnPublisher?>(null),
|
currentPublisher: ValueNotifier<SnPublisher?>(originalPost?.publisher),
|
||||||
tagsController: tagsController,
|
tagsController: tagsController,
|
||||||
categoriesController: categoriesController,
|
categoriesController: categoriesController,
|
||||||
draftId: id,
|
draftId: id,
|
||||||
|
@ -11,6 +11,7 @@ import 'package:island/models/post.dart';
|
|||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
|
import 'package:island/screens/posts/compose.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
import 'package:island/services/time.dart';
|
import 'package:island/services/time.dart';
|
||||||
import 'package:island/widgets/account/account_name.dart';
|
import 'package:island/widgets/account/account_name.dart';
|
||||||
@ -116,14 +117,20 @@ class PostItem extends HookConsumerWidget {
|
|||||||
title: 'reply'.tr(),
|
title: 'reply'.tr(),
|
||||||
image: MenuImage.icon(Symbols.reply),
|
image: MenuImage.icon(Symbols.reply),
|
||||||
callback: () {
|
callback: () {
|
||||||
context.push('/posts/compose', extra: {'repliedPost': item});
|
context.push(
|
||||||
|
'/posts/compose',
|
||||||
|
extra: PostComposeInitialState(replyingTo: item),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
MenuAction(
|
MenuAction(
|
||||||
title: 'forward'.tr(),
|
title: 'forward'.tr(),
|
||||||
image: MenuImage.icon(Symbols.forward),
|
image: MenuImage.icon(Symbols.forward),
|
||||||
callback: () {
|
callback: () {
|
||||||
context.push('/posts/compose', extra: {'forwardedPost': item});
|
context.push(
|
||||||
|
'/posts/compose',
|
||||||
|
extra: PostComposeInitialState(forwardingTo: item),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
MenuSeparator(),
|
MenuSeparator(),
|
||||||
|
@ -87,7 +87,7 @@ class PostItemCreator extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Material(
|
child: Material(
|
||||||
color: Colors.transparent,
|
color: backgroundColor ?? Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
elevation: 1,
|
elevation: 1,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
|
@ -1025,7 +1025,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
flutter_web_plugins:
|
flutter_web_plugins:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
@ -1097,10 +1097,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: go_router
|
name: go_router
|
||||||
sha256: ac294be30ba841830cfa146e5a3b22bb09f8dc5a0fdd9ca9332b04b0bde99ebf
|
sha256: c489908a54ce2131f1d1b7cc631af9c1a06fac5ca7c449e959192089f9489431
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "15.2.4"
|
version: "16.0.0"
|
||||||
google_fonts:
|
google_fonts:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -30,6 +30,8 @@ environment:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_web_plugins:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
@ -37,7 +39,7 @@ dependencies:
|
|||||||
flutter_hooks: ^0.21.2
|
flutter_hooks: ^0.21.2
|
||||||
hooks_riverpod: ^2.6.1
|
hooks_riverpod: ^2.6.1
|
||||||
bitsdojo_window: ^0.1.6
|
bitsdojo_window: ^0.1.6
|
||||||
go_router: ^15.1.3
|
go_router: ^16.0.0
|
||||||
styled_widget: ^0.4.1
|
styled_widget: ^0.4.1
|
||||||
shared_preferences: ^2.5.3
|
shared_preferences: ^2.5.3
|
||||||
flutter_riverpod: ^2.6.1
|
flutter_riverpod: ^2.6.1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user