Add emote and badge size sliders (#66)

Closes #66
This commit is contained in:
Tommy Chow 2022-01-11 20:58:30 -05:00
parent b35fcc2fa4
commit 89443247fe
5 changed files with 117 additions and 24 deletions

View file

@ -78,15 +78,14 @@ class IRCMessage {
List<InlineSpan> generateSpan({
required TextStyle? style,
required ChatAssetsStore assetsStore,
required double badgeHeight,
required double emoteHeight,
bool showMessage = true,
bool useZeroWidth = false,
bool useReadableColors = false,
bool? isLightTheme,
TimestampType timestamp = TimestampType.disabled,
}) {
const badgeHeight = 20.0;
const emoteHeight = 30.0;
final emoteToObject = assetsStore.emoteToObject;
final twitchBadgeToObject = assetsStore.twitchBadgesToObject;
final ffzUserToBadges = assetsStore.userToFFZBadges;
@ -307,20 +306,6 @@ class IRCMessage {
))
.toList();
// Regex from dart_emoji package; used for emoji compatibility with zero-width
final regexEmoji = RegExp(
r'[\u{1f300}-\u{1f5ff}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}'
r'\u{1f680}-\u{1f6ff}\u{2600}-\u{26ff}\u{2700}'
r'-\u{27bf}\u{1f1e6}-\u{1f1ff}\u{1f191}-\u{1f251}'
r'\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}'
r'-\u{1f17f}\u{1f18e}\u{3030}\u{2b50}\u{2b55}'
r'\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}'
r'-\u{2b1c}\u{3297}\u{3299}\u{303d}\u{00a9}'
r'\u{00ae}\u{2122}\u{23f3}\u{24c2}\u{23e9}'
r'-\u{23ef}\u{25b6}\u{23f8}-\u{23fa}\u{200d}]+',
unicode: true,
);
var nextWordIsEmoji = false;
if (regexEmoji.hasMatch(words[index])) nextWordIsEmoji = true;
@ -332,7 +317,15 @@ class IRCMessage {
preferBelow: false,
child: Stack(
alignment: AlignmentDirectional.center,
children: nextWordIsEmoji ? [Text(words[index]), ...stack] : stack,
children: nextWordIsEmoji
? [
Text(
words[index],
style: textStyle?.copyWith(fontSize: emoteHeight),
),
...stack
]
: stack,
),
),
),
@ -352,7 +345,11 @@ class IRCMessage {
);
}
} else {
localSpan.add(_createTextSpan(text: word, style: textStyle));
if (regexEmoji.hasMatch(word)) {
localSpan.add(_createTextSpan(text: word, style: textStyle?.copyWith(fontSize: emoteHeight)));
} else {
localSpan.add(_createTextSpan(text: word, style: textStyle));
}
}
localSpan.add(const TextSpan(text: ' '));
index--;
@ -372,7 +369,11 @@ class IRCMessage {
),
);
} else {
span.add(_createTextSpan(text: word, style: textStyle));
if (regexEmoji.hasMatch(word)) {
span.add(_createTextSpan(text: word, style: textStyle?.copyWith(fontSize: emoteHeight)));
} else {
span.add(_createTextSpan(text: word, style: textStyle));
}
}
}
}
@ -676,3 +677,17 @@ enum Command {
globalUserState,
none,
}
// Regex from dart_emoji package; used for emoji compatibility with zero-width
final regexEmoji = RegExp(
r'[\u{1f300}-\u{1f5ff}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}'
r'\u{1f680}-\u{1f6ff}\u{2600}-\u{26ff}\u{2700}'
r'-\u{27bf}\u{1f1e6}-\u{1f1ff}\u{1f191}-\u{1f251}'
r'\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}'
r'-\u{1f17f}\u{1f18e}\u{3030}\u{2b50}\u{2b55}'
r'\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}'
r'-\u{2b1c}\u{3297}\u{3299}\u{303d}\u{00a9}'
r'\u{00ae}\u{2122}\u{23f3}\u{24c2}\u{23e9}'
r'-\u{23ef}\u{25b6}\u{23f8}-\u{23fa}\u{200d}]+',
unicode: true,
);

View file

