✨ Dashboard explore
This commit is contained in:
59
lib/widgets/posts/content/article.dart
Normal file
59
lib/widgets/posts/content/article.dart
Normal file
@ -0,0 +1,59 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:solian/models/post.dart';
|
||||
import 'package:markdown/markdown.dart' as markdown;
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
class ArticleContent extends StatelessWidget {
|
||||
final Post item;
|
||||
final bool brief;
|
||||
|
||||
const ArticleContent({super.key, required this.item, required this.brief});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return brief
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.title,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
Text(
|
||||
item.description,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(item.title),
|
||||
subtitle: Text(item.description),
|
||||
),
|
||||
const Divider(color: Color(0xffefefef)),
|
||||
Markdown(
|
||||
selectable: !brief,
|
||||
data: item.content,
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
extensionSet: markdown.ExtensionSet(
|
||||
markdown.ExtensionSet.gitHubFlavored.blockSyntaxes,
|
||||
markdown.ExtensionSet.gitHubFlavored.inlineSyntaxes,
|
||||
),
|
||||
onTapLink: (text, href, title) async {
|
||||
if (href == null) return;
|
||||
await launchUrlString(
|
||||
href,
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
131
lib/widgets/posts/content/attachment.dart
Normal file
131
lib/widgets/posts/content/attachment.dart
Normal file
@ -0,0 +1,131 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:chewie/chewie.dart';
|
||||
import 'package:solian/models/post.dart';
|
||||
import 'package:solian/utils/service_url.dart';
|
||||
import 'package:flutter_carousel_widget/flutter_carousel_widget.dart';
|
||||
import 'package:solian/widgets/posts/attachment_screen.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
class AttachmentItem extends StatefulWidget {
|
||||
final Attachment item;
|
||||
|
||||
const AttachmentItem({super.key, required this.item});
|
||||
|
||||
@override
|
||||
State<AttachmentItem> createState() => _AttachmentItemState();
|
||||
}
|
||||
|
||||
class _AttachmentItemState extends State<AttachmentItem> {
|
||||
String getTag() => 'attachment-${widget.item.fileId}';
|
||||
|
||||
Uri getFileUri() =>
|
||||
getRequestUri('interactive', '/api/attachments/o/${widget.item.fileId}');
|
||||
|
||||
VideoPlayerController? _vpController;
|
||||
ChewieController? _chewieController;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const borderRadius = Radius.circular(16);
|
||||
|
||||
Widget content;
|
||||
|
||||
if (widget.item.type == 1) {
|
||||
content = GestureDetector(
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(borderRadius),
|
||||
child: Hero(
|
||||
tag: getTag(),
|
||||
child: Image.network(
|
||||
getFileUri().toString(),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) {
|
||||
return AttachmentScreen(
|
||||
tag: getTag(),
|
||||
url: getFileUri().toString(),
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
_vpController = VideoPlayerController.networkUrl(getFileUri());
|
||||
_chewieController = ChewieController(
|
||||
videoPlayerController: _vpController!,
|
||||
);
|
||||
|
||||
content = FutureBuilder(
|
||||
future: () async {
|
||||
await _vpController?.initialize();
|
||||
return true;
|
||||
}(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return ClipRRect(
|
||||
borderRadius: const BorderRadius.all(borderRadius),
|
||||
child: Chewie(
|
||||
controller: _chewieController!,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(borderRadius),
|
||||
border: Border.all(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 0.9,
|
||||
),
|
||||
),
|
||||
child: content,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_vpController?.dispose();
|
||||
_chewieController?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class AttachmentList extends StatelessWidget {
|
||||
final List<Attachment> items;
|
||||
|
||||
const AttachmentList({super.key, required this.items});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FlutterCarousel(
|
||||
options: CarouselOptions(
|
||||
aspectRatio: 16 / 9,
|
||||
showIndicator: true,
|
||||
slideIndicator: const CircularSlideIndicator(),
|
||||
),
|
||||
items: items.map((item) {
|
||||
return Builder(
|
||||
builder: (BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: AttachmentItem(item: item),
|
||||
);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
}
|
21
lib/widgets/posts/content/moment.dart
Normal file
21
lib/widgets/posts/content/moment.dart
Normal file
@ -0,0 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:solian/models/post.dart';
|
||||
|
||||
class MomentContent extends StatelessWidget {
|
||||
final Post item;
|
||||
final bool brief;
|
||||
|
||||
const MomentContent({super.key, required this.brief, required this.item});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Markdown(
|
||||
selectable: !brief,
|
||||
data: item.content,
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user