kopia lustrzana https://gitlab.com/mysocialportal/relatica
140 wiersze
4.0 KiB
Dart
140 wiersze
4.0 KiB
Dart
![]() |
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
|
||
![]() |
import 'package:logging/logging.dart';
|
||
![]() |
|
||
![]() |
import '../../models/flattened_tree_item.dart';
|
||
![]() |
import '../../models/timeline_entry.dart';
|
||
![]() |
import '../../utils/url_opening_utils.dart';
|
||
![]() |
import '../media_attachment_viewer_control.dart';
|
||
![]() |
import '../padding.dart';
|
||
|
import 'interactions_bar_control.dart';
|
||
![]() |
import 'status_header_control.dart';
|
||
![]() |
|
||
![]() |
class FlattenedTreeEntryControl extends StatefulWidget {
|
||
|
final FlattenedTreeItem originalItem;
|
||
![]() |
final bool openRemote;
|
||
|
final bool showStatusOpenButton;
|
||
![]() |
|
||
![]() |
const FlattenedTreeEntryControl(
|
||
![]() |
{super.key,
|
||
|
required this.originalItem,
|
||
|
required this.openRemote,
|
||
|
required this.showStatusOpenButton});
|
||
![]() |
|
||
|
@override
|
||
![]() |
State<FlattenedTreeEntryControl> createState() => _StatusControlState();
|
||
![]() |
}
|
||
|
|
||
![]() |
class _StatusControlState extends State<FlattenedTreeEntryControl> {
|
||
|
static final _logger = Logger('$FlattenedTreeEntryControl');
|
||
![]() |
|
||
![]() |
var showContent = true;
|
||
|
|
||
![]() |
var showComments = false;
|
||
|
|
||
![]() |
FlattenedTreeItem get item => widget.originalItem;
|
||
![]() |
|
||
![]() |
TimelineEntry get entry => item.timelineEntry;
|
||
![]() |
|
||
![]() |
bool get isPublic => entry.isPublic;
|
||
![]() |
|
||
![]() |
bool get isPost => entry.parentId.isEmpty;
|
||
![]() |
|
||
|
bool get hasComments => entry.engagementSummary.repliesCount > 0;
|
||
|
|
||
![]() |
@override
|
||
|
void initState() {
|
||
|
showContent = entry.spoilerText.isEmpty;
|
||
![]() |
showComments = isPost ? false : true;
|
||
![]() |
}
|
||
|
|
||
![]() |
@override
|
||
|
Widget build(BuildContext context) {
|
||
![]() |
_logger.finest('Building ${entry.toShortString()}');
|
||
|
const otherPadding = 8.0;
|
||
|
final leftPadding = otherPadding + (widget.originalItem.level * 15.0);
|
||
|
final color = widget.originalItem.level.isOdd
|
||
|
? Theme.of(context).splashColor
|
||
|
: Theme.of(context).cardColor;
|
||
![]() |
final body = Padding(
|
||
![]() |
padding: const EdgeInsets.all(8.0),
|
||
![]() |
child: Column(
|
||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||
|
children: [
|
||
![]() |
StatusHeaderControl(
|
||
|
entry: entry,
|
||
|
),
|
||
![]() |
const VerticalPadding(
|
||
|
height: 5,
|
||
|
),
|
||
![]() |
if (entry.spoilerText.isNotEmpty)
|
||
|
TextButton(
|
||
|
onPressed: () {
|
||
|
setState(() {
|
||
|
showContent = !showContent;
|
||
|
});
|
||
|
},
|
||
|
child: Text(
|
||
|
'Content Summary: ${entry.spoilerText} (Click to ${showContent ? "Hide" : "Show"}}')),
|
||
|
if (showContent) ...[
|
||
|
buildBody(context),
|
||
|
const VerticalPadding(
|
||
|
height: 5,
|
||
|
),
|
||
|
buildMediaBar(context),
|
||
|
],
|
||
![]() |
const VerticalPadding(
|
||
|
height: 5,
|
||
|
),
|
||
![]() |
InteractionsBarControl(
|
||
|
entry: entry,
|
||
|
isMine: item.isMine,
|
||
![]() |
openRemote: widget.openRemote,
|
||
|
showOpenControl: widget.showStatusOpenButton,
|
||
![]() |
),
|
||
![]() |
const VerticalPadding(
|
||
|
height: 5,
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
);
|
||
![]() |
return Padding(
|
||
|
padding: EdgeInsets.only(
|
||
|
left: leftPadding,
|
||
|
right: otherPadding,
|
||
|
top: otherPadding,
|
||
|
bottom: otherPadding,
|
||
|
),
|
||
|
child: isPost ? body : Card(color: color, child: body),
|
||
|
);
|
||
![]() |
}
|
||
|
|
||
|
Widget buildBody(BuildContext context) {
|
||
![]() |
return HtmlWidget(
|
||
|
entry.body,
|
||
|
onTapUrl: (url) async {
|
||
|
return await openUrlStringInSystembrowser(context, url, 'video');
|
||
|
},
|
||
![]() |
);
|
||
|
}
|
||
|
|
||
|
Widget buildMediaBar(BuildContext context) {
|
||
|
final items = entry.mediaAttachments;
|
||
|
if (items.isEmpty) {
|
||
|
return const SizedBox();
|
||
|
}
|
||
|
return SizedBox(
|
||
|
height: 250.0,
|
||
|
child: ListView.separated(
|
||
|
scrollDirection: Axis.horizontal,
|
||
|
itemBuilder: (context, index) {
|
||
![]() |
return MediaAttachmentViewerControl(attachment: items[index]);
|
||
![]() |
},
|
||
|
separatorBuilder: (context, index) {
|
||
|
return HorizontalPadding();
|
||
|
},
|
||
|
itemCount: items.length));
|
||
|
}
|
||
|
}
|