💄 Bug fixes and optimization

This commit is contained in:
LittleSheep 2024-04-14 01:45:27 +08:00
parent 4489b604d6
commit 07935a4017
7 changed files with 175 additions and 69 deletions

View File

@ -1,6 +1,7 @@
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:solian/screens/account.dart'; import 'package:solian/screens/account.dart';
import 'package:solian/screens/explore.dart'; import 'package:solian/screens/explore.dart';
import 'package:solian/screens/posts/new_moment.dart';
import 'package:solian/screens/posts/screen.dart'; import 'package:solian/screens/posts/screen.dart';
final router = GoRouter( final router = GoRouter(
@ -15,6 +16,11 @@ final router = GoRouter(
name: 'account', name: 'account',
builder: (context, state) => const AccountScreen(), builder: (context, state) => const AccountScreen(),
), ),
GoRoute(
path: '/posts/moments/new',
name: 'posts.moments.new',
builder: (context, state) => const NewMomentScreen(),
),
GoRoute( GoRoute(
path: '/posts/:dataset/:alias', path: '/posts/:dataset/:alias',
name: 'posts.screen', name: 'posts.screen',

View File

@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
class NewMomentScreen extends StatelessWidget {
const NewMomentScreen({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Container(
constraints: const BoxConstraints(maxWidth: 640),
child: Column(
children: [
],
),
),
);
}
}

View File

@ -89,7 +89,7 @@ class CommentListHeader extends StatelessWidget {
final auth = context.read<AuthProvider>(); final auth = context.read<AuthProvider>();
return Container( return Container(
padding: const EdgeInsets.only(left: 10, right: 10, top: 20), padding: const EdgeInsets.only(left: 8, right: 8, top: 20),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:solian/models/post.dart'; import 'package:solian/models/post.dart';
import 'package:markdown/markdown.dart' as markdown; import 'package:markdown/markdown.dart' as markdown;
import 'package:solian/utils/service_url.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
class ArticleContent extends StatelessWidget { class ArticleContent extends StatelessWidget {
@ -12,31 +13,30 @@ class ArticleContent extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return brief final headingPart = Column(
? Padding( crossAxisAlignment: CrossAxisAlignment.start,
padding: const EdgeInsets.symmetric(horizontal: 12), children: [
child: Column( Text(
crossAxisAlignment: CrossAxisAlignment.start, item.title,
children: [ style: Theme.of(context).textTheme.titleMedium,
Text( ),
item.title, Text(
style: Theme.of(context).textTheme.titleMedium, item.description,
), style: Theme.of(context).textTheme.bodyMedium,
Text(
item.description,
style: Theme.of(context).textTheme.bodyMedium,
)
],
),
) )
],
);
return brief
? headingPart
: Column( : Column(
children: [ children: [
ListTile( Padding(
title: Text(item.title), padding: const EdgeInsets.only(bottom: 12),
subtitle: Text(item.description), child: headingPart,
), ),
const Divider(color: Color(0xffefefef)),
Markdown( Markdown(
padding: const EdgeInsets.all(0),
selectable: !brief, selectable: !brief,
data: item.content, data: item.content,
shrinkWrap: true, shrinkWrap: true,
@ -52,6 +52,15 @@ class ArticleContent extends StatelessWidget {
mode: LaunchMode.externalApplication, mode: LaunchMode.externalApplication,
); );
}, },
imageBuilder: (url, _, __) {
if (url.toString().startsWith("/api/attachments")) {
return Image.network(
getRequestUri('interactive', url.toString())
.toString());
} else {
return Image.network(url.toString());
}
},
), ),
], ],
); );

View File

@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:chewie/chewie.dart'; import 'package:chewie/chewie.dart';
import 'package:solian/models/post.dart'; import 'package:solian/models/post.dart';
@ -8,8 +9,9 @@ import 'package:video_player/video_player.dart';
class AttachmentItem extends StatefulWidget { class AttachmentItem extends StatefulWidget {
final Attachment item; final Attachment item;
final String? badge;
const AttachmentItem({super.key, required this.item}); const AttachmentItem({super.key, required this.item, this.badge});
@override @override
State<AttachmentItem> createState() => _AttachmentItemState(); State<AttachmentItem> createState() => _AttachmentItemState();
@ -36,9 +38,22 @@ class _AttachmentItemState extends State<AttachmentItem> {
borderRadius: const BorderRadius.all(borderRadius), borderRadius: const BorderRadius.all(borderRadius),
child: Hero( child: Hero(
tag: getTag(), tag: getTag(),
child: Image.network( child: Stack(
getFileUri().toString(), children: [
fit: BoxFit.cover, Image.network(
getFileUri().toString(),
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
widget.badge == null
? Container()
: Positioned(
right: 12,
bottom: 8,
child: Chip(label: Text(widget.badge!)),
)
],
), ),
), ),
), ),
@ -110,18 +125,21 @@ class AttachmentList extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var renderProgress = 0;
return FlutterCarousel( return FlutterCarousel(
options: CarouselOptions( options: CarouselOptions(
aspectRatio: 16 / 9, aspectRatio: 16 / 9,
showIndicator: true, viewportFraction: 1,
slideIndicator: const CircularSlideIndicator(),
), ),
items: items.map((item) { items: items.map((item) {
renderProgress++;
final badge = '$renderProgress/${items.length}';
return Builder( return Builder(
builder: (BuildContext context) { builder: (BuildContext context) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 4), padding: const EdgeInsets.symmetric(horizontal: 4),
child: AttachmentItem(item: item), child: AttachmentItem(
item: item, badge: items.length <= 1 ? null : badge),
); );
}, },
); );

View File

@ -15,7 +15,7 @@ class MomentContent extends StatelessWidget {
data: item.content, data: item.content,
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.all(0),
); );
} }
} }

View File

@ -20,7 +20,7 @@ class _PostItemState extends State<PostItem> {
Widget renderContent() { Widget renderContent() {
switch (widget.item.modelType) { switch (widget.item.modelType) {
case "article": case 'article':
return ArticleContent(item: widget.item, brief: widget.brief ?? true); return ArticleContent(item: widget.item, brief: widget.brief ?? true);
default: default:
return MomentContent(item: widget.item, brief: widget.brief ?? true); return MomentContent(item: widget.item, brief: widget.brief ?? true);
@ -28,56 +28,110 @@ class _PostItemState extends State<PostItem> {
} }
Widget renderAttachments() { Widget renderAttachments() {
if(widget.item.attachments != null && widget.item.attachments!.isNotEmpty) { if (widget.item.modelType == 'article') return Container();
return AttachmentList(items: widget.item.attachments!);
if (widget.item.attachments != null &&
widget.item.attachments!.isNotEmpty) {
return Padding(
padding: const EdgeInsets.only(top: 8),
child: AttachmentList(items: widget.item.attachments!),
);
} else { } else {
return Container(); return Container();
} }
} }
String getAuthorDescribe() => widget.item.author.description.isNotEmpty
? widget.item.author.description
: 'No description yet.';
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( final headingParts = [
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), Padding(
child: Column( padding: const EdgeInsets.symmetric(horizontal: 12),
children: [ child: Row(
Row( children: [
crossAxisAlignment: CrossAxisAlignment.start, Text(
children: [ widget.item.author.nick,
CircleAvatar( style: const TextStyle(fontWeight: FontWeight.bold),
backgroundImage: NetworkImage(widget.item.author.avatar), ),
), const SizedBox(width: 4),
Expanded( Text(timeago.format(widget.item.createdAt))
child: Column( ],
crossAxisAlignment: CrossAxisAlignment.start, ),
children: [ ),
Padding( ];
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row( if (widget.brief ?? true) {
children: [ return Padding(
Text( padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
widget.item.author.nick, child: Column(
style: const TextStyle(fontWeight: FontWeight.bold), children: [
), Row(
const SizedBox(width: 4), crossAxisAlignment: CrossAxisAlignment.start,
Text( children: [
timeago.format(widget.item.createdAt) CircleAvatar(
) backgroundImage: NetworkImage(widget.item.author.avatar),
],
),
),
renderContent(),
],
), ),
), Expanded(
], child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
...headingParts,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: renderContent(),
),
renderAttachments(),
],
),
),
],
),
],
),
);
} else {
return Column(
children: [
Padding(
padding: const EdgeInsets.only(left: 12, right: 12, top: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CircleAvatar(
backgroundImage: NetworkImage(widget.item.author.avatar),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
...headingParts,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text(
getAuthorDescribe(),
maxLines: 1,
),
),
],
),
),
],
),
),
const Padding(
padding: EdgeInsets.only(top: 6),
child: Divider(thickness: 0.3),
), ),
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.symmetric(horizontal: 16),
child: renderAttachments(), child: renderContent(),
), ),
renderAttachments()
], ],
), );
); }
} }
} }