mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-07-16 13:50:48 +10:00
Centralize GIF parsing in a helper like for reactions
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
class GifHelper {
|
||||||
|
/// Parse a known GIF format, which can be any of:
|
||||||
|
/// g:GIFID
|
||||||
|
/// https://media.giphy.com/media/GIFID/giphy.gif
|
||||||
|
/// https://giphy.com/gifs/Optional-title-with-dashes-GIFID
|
||||||
|
///
|
||||||
|
/// GIFID is a Giphy GIF ID. The https:// is optional (and
|
||||||
|
/// can also be http://). The giphy.com/gifs form can also
|
||||||
|
/// include a trailing slash.
|
||||||
|
///
|
||||||
|
/// Returns null if text is not a valid GIF format
|
||||||
|
static String? parseGifId(String text) {
|
||||||
|
final trimmed = text.trim();
|
||||||
|
final match = RegExp(r'^g:([A-Za-z0-9_-]+)$').firstMatch(trimmed);
|
||||||
|
if (match != null) {
|
||||||
|
return match.group(1);
|
||||||
|
}
|
||||||
|
final directUrlMatch = RegExp(
|
||||||
|
r'^(?:https?:\/\/)?media\.giphy\.com\/media\/([A-Za-z0-9_-]+)\/giphy\.gif$',
|
||||||
|
).firstMatch(trimmed);
|
||||||
|
if (directUrlMatch != null) {
|
||||||
|
return directUrlMatch.group(1);
|
||||||
|
}
|
||||||
|
// Giphy understands page URLs with just the ID, or any string and a
|
||||||
|
// dash before the ID, and redirects to a page with a dash-separated
|
||||||
|
// title, a dash, and the ID. IDs in this form *probably* can't
|
||||||
|
// contain dashes.
|
||||||
|
final pageMatch = RegExp(
|
||||||
|
r'^(?:https?:\/\/)?giphy\.com\/gifs\/(?:[^/?]*-)?([A-Za-z0-9_]+)\/?$',
|
||||||
|
).firstMatch(trimmed);
|
||||||
|
return pageMatch?.group(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import '../connector/meshcore_connector.dart';
|
|||||||
import '../utils/platform_info.dart';
|
import '../utils/platform_info.dart';
|
||||||
import '../helpers/chat_scroll_controller.dart';
|
import '../helpers/chat_scroll_controller.dart';
|
||||||
import '../connector/meshcore_protocol.dart';
|
import '../connector/meshcore_protocol.dart';
|
||||||
|
import '../helpers/gif_helper.dart';
|
||||||
import '../helpers/reaction_helper.dart';
|
import '../helpers/reaction_helper.dart';
|
||||||
import '../helpers/utf8_length_limiter.dart';
|
import '../helpers/utf8_length_limiter.dart';
|
||||||
import '../l10n/l10n.dart';
|
import '../l10n/l10n.dart';
|
||||||
@@ -355,7 +356,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
|||||||
final settingsService = context.watch<AppSettingsService>();
|
final settingsService = context.watch<AppSettingsService>();
|
||||||
final enableTracing = settingsService.settings.enableMessageTracing;
|
final enableTracing = settingsService.settings.enableMessageTracing;
|
||||||
final isOutgoing = message.isOutgoing;
|
final isOutgoing = message.isOutgoing;
|
||||||
final gifId = _parseGifId(message.text);
|
final gifId = GifHelper.parseGifId(message.text);
|
||||||
final poi = _parsePoiMessage(message.text);
|
final poi = _parsePoiMessage(message.text);
|
||||||
final translatedDisplayText =
|
final translatedDisplayText =
|
||||||
message.translatedText != null &&
|
message.translatedText != null &&
|
||||||
@@ -699,7 +700,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
|||||||
final colorScheme = Theme.of(context).colorScheme;
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
final previewTextColor = colorScheme.onSurface.withValues(alpha: 0.7);
|
final previewTextColor = colorScheme.onSurface.withValues(alpha: 0.7);
|
||||||
|
|
||||||
final gifId = _parseGifId(replyText);
|
final gifId = GifHelper.parseGifId(replyText);
|
||||||
final poi = _parsePoiMessage(replyText);
|
final poi = _parsePoiMessage(replyText);
|
||||||
|
|
||||||
Widget contentPreview;
|
Widget contentPreview;
|
||||||
@@ -811,12 +812,6 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String? _parseGifId(String text) {
|
|
||||||
final trimmed = text.trim();
|
|
||||||
final match = RegExp(r'^g:([A-Za-z0-9_-]+)$').firstMatch(trimmed);
|
|
||||||
return match?.group(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_PoiInfo? _parsePoiMessage(String text) {
|
_PoiInfo? _parsePoiMessage(String text) {
|
||||||
final trimmed = text.trim();
|
final trimmed = text.trim();
|
||||||
final match = RegExp(
|
final match = RegExp(
|
||||||
@@ -1053,7 +1048,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
|||||||
child: ValueListenableBuilder<TextEditingValue>(
|
child: ValueListenableBuilder<TextEditingValue>(
|
||||||
valueListenable: _textController,
|
valueListenable: _textController,
|
||||||
builder: (context, value, child) {
|
builder: (context, value, child) {
|
||||||
final gifId = _parseGifId(value.text);
|
final gifId = GifHelper.parseGifId(value.text);
|
||||||
if (gifId != null) {
|
if (gifId != null) {
|
||||||
return Focus(
|
return Focus(
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import '../connector/meshcore_protocol.dart';
|
|||||||
import '../helpers/reaction_helper.dart';
|
import '../helpers/reaction_helper.dart';
|
||||||
import '../widgets/message_status_icon.dart';
|
import '../widgets/message_status_icon.dart';
|
||||||
import '../helpers/chat_scroll_controller.dart';
|
import '../helpers/chat_scroll_controller.dart';
|
||||||
|
import '../helpers/gif_helper.dart';
|
||||||
import '../helpers/path_helper.dart';
|
import '../helpers/path_helper.dart';
|
||||||
import '../helpers/utf8_length_limiter.dart';
|
import '../helpers/utf8_length_limiter.dart';
|
||||||
import '../models/channel_message.dart';
|
import '../models/channel_message.dart';
|
||||||
@@ -523,7 +524,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
child: ValueListenableBuilder<TextEditingValue>(
|
child: ValueListenableBuilder<TextEditingValue>(
|
||||||
valueListenable: _textController,
|
valueListenable: _textController,
|
||||||
builder: (context, value, child) {
|
builder: (context, value, child) {
|
||||||
final gifId = _parseGifId(value.text);
|
final gifId = GifHelper.parseGifId(value.text);
|
||||||
if (gifId != null) {
|
if (gifId != null) {
|
||||||
return Focus(
|
return Focus(
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
@@ -598,28 +599,6 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String? _parseGifId(String text) {
|
|
||||||
final trimmed = text.trim();
|
|
||||||
final match = RegExp(r'^g:([A-Za-z0-9_-]+)$').firstMatch(trimmed);
|
|
||||||
if (match != null) {
|
|
||||||
return match.group(1);
|
|
||||||
}
|
|
||||||
final directUrlMatch = RegExp(
|
|
||||||
r'^(?:https?:\/\/)?media\.giphy\.com\/media\/([A-Za-z0-9_-]+)\/giphy\.gif$',
|
|
||||||
).firstMatch(trimmed);
|
|
||||||
if (directUrlMatch != null) {
|
|
||||||
return directUrlMatch.group(1);
|
|
||||||
}
|
|
||||||
// Giphy understands page URLs with just the ID, or any string and a
|
|
||||||
// dash before the ID, and redirects to a page with a dash-separated
|
|
||||||
// title, a dash, and the ID. IDs in this form *probably* can't
|
|
||||||
// contain dashes.
|
|
||||||
final pageMatch = RegExp(
|
|
||||||
r'^(?:https?:\/\/)?giphy\.com\/gifs\/(?:[^/?]*-)?([A-Za-z0-9_]+)\/?$',
|
|
||||||
).firstMatch(trimmed);
|
|
||||||
return pageMatch?.group(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showGifPicker(BuildContext context) {
|
void _showGifPicker(BuildContext context) {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -1589,7 +1568,7 @@ class _MessageBubble extends StatelessWidget {
|
|||||||
final enableTracing = settingsService.settings.enableMessageTracing;
|
final enableTracing = settingsService.settings.enableMessageTracing;
|
||||||
final isOutgoing = message.isOutgoing;
|
final isOutgoing = message.isOutgoing;
|
||||||
final colorScheme = Theme.of(context).colorScheme;
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
final gifId = _parseGifId(message.text);
|
final gifId = GifHelper.parseGifId(message.text);
|
||||||
final poi = _parsePoiMessage(message.text);
|
final poi = _parsePoiMessage(message.text);
|
||||||
final isFailed = message.status == MessageStatus.failed;
|
final isFailed = message.status == MessageStatus.failed;
|
||||||
final bubbleColor = isFailed
|
final bubbleColor = isFailed
|
||||||
@@ -1863,12 +1842,6 @@ class _MessageBubble extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String? _parseGifId(String text) {
|
|
||||||
final trimmed = text.trim();
|
|
||||||
final match = RegExp(r'^g:([A-Za-z0-9_-]+)$').firstMatch(trimmed);
|
|
||||||
return match?.group(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_PoiInfo? _parsePoiMessage(String text) {
|
_PoiInfo? _parsePoiMessage(String text) {
|
||||||
final trimmed = text.trim();
|
final trimmed = text.trim();
|
||||||
final match = RegExp(
|
final match = RegExp(
|
||||||
|
|||||||
Reference in New Issue
Block a user