@ -31,6 +31,8 @@ class ChatMessage extends StatelessWidget {
children: ircMessage.generateSpan(
style: DefaultTextStyle.of(context).style,
assetsStore: assetsStore,
emoteHeight: settingsStore.emoteHeight,
badgeHeight: settingsStore.badgeHeight,
useZeroWidth: settingsStore.showZeroWidth,
useReadableColors: settingsStore.useReadableColors,
isLightTheme: Theme.of(context).brightness == Brightness.light,
@ -68,6 +70,8 @@ class ChatMessage extends StatelessWidget {
children: ircMessage.generateSpan(
style: DefaultTextStyle.of(context).style,
assetsStore: assetsStore,
emoteHeight: settingsStore.emoteHeight,
badgeHeight: settingsStore.badgeHeight,
showMessage: settingsStore.showDeletedMessages,
useZeroWidth: settingsStore.showZeroWidth,
useReadableColors: settingsStore.useReadableColors,
@ -122,6 +126,8 @@ class ChatMessage extends StatelessWidget {
children: ircMessage.generateSpan(
style: DefaultTextStyle.of(context).style,
assetsStore: assetsStore,
emoteHeight: settingsStore.emoteHeight,
badgeHeight: settingsStore.badgeHeight,
useZeroWidth: settingsStore.showZeroWidth,
useReadableColors: settingsStore.useReadableColors,
isLightTheme: Theme.of(context).brightness == Brightness.light,

View file

@ -80,13 +80,21 @@ class _ChatSettingsState extends State<ChatSettings> {
Text.rich(
TextSpan(
children: [
const TextSpan(text: 'Hello! This is a text preview message '),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: CachedNetworkImage(
imageUrl: 'https://static-cdn.jtvnw.net/badges/v1/bbbe0db0-a598-423e-86d0-f9fb98ca1933/3',
placeholder: (context, url) => const SizedBox(),
height: settingsStore.badgeHeight,
),
),
const TextSpan(text: ' Badge and emote preview '),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: CachedNetworkImage(
imageUrl: 'https://static-cdn.jtvnw.net/emoticons/v2/425618/default/dark/3.0',
placeholder: (context, url) => const SizedBox(),
height: 30.0,
height: settingsStore.emoteHeight,
),
),
],
@ -95,12 +103,12 @@ class _ChatSettingsState extends State<ChatSettings> {
),
SizedBox(height: settingsStore.messageSpacing),
Text(
'Here is a another message to visualize spacing!',
'Hello! Here\'s a text preview.',
textScaleFactor: settingsStore.fontScale,
),
SizedBox(height: settingsStore.messageSpacing),
Text(
'And one more for spacing without an emote!',
'And another for spacing without an emote!',
textScaleFactor: settingsStore.fontScale,
),
],
@ -129,6 +137,26 @@ class _ChatSettingsState extends State<ChatSettings> {
onChanged: (newValue) => settingsStore.messageSpacing = newValue,
),
),
ListTile(
title: Text('Badge height: ${settingsStore.badgeHeight.toStringAsFixed(0)}'),
subtitle: Slider.adaptive(
value: settingsStore.badgeHeight,
min: 10.0,
max: 50.0,
divisions: 8,
onChanged: (newValue) => settingsStore.badgeHeight = newValue,
),
),
ListTile(
title: Text('Emote height: ${settingsStore.emoteHeight.toStringAsFixed(0)}'),
subtitle: Slider.adaptive(
value: settingsStore.emoteHeight,
min: 10.0,
max: 50.0,
divisions: 8,
onChanged: (newValue) => settingsStore.emoteHeight = newValue,
),
),
Container(
padding: const EdgeInsets.all(10.0),
width: double.infinity,

View file

@ -64,6 +64,14 @@ abstract class _SettingsStoreBase with Store {
@observable
var messageSpacing = 10.0;
@JsonKey(defaultValue: 20.0)
@observable
var badgeHeight = 20.0;
@JsonKey(defaultValue: 30.0)
@observable
var emoteHeight = 30.0;
// Global configs
@JsonKey(defaultValue: false)
@observable

View file

@ -25,6 +25,8 @@ SettingsStore _$SettingsStoreFromJson(Map<String, dynamic> json) =>
..useReadableColors = json['useReadableColors'] as bool? ?? true
..fontScale = (json['fontScale'] as num?)?.toDouble() ?? 1.0
..messageSpacing = (json['messageSpacing'] as num?)?.toDouble() ?? 10.0
..badgeHeight = (json['badgeHeight'] as num?)?.toDouble() ?? 20.0
..emoteHeight = (json['emoteHeight'] as num?)?.toDouble() ?? 30.0
..fullScreen = json['fullScreen'] as bool? ?? false
..expandInfo = json['expandInfo'] as bool? ?? true;
@ -42,6 +44,8 @@ Map<String, dynamic> _$SettingsStoreToJson(SettingsStore instance) =>
'useReadableColors': instance.useReadableColors,
'fontScale': instance.fontScale,
'messageSpacing': instance.messageSpacing,
'badgeHeight': instance.badgeHeight,
'emoteHeight': instance.emoteHeight,
'fullScreen': instance.fullScreen,
'expandInfo': instance.expandInfo,
};
@ -251,6 +255,36 @@ mixin _$SettingsStore on _SettingsStoreBase, Store {
});
}
final _$badgeHeightAtom = Atom(name: '_SettingsStoreBase.badgeHeight');
@override
double get badgeHeight {
_$badgeHeightAtom.reportRead();
return super.badgeHeight;
}
@override
set badgeHeight(double value) {
_$badgeHeightAtom.reportWrite(value, super.badgeHeight, () {
super.badgeHeight = value;
});
}
final _$emoteHeightAtom = Atom(name: '_SettingsStoreBase.emoteHeight');
@override
double get emoteHeight {
_$emoteHeightAtom.reportRead();
return super.emoteHeight;
}
@override
set emoteHeight(double value) {
_$emoteHeightAtom.reportWrite(value, super.emoteHeight, () {
super.emoteHeight = value;
});
}
final _$fullScreenAtom = Atom(name: '_SettingsStoreBase.fullScreen');
@override
@ -296,6 +330,8 @@ timestampType: ${timestampType},
useReadableColors: ${useReadableColors},
fontScale: ${fontScale},
messageSpacing: ${messageSpacing},
badgeHeight: ${badgeHeight},
emoteHeight: ${emoteHeight},
fullScreen: ${fullScreen},
expandInfo: ${expandInfo}
''';