Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
d22eac5c10 | |||
e5381dd5e0 | |||
1c26944a05 |
@ -47,16 +47,19 @@ class ChatListShell extends StatelessWidget {
|
|||||||
direction: Axis.horizontal,
|
direction: Axis.horizontal,
|
||||||
divider: ResizableDivider(
|
divider: ResizableDivider(
|
||||||
thickness: 0.3,
|
thickness: 0.3,
|
||||||
color: Theme.of(context).dividerColor,
|
color: Theme.of(context).dividerColor.withOpacity(0.3),
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
const ResizableChild(
|
const ResizableChild(
|
||||||
minSize: 280,
|
minSize: 280,
|
||||||
maxSize: 520,
|
maxSize: 520,
|
||||||
size: ResizableSize.pixels(320),
|
size: ResizableSize.pixels(360),
|
||||||
child: ChatList(),
|
child: ChatList(),
|
||||||
),
|
),
|
||||||
ResizableChild(child: child ?? const EmptyPagePlaceholder()),
|
ResizableChild(
|
||||||
|
minSize: 280,
|
||||||
|
child: child ?? const EmptyPagePlaceholder(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
|
||||||
import 'package:solian/models/pagination.dart';
|
import 'package:solian/models/pagination.dart';
|
||||||
import 'package:solian/models/post.dart';
|
import 'package:solian/models/post.dart';
|
||||||
import 'package:solian/providers/content/posts.dart';
|
import 'package:solian/providers/content/posts.dart';
|
||||||
import 'package:solian/theme.dart';
|
import 'package:solian/theme.dart';
|
||||||
import 'package:solian/widgets/app_bar_leading.dart';
|
import 'package:solian/widgets/app_bar_leading.dart';
|
||||||
import 'package:solian/widgets/app_bar_title.dart';
|
import 'package:solian/widgets/app_bar_title.dart';
|
||||||
|
import 'package:solian/widgets/loading_indicator.dart';
|
||||||
import 'package:solian/widgets/posts/post_action.dart';
|
import 'package:solian/widgets/posts/post_action.dart';
|
||||||
import 'package:solian/widgets/posts/post_owned_list.dart';
|
import 'package:solian/widgets/posts/post_item.dart';
|
||||||
import 'package:solian/widgets/root_container.dart';
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
|
||||||
|
|
||||||
class DraftBoxScreen extends StatefulWidget {
|
class DraftBoxScreen extends StatefulWidget {
|
||||||
const DraftBoxScreen({super.key});
|
const DraftBoxScreen({super.key});
|
||||||
@ -19,38 +20,50 @@ class DraftBoxScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DraftBoxScreenState extends State<DraftBoxScreen> {
|
class _DraftBoxScreenState extends State<DraftBoxScreen> {
|
||||||
final PagingController<int, Post> _pagingController =
|
bool _isBusy = true;
|
||||||
PagingController(firstPageKey: 0);
|
int? _totalPosts;
|
||||||
|
final List<Post> _posts = List.empty(growable: true);
|
||||||
|
|
||||||
_getPosts(int pageKey) async {
|
_getPosts() async {
|
||||||
final PostProvider provider = Get.find();
|
setState(() => _isBusy = true);
|
||||||
|
|
||||||
Response resp;
|
final PostProvider posts = Get.find();
|
||||||
try {
|
final resp = await posts.listDraft(_posts.length);
|
||||||
resp = await provider.listDraft(pageKey);
|
|
||||||
} catch (e) {
|
|
||||||
_pagingController.error = e;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final PaginationResult result = PaginationResult.fromJson(resp.body);
|
final PaginationResult result = PaginationResult.fromJson(resp.body);
|
||||||
if (result.count == 0) {
|
|
||||||
_pagingController.appendLastPage([]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final parsed = result.data?.map((e) => Post.fromJson(e)).toList();
|
final parsed = result.data?.map((e) => Post.fromJson(e)).toList();
|
||||||
if (parsed != null && parsed.length >= 10) {
|
_totalPosts = result.count;
|
||||||
_pagingController.appendPage(parsed, pageKey + parsed.length);
|
_posts.addAll(parsed ?? List.empty());
|
||||||
} else if (parsed != null) {
|
|
||||||
_pagingController.appendLastPage(parsed);
|
setState(() => _isBusy = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _openActions(Post item) async {
|
||||||
|
showModalBottomSheet(
|
||||||
|
useRootNavigator: true,
|
||||||
|
context: context,
|
||||||
|
builder: (context) => PostAction(
|
||||||
|
item: item,
|
||||||
|
noReact: true,
|
||||||
|
),
|
||||||
|
).then((value) {
|
||||||
|
if (value is Future) {
|
||||||
|
value.then((_) {
|
||||||
|
_posts.clear();
|
||||||
|
_getPosts();
|
||||||
|
});
|
||||||
|
} else if (value != null) {
|
||||||
|
_posts.clear();
|
||||||
|
_getPosts();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_pagingController.addPageRequestListener(_getPosts);
|
_getPosts();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -68,47 +81,48 @@ class _DraftBoxScreenState extends State<DraftBoxScreen> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: RefreshIndicator(
|
body: Column(
|
||||||
onRefresh: () => Future.sync(() => _pagingController.refresh()),
|
children: [
|
||||||
child: PagedListView<int, Post>(
|
LoadingIndicator(isActive: _isBusy),
|
||||||
pagingController: _pagingController,
|
Expanded(
|
||||||
builderDelegate: PagedChildBuilderDelegate(
|
child: RefreshIndicator(
|
||||||
itemBuilder: (context, item, index) {
|
onRefresh: () {
|
||||||
return PostOwnedListEntry(
|
_posts.clear();
|
||||||
item: item,
|
return _getPosts();
|
||||||
isFullContent: true,
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).colorScheme.surfaceContainerLow,
|
|
||||||
onTap: () async {
|
|
||||||
showModalBottomSheet(
|
|
||||||
useRootNavigator: true,
|
|
||||||
context: context,
|
|
||||||
builder: (context) => PostAction(
|
|
||||||
item: item,
|
|
||||||
noReact: true,
|
|
||||||
),
|
|
||||||
).then((value) {
|
|
||||||
if (value is Future) {
|
|
||||||
value.then((_) {
|
|
||||||
_pagingController.refresh();
|
|
||||||
});
|
|
||||||
} else if (value != null) {
|
|
||||||
_pagingController.refresh();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
child: InfiniteList(
|
||||||
|
itemCount: _posts.length,
|
||||||
|
hasReachedMax: _totalPosts == _posts.length,
|
||||||
|
isLoading: _isBusy,
|
||||||
|
onFetchData: () => _getPosts(),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final item = _posts[index];
|
||||||
|
return Card(
|
||||||
|
child: GestureDetector(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
PostItem(
|
||||||
|
key: Key('p${item.id}'),
|
||||||
|
item: item,
|
||||||
|
isShowEmbed: false,
|
||||||
|
isClickable: false,
|
||||||
|
isShowReply: false,
|
||||||
|
isReactable: false,
|
||||||
|
onTapMore: () => _openActions(item),
|
||||||
|
).paddingSymmetric(vertical: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () => _openActions(item),
|
||||||
|
),
|
||||||
).paddingOnly(left: 12, right: 12, bottom: 4);
|
).paddingOnly(left: 12, right: 12, bottom: 4);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_pagingController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_animate/flutter_animate.dart';
|
import 'package:flutter_animate/flutter_animate.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@ -34,6 +35,24 @@ class ChatEventList extends StatelessWidget {
|
|||||||
return a.createdAt.difference(b.createdAt).inMinutes <= 3;
|
return a.createdAt.difference(b.createdAt).inMinutes <= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _openActions(BuildContext context, Event item) {
|
||||||
|
showModalBottomSheet(
|
||||||
|
useRootNavigator: true,
|
||||||
|
context: context,
|
||||||
|
builder: (context) => ChatEventAction(
|
||||||
|
channel: channel,
|
||||||
|
realm: channel.realm,
|
||||||
|
item: item,
|
||||||
|
onEdit: () {
|
||||||
|
onEdit(item);
|
||||||
|
},
|
||||||
|
onReply: () {
|
||||||
|
onReply(item);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
@ -65,7 +84,8 @@ class ChatEventList extends StatelessWidget {
|
|||||||
|
|
||||||
final item = chatController.currentEvents[index].data;
|
final item = chatController.currentEvents[index].data;
|
||||||
|
|
||||||
return GestureDetector(
|
return TapRegion(
|
||||||
|
child: GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
child: Builder(builder: (context) {
|
child: Builder(builder: (context) {
|
||||||
final widget = ChatEvent(
|
final widget = ChatEvent(
|
||||||
@ -94,21 +114,15 @@ class ChatEventList extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
showModalBottomSheet(
|
_openActions(context, item!);
|
||||||
useRootNavigator: true,
|
|
||||||
context: context,
|
|
||||||
builder: (context) => ChatEventAction(
|
|
||||||
channel: channel,
|
|
||||||
realm: channel.realm,
|
|
||||||
item: item!,
|
|
||||||
onEdit: () {
|
|
||||||
onEdit(item);
|
|
||||||
},
|
|
||||||
onReply: () {
|
|
||||||
onReply(item);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
onTapInside: (event) {
|
||||||
|
if (event.buttons == kSecondaryMouseButton) {
|
||||||
|
_openActions(context, item!);
|
||||||
|
} else if (event.buttons == kMiddleMouseButton) {
|
||||||
|
onReply(item!);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -91,17 +91,21 @@ class _PostActionState extends State<PostAction> {
|
|||||||
|
|
||||||
setState(() => _isBusy = true);
|
setState(() => _isBusy = true);
|
||||||
|
|
||||||
|
final double width = hasMultipleAttachment ? 640 : 480;
|
||||||
|
|
||||||
final screenshot = ScreenshotController();
|
final screenshot = ScreenshotController();
|
||||||
final image = await screenshot.captureFromLongWidget(
|
final image = await screenshot.captureFromLongWidget(
|
||||||
MediaQuery(
|
MediaQuery(
|
||||||
data: MediaQuery.of(context),
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
size: Size(width, double.infinity),
|
||||||
|
),
|
||||||
child: PostShareImage(item: widget.item),
|
child: PostShareImage(item: widget.item),
|
||||||
),
|
),
|
||||||
context: context,
|
context: context,
|
||||||
pixelRatio: 2,
|
pixelRatio: 2,
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
minWidth: 480,
|
minWidth: 480,
|
||||||
maxWidth: hasMultipleAttachment ? 640 : 480,
|
maxWidth: width,
|
||||||
minHeight: 640,
|
minHeight: 640,
|
||||||
maxHeight: double.infinity,
|
maxHeight: double.infinity,
|
||||||
),
|
),
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:solian/models/post.dart';
|
|
||||||
import 'package:solian/widgets/posts/post_item.dart';
|
|
||||||
|
|
||||||
class PostOwnedListEntry extends StatelessWidget {
|
|
||||||
final Post item;
|
|
||||||
final Function onTap;
|
|
||||||
final bool isFullContent;
|
|
||||||
final Color? backgroundColor;
|
|
||||||
|
|
||||||
const PostOwnedListEntry({
|
|
||||||
super.key,
|
|
||||||
required this.item,
|
|
||||||
required this.onTap,
|
|
||||||
this.isFullContent = false,
|
|
||||||
this.backgroundColor,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Card(
|
|
||||||
child: GestureDetector(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
PostItem(
|
|
||||||
key: Key('p${item.id}'),
|
|
||||||
item: item,
|
|
||||||
isShowEmbed: false,
|
|
||||||
isClickable: false,
|
|
||||||
isShowReply: false,
|
|
||||||
isReactable: false,
|
|
||||||
).paddingSymmetric(vertical: 8),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onTap: () => onTap(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,7 @@ name: solian
|
|||||||
description: "The Solar Network App"
|
description: "The Solar Network App"
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 1.3.8+13
|
version: 1.4.0+14
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.4 <4.0.0"
|
sdk: ">=3.3.4 <4.0.0"
|
||||||
|
Reference in New Issue
Block a user