Don't make message text selectable as it breaks long press context menus
This commit is contained in:
parent
0b9ddbfbc8
commit
bb842abfb1
1 changed files with 117 additions and 119 deletions
|
|
@ -21,135 +21,133 @@ class Html extends ConsumerWidget {
|
||||||
const Html(this.html, {this.textStyle, super.key});
|
const Html(this.html, {this.textStyle, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) => SelectionArea(
|
Widget build(BuildContext context, WidgetRef ref) => HtmlWidget(
|
||||||
child: HtmlWidget(
|
html,
|
||||||
html,
|
textStyle: textStyle,
|
||||||
textStyle: textStyle,
|
customWidgetBuilder: (element) {
|
||||||
customWidgetBuilder: (element) {
|
if (element.attributes.keys.contains("data-mx-profile-fallback")) {
|
||||||
if (element.attributes.keys.contains("data-mx-profile-fallback")) {
|
return SizedBox.shrink();
|
||||||
return SizedBox.shrink();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (element.attributes.keys.contains("data-mx-spoiler")) {
|
if (element.attributes.keys.contains("data-mx-spoiler")) {
|
||||||
return InlineCustomWidget(child: SpoilerText(text: element.text));
|
return InlineCustomWidget(child: SpoilerText(text: element.text));
|
||||||
}
|
}
|
||||||
|
|
||||||
final height = int.tryParse(element.attributes["height"] ?? "") ?? 300;
|
final height = int.tryParse(element.attributes["height"] ?? "") ?? 300;
|
||||||
final width = int.tryParse(element.attributes["width"] ?? "");
|
final width = int.tryParse(element.attributes["width"] ?? "");
|
||||||
final src = Uri.tryParse(element.attributes["src"] ?? "")
|
final src = Uri.tryParse(element.attributes["src"] ?? "")
|
||||||
?.mxcToHttps(
|
?.mxcToHttps(
|
||||||
ref.watch(
|
ref.watch(
|
||||||
ClientStateController.provider.select(
|
ClientStateController.provider.select(
|
||||||
(value) => value?.homeserverUrl,
|
(value) => value?.homeserverUrl,
|
||||||
),
|
),
|
||||||
) ??
|
) ??
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
.toString();
|
.toString();
|
||||||
|
|
||||||
return switch (element.localName) {
|
return switch (element.localName) {
|
||||||
"code" =>
|
"code" =>
|
||||||
element.parent?.localName == "pre"
|
element.parent?.localName == "pre"
|
||||||
? element.outerHtml.contains("<br class=\"fake-break\">")
|
? element.outerHtml.contains("<br class=\"fake-break\">")
|
||||||
? Html(
|
? Html(
|
||||||
"""<pre>${element.outerHtml.replaceAll("<br class=\"fake-break\">", "\n")}</pre>""",
|
"""<pre>${element.outerHtml.replaceAll("<br class=\"fake-break\">", "\n")}</pre>""",
|
||||||
)
|
)
|
||||||
: CodeBlock(
|
: CodeBlock(
|
||||||
element.text,
|
element.text,
|
||||||
lang: element.className.replaceAll("language-", ""),
|
lang: element.className.replaceAll("language-", ""),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
"blockquote" => Quoted(Html(element.innerHtml)),
|
"blockquote" => Quoted(Html(element.innerHtml)),
|
||||||
|
|
||||||
"a" =>
|
"a" =>
|
||||||
element.attributes["href"]?.mention == null
|
element.attributes["href"]?.mention == null
|
||||||
? null
|
? null
|
||||||
: InlineCustomWidget(child: MentionChip(element.text)),
|
: InlineCustomWidget(child: MentionChip(element.text)),
|
||||||
|
|
||||||
"img" =>
|
"img" =>
|
||||||
src == null
|
src == null
|
||||||
? SizedBox.shrink()
|
? SizedBox.shrink()
|
||||||
: InlineCustomWidget(
|
: InlineCustomWidget(
|
||||||
alignment: PlaceholderAlignment.middle,
|
alignment: PlaceholderAlignment.middle,
|
||||||
child: ExpandableImage(
|
child: ExpandableImage(
|
||||||
src,
|
src,
|
||||||
child: Image(
|
child: Image(
|
||||||
image: CachedNetworkImage(
|
image: CachedNetworkImage(
|
||||||
src,
|
src,
|
||||||
ref.watch(CrossCacheController.provider),
|
ref.watch(CrossCacheController.provider),
|
||||||
headers: ref.headers,
|
headers: ref.headers,
|
||||||
),
|
|
||||||
errorBuilder: (_, error, _) => Text(
|
|
||||||
"Image Failed to Load",
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).colorScheme.error,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
height: height.toDouble(),
|
|
||||||
width: width?.toDouble(),
|
|
||||||
loadingBuilder: (_, child, loadingProgress) =>
|
|
||||||
loadingProgress == null
|
|
||||||
? child
|
|
||||||
: CircularProgressIndicator(),
|
|
||||||
),
|
),
|
||||||
|
errorBuilder: (_, error, _) => Text(
|
||||||
|
"Image Failed to Load",
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.error,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
height: height.toDouble(),
|
||||||
|
width: width?.toDouble(),
|
||||||
|
loadingBuilder: (_, child, loadingProgress) =>
|
||||||
|
loadingProgress == null
|
||||||
|
? child
|
||||||
|
: CircularProgressIndicator(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("del" ||
|
),
|
||||||
"h1" ||
|
("del" ||
|
||||||
"h2" ||
|
"h1" ||
|
||||||
"h3" ||
|
"h2" ||
|
||||||
"h4" ||
|
"h3" ||
|
||||||
"h5" ||
|
"h4" ||
|
||||||
"h6" ||
|
"h5" ||
|
||||||
"p" ||
|
"h6" ||
|
||||||
"ul" ||
|
"p" ||
|
||||||
"ol" ||
|
"ul" ||
|
||||||
"sup" ||
|
"ol" ||
|
||||||
"sub" ||
|
"sup" ||
|
||||||
"li" ||
|
"sub" ||
|
||||||
"b" ||
|
"li" ||
|
||||||
"i" ||
|
"b" ||
|
||||||
"u" ||
|
"i" ||
|
||||||
"strong" ||
|
"u" ||
|
||||||
"em" ||
|
"strong" ||
|
||||||
"s" ||
|
"em" ||
|
||||||
"code" ||
|
"s" ||
|
||||||
"hr" ||
|
"code" ||
|
||||||
"br" ||
|
"hr" ||
|
||||||
"div" ||
|
"br" ||
|
||||||
"table" ||
|
"div" ||
|
||||||
"thead" ||
|
"table" ||
|
||||||
"tbody" ||
|
"thead" ||
|
||||||
"tr" ||
|
"tbody" ||
|
||||||
"th" ||
|
"tr" ||
|
||||||
"td" ||
|
"th" ||
|
||||||
"caption" ||
|
"td" ||
|
||||||
"pre" ||
|
"caption" ||
|
||||||
"span" ||
|
"pre" ||
|
||||||
"details" ||
|
"span" ||
|
||||||
"summary") =>
|
"details" ||
|
||||||
null,
|
"summary") =>
|
||||||
|
null,
|
||||||
|
|
||||||
_ => SizedBox.shrink(),
|
_ => SizedBox.shrink(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
customStylesBuilder: (element) => {
|
customStylesBuilder: (element) => {
|
||||||
"width": "auto",
|
"width": "auto",
|
||||||
...Map.fromEntries(
|
...Map.fromEntries(
|
||||||
element.attributes
|
element.attributes
|
||||||
.mapTo<MapEntry<String, String>?>(
|
.mapTo<MapEntry<String, String>?>(
|
||||||
(key, value) => switch (key) {
|
(key, value) => switch (key) {
|
||||||
"data-mx-color" => MapEntry("color", value),
|
"data-mx-color" => MapEntry("color", value),
|
||||||
"data-mx-bg-color" => MapEntry("background-color", value),
|
"data-mx-bg-color" => MapEntry("background-color", value),
|
||||||
_ => null,
|
_ => null,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.nonNulls,
|
.nonNulls,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
onTapUrl: (url) =>
|
onTapUrl: (url) =>
|
||||||
ref.watch(LaunchHelper.provider).launchUrl(Uri.parse(url)),
|
ref.watch(LaunchHelper.provider).launchUrl(Uri.parse(url)),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue