Skip to content

Commit

Permalink
feat: add animated emoji support
Browse files Browse the repository at this point in the history
- implement animated emoji support in both HTML and Linkify message type
- fix some missing font glyphs
- trim message input

Signed-off-by: The one with the braid <[email protected]>
  • Loading branch information
The one with the braid authored and TheOneWithTheBraid committed Nov 17, 2023
1 parent c149503 commit dc8d77b
Show file tree
Hide file tree
Showing 30 changed files with 842 additions and 174 deletions.
2 changes: 2 additions & 0 deletions assets/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2484,6 +2484,8 @@
"oldDisplayName": {}
}
},
"autoplayAnimations": "Automatically play animations",
"defaultEmojiTone": "Default emoji tone",
"newSpaceDescription": "Spaces allows you to consolidate your chats and build private or public communities.",
"encryptThisChat": "Encrypt this chat",
"endToEndEncryption": "End to end encryption",
Expand Down
Binary file added fonts/NotoSansSymbols-VariableFont_wght.ttf
Binary file not shown.
4 changes: 2 additions & 2 deletions lib/config/app_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ abstract class AppConfig {
static bool hideUnknownEvents = true;
static bool hideUnimportantStateEvents = true;
static bool separateChatTypes = false;
static bool autoplayImages = true;
static bool autoplayImages = false;
static bool sendTypingNotifications = true;
static bool sendOnEnter = false;
static bool experimentalVoip = false;
Expand All @@ -60,7 +60,7 @@ abstract class AppConfig {
static const String pushNotificationsGatewayUrl =
'https://push.fluffychat.im/_matrix/push/v1/notify';
static const String pushNotificationsPusherFormat = 'event_id_only';
static const String emojiFontName = 'Noto Emoji';
static const String emojiFontName = 'Noto Color Emoji';
static const String emojiFontUrl =
'https://github.com/googlefonts/noto-emoji/';
static const double borderRadius = 16.0;
Expand Down
2 changes: 1 addition & 1 deletion lib/config/themes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ abstract class FluffyThemes {

static const fallbackTextStyle = TextStyle(
fontFamily: 'Roboto',
fontFamilyFallback: ['NotoEmoji'],
fontFamilyFallback: [AppConfig.emojiFontName],
);

static var fallbackTextTheme = const TextTheme(
Expand Down
4 changes: 2 additions & 2 deletions lib/pages/bootstrap/bootstrap_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class BootstrapDialogState extends State<BootstrapDialog> {
minLines: 2,
maxLines: 4,
readOnly: true,
style: const TextStyle(fontFamily: 'RobotoMono'),
style: const TextStyle(fontFamily: 'Roboto Mono'),
controller: TextEditingController(text: key),
decoration: const InputDecoration(
contentPadding: EdgeInsets.all(16),
Expand Down Expand Up @@ -256,7 +256,7 @@ class BootstrapDialogState extends State<BootstrapDialog> {
? null
: [AutofillHints.password],
controller: _recoveryKeyTextEditingController,
style: const TextStyle(fontFamily: 'RobotoMono'),
style: const TextStyle(fontFamily: 'Roboto Mono'),
decoration: InputDecoration(
contentPadding: const EdgeInsets.all(16),
hintStyle: TextStyle(
Expand Down
19 changes: 7 additions & 12 deletions lib/pages/chat/chat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,6 @@ class ChatController extends State<ChatPageWithRoom> {

final int _loadHistoryCount = 100;

String inputText = '';

String pendingText = '';

bool showEmojiPicker = false;
Expand Down Expand Up @@ -295,7 +293,6 @@ class ChatController extends State<ChatPageWithRoom> {
final draft = prefs.getString('draft_$roomId');
if (draft != null && draft.isNotEmpty) {
sendController.text = draft;
setState(() => inputText = draft);
}
}

Expand Down Expand Up @@ -472,18 +469,18 @@ class ChatController extends State<ChatPageWithRoom> {

// ignore: unawaited_futures
room.sendTextEvent(
sendController.text,
sendController.text.trim(),
inReplyTo: replyEvent,
editEventId: editEvent?.eventId,
parseCommands: parseCommands,
);
// TextEditingValue required due to potential selection present
sendController.value = TextEditingValue(
text: pendingText,
selection: const TextSelection.collapsed(offset: 0),
);

setState(() {
inputText = pendingText;
replyEvent = null;
editEvent = null;
pendingText = '';
Expand Down Expand Up @@ -1051,7 +1048,7 @@ class ChatController extends State<ChatPageWithRoom> {
setState(() {
pendingText = sendController.text;
editEvent = selectedEvents.first;
inputText = sendController.text =
sendController.text =
editEvent!.getDisplayEvent(timeline!).calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: false,
Expand Down Expand Up @@ -1206,10 +1203,9 @@ class ChatController extends State<ChatPageWithRoom> {
if ((prefix.isNotEmpty) &&
text.toLowerCase() == '${prefix.toLowerCase()} ') {
setSendingClient(client);
setState(() {
inputText = '';
sendController.text = '';
});

sendController.text = '';

return;
}
}
Expand All @@ -1233,7 +1229,6 @@ class ChatController extends State<ChatPageWithRoom> {
);
}
}
setState(() => inputText = text);
}

bool get isArchived =>
Expand Down Expand Up @@ -1302,7 +1297,7 @@ class ChatController extends State<ChatPageWithRoom> {

void cancelReplyEventAction() => setState(() {
if (editEvent != null) {
inputText = sendController.text = pendingText;
sendController.text = pendingText;
pendingText = '';
}
replyEvent = null;
Expand Down
7 changes: 4 additions & 3 deletions lib/pages/chat/chat_input_row.dart
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class ChatInputRow extends StatelessWidget {
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,
height: 56,
width: controller.inputText.isEmpty ? 56 : 0,
width: controller.sendController.text.isEmpty ? 56 : 0,
alignment: Alignment.center,
clipBehavior: Clip.hardEdge,
decoration: const BoxDecoration(),
Expand Down Expand Up @@ -268,7 +268,7 @@ class ChatInputRow extends StatelessWidget {
),
),
if (PlatformInfos.platformCanRecord &&
controller.inputText.isEmpty)
controller.sendController.text.isEmpty)
Container(
height: 56,
alignment: Alignment.center,
Expand All @@ -278,7 +278,8 @@ class ChatInputRow extends StatelessWidget {
onPressed: controller.voiceMessageAction,
),
),
if (!PlatformInfos.isMobile || controller.inputText.isNotEmpty)
if (!PlatformInfos.isMobile ||
controller.sendController.text.isNotEmpty)
Container(
height: 56,
alignment: Alignment.center,
Expand Down
47 changes: 30 additions & 17 deletions lib/pages/chat/events/cute_events.dart
Original file line number Diff line number Diff line change
@@ -1,34 +1,43 @@
import 'dart:math';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart';

import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pages/settings_chat/settings_chat.dart';
import 'package:fluffychat/widgets/animated_emoji_plain_text.dart';
import 'package:fluffychat/widgets/matrix.dart';

class CuteContent extends StatefulWidget {
final Event event;
final Color color;

const CuteContent(this.event, {super.key});
const CuteContent(
this.event, {
super.key,
required this.color,
});

@override
State<CuteContent> createState() => _CuteContentState();
}

class _CuteContentState extends State<CuteContent> {
static bool _isOverlayShown = false;

@override
void initState() {
if (AppConfig.autoplayImages && !_isOverlayShown) {
addOverlay();
}
super.initState();
}
bool initialized = false;

@override
Widget build(BuildContext context) {
if (initialized == false) {
initialized = true;

if (Matrix.of(context).client.autoplayAnimatedContent ??
!kIsWeb && !_isOverlayShown) {
addOverlay();
}
}
return FutureBuilder<User?>(
future: widget.event.fetchSenderUser(),
builder: (context, snapshot) {
Expand All @@ -40,9 +49,10 @@ class _CuteContentState extends State<CuteContent> {
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
TextLinkifyEmojify(
widget.event.text,
style: const TextStyle(fontSize: 150),
fontSize: 150,
textColor: widget.color,
),
if (label != null) Text(label),
],
Expand Down Expand Up @@ -183,11 +193,14 @@ class _CuteOverlayContent extends StatelessWidget {

@override
Widget build(BuildContext context) {
return SizedBox.square(
dimension: size,
child: Text(
emoji,
style: const TextStyle(fontSize: 48),
return SizedOverflowBox(
size: const Size.square(size),
child: ClipRect(
clipBehavior: Clip.hardEdge,
child: Text(
emoji,
style: const TextStyle(fontSize: 56),
),
),
);
}
Expand Down
Loading

0 comments on commit dc8d77b

Please sign in to comment.