✨ Better sticker & able embed attachment into markdown
This commit is contained in:
parent
4f6c5aa053
commit
56bbf73b5e
@ -322,3 +322,50 @@ class AttachmentListEntry extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AttachmentSelfContainedEntry extends StatefulWidget {
|
||||
final int id;
|
||||
final String parentId;
|
||||
final bool isDense;
|
||||
|
||||
const AttachmentSelfContainedEntry({
|
||||
super.key,
|
||||
required this.id,
|
||||
required this.parentId,
|
||||
this.isDense = false,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AttachmentSelfContainedEntry> createState() =>
|
||||
_AttachmentSelfContainedEntryState();
|
||||
}
|
||||
|
||||
class _AttachmentSelfContainedEntryState
|
||||
extends State<AttachmentSelfContainedEntry> {
|
||||
bool _showMature = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final AttachmentProvider attachments = Get.find();
|
||||
|
||||
return FutureBuilder(
|
||||
future: attachments.getMetadata(widget.id),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return const Text('Loading...');
|
||||
}
|
||||
|
||||
return AttachmentListEntry(
|
||||
item: snapshot.data,
|
||||
isDense: widget.isDense,
|
||||
parentId: widget.parentId,
|
||||
showMature: _showMature,
|
||||
showBorder: true,
|
||||
onReveal: (value) {
|
||||
setState(() => _showMature = value);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,11 @@ class ChatEventMessage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
return MarkdownTextContent(content: body.text);
|
||||
return MarkdownTextContent(
|
||||
parentId: 'm${item.id}',
|
||||
isSelectable: true,
|
||||
content: body.text,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(BuildContext context) {
|
||||
|
@ -1,20 +1,25 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_markdown_selectionarea/flutter_markdown.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:markdown/markdown.dart' as markdown;
|
||||
import 'package:markdown/markdown.dart';
|
||||
import 'package:solian/platform.dart';
|
||||
import 'package:solian/providers/stickers.dart';
|
||||
import 'package:solian/widgets/attachments/attachment_list.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
import 'account/account_profile_popup.dart';
|
||||
|
||||
class MarkdownTextContent extends StatelessWidget {
|
||||
final String content;
|
||||
final String parentId;
|
||||
final bool isSelectable;
|
||||
|
||||
const MarkdownTextContent({
|
||||
super.key,
|
||||
required this.content,
|
||||
required this.parentId,
|
||||
this.isSelectable = false,
|
||||
});
|
||||
|
||||
@ -42,6 +47,7 @@ class MarkdownTextContent extends StatelessWidget {
|
||||
_UserNameCardInlineSyntax(),
|
||||
_CustomEmoteInlineSyntax(),
|
||||
markdown.EmojiSyntax(),
|
||||
markdown.AutolinkSyntax(),
|
||||
markdown.AutolinkExtensionSyntax(),
|
||||
...markdown.ExtensionSet.gitHubFlavored.inlineSyntaxes
|
||||
],
|
||||
@ -70,6 +76,38 @@ class MarkdownTextContent extends StatelessWidget {
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
},
|
||||
imageBuilder: (uri, title, alt) {
|
||||
var url = uri.toString();
|
||||
double? width, height;
|
||||
if (url.startsWith('solink://')) {
|
||||
final segments = url.replaceFirst('solink://', '').split('/');
|
||||
switch (segments[0]) {
|
||||
case 'stickers':
|
||||
final StickerProvider sticker = Get.find();
|
||||
url = sticker.aliasImageMapping[segments[1]]!;
|
||||
width = 28;
|
||||
height = 28;
|
||||
break;
|
||||
case 'attachments':
|
||||
const radius = BorderRadius.all(Radius.circular(8));
|
||||
return LimitedBox(
|
||||
maxHeight: 360,
|
||||
child: ClipRRect(
|
||||
borderRadius: radius,
|
||||
child: AttachmentSelfContainedEntry(
|
||||
isDense: true,
|
||||
parentId: parentId,
|
||||
id: int.parse(segments[1]),
|
||||
),
|
||||
),
|
||||
).paddingSymmetric(vertical: 4);
|
||||
}
|
||||
}
|
||||
|
||||
return PlatformInfo.canCacheImage
|
||||
? CachedNetworkImage(imageUrl: url, width: width, height: height)
|
||||
: Image.network(url, width: width, height: height);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -111,7 +149,7 @@ class _CustomEmoteInlineSyntax extends InlineSyntax {
|
||||
}
|
||||
|
||||
final element = markdown.Element.empty('img');
|
||||
element.attributes['src'] = sticker.aliasImageMapping[alias]!;
|
||||
element.attributes['src'] = 'solink://stickers/$alias';
|
||||
parser.addNode(element);
|
||||
|
||||
return true;
|
||||
|
@ -295,6 +295,7 @@ class _PostItemState extends State<PostItem> {
|
||||
setState(() => _contentHeight = size.height);
|
||||
},
|
||||
child: MarkdownTextContent(
|
||||
parentId: 'p${item.id}',
|
||||
content: item.body['content'],
|
||||
isSelectable: widget.isContentSelectable,
|
||||
).paddingOnly(
|
||||
@ -389,6 +390,7 @@ class _PostItemState extends State<PostItem> {
|
||||
setState(() => _contentHeight = size.height);
|
||||
},
|
||||
child: MarkdownTextContent(
|
||||
parentId: 'p${item.id}',
|
||||
content: item.body['content'],
|
||||
isSelectable: widget.isContentSelectable,
|
||||
).paddingOnly(left: 12, right: 8),
|
||||
|
Loading…
Reference in New Issue
Block a user