♻️ Refactor markdown sticker rendering
This commit is contained in:
@@ -47,7 +47,6 @@ class MarkdownTextContent extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final baseUrl = ref.watch(serverUrlProvider);
|
|
||||||
final doesEnlargeSticker = useMemoized(() {
|
final doesEnlargeSticker = useMemoized(() {
|
||||||
// Check if content only contains one sticker by matching the sticker pattern
|
// Check if content only contains one sticker by matching the sticker pattern
|
||||||
final stickerPattern = RegExp(stickerRegex);
|
final stickerPattern = RegExp(stickerRegex);
|
||||||
@@ -88,6 +87,14 @@ class MarkdownTextContent extends HookConsumerWidget {
|
|||||||
onToggle: () => spoilerRevealed.value = !spoilerRevealed.value,
|
onToggle: () => spoilerRevealed.value = !spoilerRevealed.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final baseUrl = ref.watch(serverUrlProvider);
|
||||||
|
final stickerGenerator = StickerGenerator(
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||||
|
foregroundColor: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
isEnlarged: doesEnlargeSticker,
|
||||||
|
baseUrl: baseUrl,
|
||||||
|
);
|
||||||
|
|
||||||
return MarkdownBlock(
|
return MarkdownBlock(
|
||||||
data: content,
|
data: content,
|
||||||
selectable: isSelectable,
|
selectable: isSelectable,
|
||||||
@@ -186,28 +193,6 @@ class MarkdownTextContent extends HookConsumerWidget {
|
|||||||
).clipRRect(all: 8),
|
).clipRRect(all: 8),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
case 'stickers':
|
|
||||||
final size = doesEnlargeSticker ? 96.0 : 24.0;
|
|
||||||
final stickerUri =
|
|
||||||
'$baseUrl/sphere/stickers/lookup/${uri.pathSegments[0]}/open';
|
|
||||||
return ClipRRect(
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
|
||||||
borderRadius: const BorderRadius.all(
|
|
||||||
Radius.circular(8),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: UniversalImage(
|
|
||||||
uri: stickerUri,
|
|
||||||
width: size,
|
|
||||||
height: size,
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
noCacheOptimization: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final content = ClipRRect(
|
final content = ClipRRect(
|
||||||
@@ -228,7 +213,12 @@ class MarkdownTextContent extends HookConsumerWidget {
|
|||||||
generator: MarkdownTextContent.buildGenerator(
|
generator: MarkdownTextContent.buildGenerator(
|
||||||
isDark: isDark,
|
isDark: isDark,
|
||||||
linesMargin: linesMargin,
|
linesMargin: linesMargin,
|
||||||
generators: [mentionGenerator, highlightGenerator, spoilerGenerator],
|
generators: [
|
||||||
|
mentionGenerator,
|
||||||
|
highlightGenerator,
|
||||||
|
spoilerGenerator,
|
||||||
|
stickerGenerator,
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -284,9 +274,8 @@ class _StickerInlineSyntax extends markdown.InlineSyntax {
|
|||||||
@override
|
@override
|
||||||
bool onMatch(markdown.InlineParser parser, Match match) {
|
bool onMatch(markdown.InlineParser parser, Match match) {
|
||||||
final placeholder = match[1]!;
|
final placeholder = match[1]!;
|
||||||
final image = markdown.Element.text('img', '')
|
final element = markdown.Element('sticker', [markdown.Text(placeholder)]);
|
||||||
..attributes['src'] = Uri.encodeFull('solian://stickers/$placeholder');
|
parser.addNode(element);
|
||||||
parser.addNode(image);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -559,3 +548,68 @@ class SpoilerSpanNode extends SpanNode {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class StickerGenerator extends SpanNodeGeneratorWithTag {
|
||||||
|
StickerGenerator({
|
||||||
|
required Color backgroundColor,
|
||||||
|
required Color foregroundColor,
|
||||||
|
required bool isEnlarged,
|
||||||
|
required String baseUrl,
|
||||||
|
}) : super(
|
||||||
|
tag: 'sticker',
|
||||||
|
generator: (
|
||||||
|
markdown.Element element,
|
||||||
|
MarkdownConfig config,
|
||||||
|
WidgetVisitor visitor,
|
||||||
|
) {
|
||||||
|
return StickerSpanNode(
|
||||||
|
placeholder: element.textContent,
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
foregroundColor: foregroundColor,
|
||||||
|
isEnlarged: isEnlarged,
|
||||||
|
baseUrl: baseUrl,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class StickerSpanNode extends SpanNode {
|
||||||
|
final String placeholder;
|
||||||
|
final Color backgroundColor;
|
||||||
|
final Color foregroundColor;
|
||||||
|
final bool isEnlarged;
|
||||||
|
final String baseUrl;
|
||||||
|
|
||||||
|
StickerSpanNode({
|
||||||
|
required this.placeholder,
|
||||||
|
required this.backgroundColor,
|
||||||
|
required this.foregroundColor,
|
||||||
|
required this.isEnlarged,
|
||||||
|
required this.baseUrl,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
InlineSpan build() {
|
||||||
|
final size = isEnlarged ? 96.0 : 24.0;
|
||||||
|
final stickerUri = '$baseUrl/sphere/stickers/lookup/$placeholder/open';
|
||||||
|
return WidgetSpan(
|
||||||
|
alignment: PlaceholderAlignment.middle,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: backgroundColor.withOpacity(0.1),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
),
|
||||||
|
child: UniversalImage(
|
||||||
|
uri: stickerUri,
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
noCacheOptimization: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user