|
@@ -1,137 +0,0 @@
|
|
|
-import 'package:flutter/material.dart';
|
|
|
-import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
|
|
-import 'package:url_launcher/url_launcher.dart';
|
|
|
-import 'package:veloe_kemono_party_flutter/models/attachment.dart';
|
|
|
-import 'package:veloe_kemono_party_flutter/models/post.dart';
|
|
|
-import 'package:veloe_kemono_party_flutter/pages/widgets/smart_image_container.dart';
|
|
|
-
|
|
|
-class PostDetailView extends StatelessWidget {
|
|
|
- final Post post;
|
|
|
-
|
|
|
- const PostDetailView({super.key, required this.post});
|
|
|
-
|
|
|
- @override
|
|
|
- Widget build(BuildContext context) {
|
|
|
- return Scaffold(
|
|
|
- appBar: AppBar(
|
|
|
- title: Text(post.title),
|
|
|
- elevation: 0,
|
|
|
- ),
|
|
|
- body: LayoutBuilder(
|
|
|
- builder: (context, constraints) {
|
|
|
- return ConstrainedBox(
|
|
|
- constraints: BoxConstraints(
|
|
|
- minHeight: constraints.maxHeight,
|
|
|
- maxWidth: constraints.maxWidth,
|
|
|
- ),
|
|
|
- child: Column(
|
|
|
- mainAxisSize: MainAxisSize.min,
|
|
|
- crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
- children: [
|
|
|
- // Header Section
|
|
|
- _buildTitle(context),
|
|
|
-
|
|
|
- // Content Area
|
|
|
- Flexible(
|
|
|
- child: Column(
|
|
|
- mainAxisSize: MainAxisSize.min,
|
|
|
- children: [
|
|
|
- if (post.attachments.isNotEmpty)
|
|
|
- _buildImageColumn(post.attachments),
|
|
|
- _buildHtmlContent(),
|
|
|
- ],
|
|
|
- ),
|
|
|
- ),
|
|
|
-
|
|
|
- // Footer Section
|
|
|
- _buildDateDisplay(context),
|
|
|
- ],
|
|
|
- ),
|
|
|
- );
|
|
|
- },
|
|
|
- ),
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- Widget _buildTitle(BuildContext context) {
|
|
|
- return Padding(
|
|
|
- padding: const EdgeInsets.all(16.0),
|
|
|
- child: Text(
|
|
|
- post.title,
|
|
|
- style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
|
|
- fontWeight: FontWeight.w600,
|
|
|
- ),
|
|
|
- ),
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- Widget _buildImageColumn(List<Attachment> attachments) {
|
|
|
- return Column(
|
|
|
- children: attachments
|
|
|
- .where((attachment) => _isImageFile(attachment.link))
|
|
|
- .map((attachment) {
|
|
|
- return Padding(
|
|
|
- padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
|
- child: SmartImageContainer(imageUrl: attachment.link),
|
|
|
- );
|
|
|
- }).toList(),
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- bool _isImageFile(String url) {
|
|
|
- try {
|
|
|
- final uri = Uri.parse(url);
|
|
|
- final path = uri.path.toLowerCase();
|
|
|
-
|
|
|
- final cleanPath = path.split('?').first.split('#').first;
|
|
|
- const imageExtensions = {
|
|
|
- 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg',
|
|
|
- 'tiff', 'heic', 'heif'
|
|
|
- };
|
|
|
- return imageExtensions.any((ext) => cleanPath.endsWith('.$ext'));
|
|
|
- } catch (e) {
|
|
|
- return false; // Invalid URL format
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
- Widget _buildHtmlContent() {
|
|
|
- return Padding(
|
|
|
- padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
|
|
- child: HtmlWidget(
|
|
|
- post.content,
|
|
|
- renderMode: RenderMode.column,
|
|
|
- onTapUrl: (url) => launchUrl(Uri.parse(url)),
|
|
|
- customWidgetBuilder: (element) {
|
|
|
- if (element.localName == 'img') {
|
|
|
- final src = element.attributes['src'];
|
|
|
- return src != null
|
|
|
- ? Padding(
|
|
|
- padding: const EdgeInsets.symmetric(vertical: 8),
|
|
|
- child: SmartImageContainer(imageUrl: src),
|
|
|
- )
|
|
|
- : const SizedBox.shrink();
|
|
|
- }
|
|
|
- return null;
|
|
|
- },
|
|
|
- ),
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- Widget _buildDateDisplay(BuildContext context) {
|
|
|
- return Padding(
|
|
|
- padding: const EdgeInsets.all(16.0),
|
|
|
- child: Row(
|
|
|
- children: [
|
|
|
- Icon(Icons.calendar_today, size: 18, color: Colors.grey[700]),
|
|
|
- const SizedBox(width: 8),
|
|
|
- Text(post.published
|
|
|
- ,
|
|
|
- style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
|
|
- color: Colors.grey[700],
|
|
|
- ),
|
|
|
- ),
|
|
|
- ],
|
|
|
- ),
|
|
|
- );
|
|
|
- }
|
|
|
-}
|