✨ 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) {
|
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/material.dart';
|
||||||
import 'package:flutter_markdown_selectionarea/flutter_markdown.dart';
|
import 'package:flutter_markdown_selectionarea/flutter_markdown.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:markdown/markdown.dart' as markdown;
|
import 'package:markdown/markdown.dart' as markdown;
|
||||||
import 'package:markdown/markdown.dart';
|
import 'package:markdown/markdown.dart';
|
||||||
|
import 'package:solian/platform.dart';
|
||||||
import 'package:solian/providers/stickers.dart';
|
import 'package:solian/providers/stickers.dart';
|
||||||
|
import 'package:solian/widgets/attachments/attachment_list.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
import 'account/account_profile_popup.dart';
|
import 'account/account_profile_popup.dart';
|
||||||
|
|
||||||
class MarkdownTextContent extends StatelessWidget {
|
class MarkdownTextContent extends StatelessWidget {
|
||||||
final String content;
|
final String content;
|
||||||
|
final String parentId;
|
||||||
final bool isSelectable;
|
final bool isSelectable;
|
||||||
|
|
||||||
const MarkdownTextContent({
|
const MarkdownTextContent({
|
||||||
super.key,
|
super.key,
|
||||||
required this.content,
|
required this.content,
|
||||||
|
required this.parentId,
|
||||||
this.isSelectable = false,
|
this.isSelectable = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -42,6 +47,7 @@ class MarkdownTextContent extends StatelessWidget {
|
|||||||
_UserNameCardInlineSyntax(),
|
_UserNameCardInlineSyntax(),
|
||||||
_CustomEmoteInlineSyntax(),
|
_CustomEmoteInlineSyntax(),
|
||||||
markdown.EmojiSyntax(),
|
markdown.EmojiSyntax(),
|
||||||
|
markdown.AutolinkSyntax(),
|
||||||
markdown.AutolinkExtensionSyntax(),
|
markdown.AutolinkExtensionSyntax(),
|
||||||
...markdown.ExtensionSet.gitHubFlavored.inlineSyntaxes
|
...markdown.ExtensionSet.gitHubFlavored.inlineSyntaxes
|
||||||
],
|
],
|
||||||
@ -70,6 +76,38 @@ class MarkdownTextContent extends StatelessWidget {
|
|||||||
mode: LaunchMode.externalApplication,
|
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');
|
final element = markdown.Element.empty('img');
|
||||||
element.attributes['src'] = sticker.aliasImageMapping[alias]!;
|
element.attributes['src'] = 'solink://stickers/$alias';
|
||||||
parser.addNode(element);
|
parser.addNode(element);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -295,6 +295,7 @@ class _PostItemState extends State<PostItem> {
|
|||||||
setState(() => _contentHeight = size.height);
|
setState(() => _contentHeight = size.height);
|
||||||
},
|
},
|
||||||
child: MarkdownTextContent(
|
child: MarkdownTextContent(
|
||||||
|
parentId: 'p${item.id}',
|
||||||
content: item.body['content'],
|
content: item.body['content'],
|
||||||
isSelectable: widget.isContentSelectable,
|
isSelectable: widget.isContentSelectable,
|
||||||
).paddingOnly(
|
).paddingOnly(
|
||||||
@ -389,6 +390,7 @@ class _PostItemState extends State<PostItem> {
|
|||||||
setState(() => _contentHeight = size.height);
|
setState(() => _contentHeight = size.height);
|
||||||
},
|
},
|
||||||
child: MarkdownTextContent(
|
child: MarkdownTextContent(
|
||||||
|
parentId: 'p${item.id}',
|
||||||
content: item.body['content'],
|
content: item.body['content'],
|
||||||
isSelectable: widget.isContentSelectable,
|
isSelectable: widget.isContentSelectable,
|
||||||
).paddingOnly(left: 12, right: 8),
|
).paddingOnly(left: 12, right: 8),
|
||||||
|
Loading…
Reference in New Issue
Block a user