forked from Nexus/nexus
add support for setting recent emoji
This commit is contained in:
parent
ec1603b828
commit
810a0b102b
4 changed files with 103 additions and 60 deletions
44
lib/controllers/recent_emoji.dart
Normal file
44
lib/controllers/recent_emoji.dart
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import "package:collection/collection.dart";
|
||||||
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
|
import "package:nexus/controllers/account_data.dart";
|
||||||
|
import "package:nexus/controllers/client.dart";
|
||||||
|
import "package:nexus/models/account_data.dart";
|
||||||
|
|
||||||
|
class RecentEmojiController extends Notifier<IList<RecentEmoji>> {
|
||||||
|
@override
|
||||||
|
IList<RecentEmoji> build() => ref.watch(
|
||||||
|
AccountDataController.provider.select(
|
||||||
|
(value) => value.recentEmoji.recentEmoji,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<void> add(String emoji) => ref
|
||||||
|
.watch(ClientController.provider.notifier)
|
||||||
|
.setAccountData(
|
||||||
|
.new(
|
||||||
|
type: AccountData.recentEmojiKey,
|
||||||
|
content: RecentEmojiData(
|
||||||
|
recentEmoji: .new([
|
||||||
|
.new(
|
||||||
|
emoji: emoji,
|
||||||
|
total:
|
||||||
|
(state
|
||||||
|
.firstWhereOrNull(
|
||||||
|
(element) => element.emoji == emoji,
|
||||||
|
)
|
||||||
|
?.total ??
|
||||||
|
0) +
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
...state.whereNot((element) => element.emoji == emoji),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
static final provider =
|
||||||
|
NotifierProvider.autoDispose<RecentEmojiController, IList<RecentEmoji>>(
|
||||||
|
RecentEmojiController.new,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -14,22 +14,9 @@ class const AccountData({
|
||||||
@JsonKey(name: AccountData.directKey)
|
@JsonKey(name: AccountData.directKey)
|
||||||
final IMap<String, IList<String>> directMessages = const IMap.empty(),
|
final IMap<String, IList<String>> directMessages = const IMap.empty(),
|
||||||
|
|
||||||
@JsonKey(
|
@JsonKey(name: AccountData.recentEmojiKey)
|
||||||
name: AccountData.recentEmojiKey,
|
final RecentEmojiData recentEmoji = const RecentEmojiData(),
|
||||||
readValue: AccountData.readRecentEmojiValue,
|
|
||||||
toJson: AccountData.recentEmojiToJson,
|
|
||||||
)
|
|
||||||
final IList<RecentEmoji> recentEmoji = const IList.empty(),
|
|
||||||
}) with _$AccountData {
|
}) with _$AccountData {
|
||||||
static List<dynamic>? readRecentEmojiValue(
|
|
||||||
Map<dynamic, dynamic> json,
|
|
||||||
String key,
|
|
||||||
) => json[key]?["recent_emoji"];
|
|
||||||
|
|
||||||
static Map<String, List<dynamic>>? recentEmojiToJson(
|
|
||||||
IList<RecentEmoji> recentEmoji,
|
|
||||||
) => {"recent_emoji": recentEmoji.map((emoji) => emoji.toJson()).toList()};
|
|
||||||
|
|
||||||
static const invitePermissionConfigKey = "m.invite_permission_config";
|
static const invitePermissionConfigKey = "m.invite_permission_config";
|
||||||
static const directKey = "m.direct";
|
static const directKey = "m.direct";
|
||||||
static const recentEmojiKey = "m.recent_emoji";
|
static const recentEmojiKey = "m.recent_emoji";
|
||||||
|
|
@ -40,6 +27,17 @@ class const AccountData({
|
||||||
_$AccountDataFromJson(json);
|
_$AccountDataFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Freezed(toJson: false, fromJson: false)
|
||||||
|
@JsonSerializable()
|
||||||
|
class const RecentEmojiData({
|
||||||
|
final IList<RecentEmoji> recentEmoji = const IList.empty(),
|
||||||
|
}) with _$RecentEmojiData {
|
||||||
|
Map<String, Object?> toJson() => _$RecentEmojiDataToJson(this);
|
||||||
|
|
||||||
|
factory RecentEmojiData.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$RecentEmojiDataFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
@Freezed(toJson: false, fromJson: false)
|
@Freezed(toJson: false, fromJson: false)
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class const InvitePermissionConfig({
|
class const InvitePermissionConfig({
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import "dart:async";
|
import "dart:async";
|
||||||
|
|
||||||
import "package:collection/collection.dart";
|
import "package:collection/collection.dart";
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
|
||||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||||
import "package:material_emoji_picker/material_emoji_picker.dart" as upstream;
|
import "package:material_emoji_picker/material_emoji_picker.dart" as upstream;
|
||||||
import "package:material_ui/material_ui.dart";
|
import "package:material_ui/material_ui.dart";
|
||||||
import "package:nexus/controllers/account_data.dart";
|
import "package:nexus/controllers/recent_emoji.dart";
|
||||||
import "package:nexus/helpers/extensions/better_when.dart";
|
import "package:nexus/helpers/extensions/better_when.dart";
|
||||||
|
import "package:nexus/main.dart";
|
||||||
|
|
||||||
class const EmojiPicker({
|
class const EmojiPicker({
|
||||||
required final FutureOr<void> Function(String value) onSelection,
|
required final FutureOr<void> Function(String value) onSelection,
|
||||||
|
|
@ -14,13 +14,19 @@ class const EmojiPicker({
|
||||||
super.key,
|
super.key,
|
||||||
}) extends ConsumerWidget {
|
}) extends ConsumerWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) => ref
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final recentEmoji = ref.watch(RecentEmojiController.provider);
|
||||||
|
|
||||||
|
return ref
|
||||||
.watch(upstream.EmojiController.provider)
|
.watch(upstream.EmojiController.provider)
|
||||||
.betterWhen(
|
.betterWhen(
|
||||||
data: (categories) => upstream.EmojiPicker(
|
data: (categories) => upstream.EmojiPicker(
|
||||||
onSelection: (value) async {
|
onSelection: (emoji) async {
|
||||||
//
|
await onSelection(emoji);
|
||||||
await onSelection(value);
|
await ref
|
||||||
|
.watch(RecentEmojiController.provider.notifier)
|
||||||
|
.add(emoji)
|
||||||
|
.onError(showError);
|
||||||
},
|
},
|
||||||
allowFreeText: allowFreeText,
|
allowFreeText: allowFreeText,
|
||||||
prependCategories: .new([
|
prependCategories: .new([
|
||||||
|
|
@ -28,20 +34,13 @@ class const EmojiPicker({
|
||||||
icon: Icon(Icons.history),
|
icon: Icon(Icons.history),
|
||||||
name: "Recent",
|
name: "Recent",
|
||||||
emojis: .new(
|
emojis: .new(
|
||||||
ref
|
recentEmoji
|
||||||
.watch(
|
|
||||||
AccountDataController.provider.select(
|
|
||||||
(value) => value.recentEmoji
|
|
||||||
.map((entry) => entry.emoji)
|
|
||||||
.toIList(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.map(
|
.map(
|
||||||
(emoji) => categories
|
(recent) => categories
|
||||||
.map((element) => element.emojis)
|
.map((element) => element.emojis)
|
||||||
.flattened
|
.flattened
|
||||||
.firstWhereOrNull(
|
.firstWhereOrNull(
|
||||||
(element) => element.value == emoji,
|
(element) => element.value == recent.emoji,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.nonNulls,
|
.nonNulls,
|
||||||
|
|
@ -51,3 +50,4 @@ class const EmojiPicker({
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ import "package:flutter/services.dart";
|
||||||
import "package:flutter_hooks/flutter_hooks.dart";
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||||
import "package:measure_size/measure_size.dart";
|
import "package:measure_size/measure_size.dart";
|
||||||
import "package:nexus/controllers/account_data.dart";
|
|
||||||
import "package:nexus/controllers/client.dart";
|
import "package:nexus/controllers/client.dart";
|
||||||
import "package:nexus/controllers/client_state.dart";
|
import "package:nexus/controllers/client_state.dart";
|
||||||
import "package:nexus/controllers/member_list_opened.dart";
|
import "package:nexus/controllers/member_list_opened.dart";
|
||||||
import "package:nexus/controllers/pinned_ids.dart";
|
import "package:nexus/controllers/pinned_ids.dart";
|
||||||
import "package:nexus/controllers/power_level.dart";
|
import "package:nexus/controllers/power_level.dart";
|
||||||
|
import "package:nexus/controllers/recent_emoji.dart";
|
||||||
import "package:nexus/controllers/rooms.dart";
|
import "package:nexus/controllers/rooms.dart";
|
||||||
import "package:nexus/controllers/room_chat.dart";
|
import "package:nexus/controllers/room_chat.dart";
|
||||||
import "package:nexus/controllers/via.dart";
|
import "package:nexus/controllers/via.dart";
|
||||||
|
|
@ -196,6 +196,8 @@ final class const RoomChat({
|
||||||
final danger = theme.colorScheme.error;
|
final danger = theme.colorScheme.error;
|
||||||
final isSentByMe = event.sender == userId;
|
final isSentByMe = event.sender == userId;
|
||||||
|
|
||||||
|
final recentEmoji = ref.watch(RecentEmojiController.provider);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
if (ref.watch(
|
if (ref.watch(
|
||||||
PowerLevelController.provider(
|
PowerLevelController.provider(
|
||||||
|
|
@ -209,13 +211,7 @@ final class const RoomChat({
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
...{
|
...{
|
||||||
...ref.watch(
|
...recentEmoji.map((entry) => entry.emoji),
|
||||||
AccountDataController.provider.select(
|
|
||||||
(value) => value.recentEmoji
|
|
||||||
.map((entry) => entry.emoji)
|
|
||||||
.toIList(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
"👍",
|
"👍",
|
||||||
"🤣",
|
"🤣",
|
||||||
"😭",
|
"😭",
|
||||||
|
|
@ -230,6 +226,11 @@ final class const RoomChat({
|
||||||
await notifier
|
await notifier
|
||||||
.sendReaction(emoji, event)
|
.sendReaction(emoji, event)
|
||||||
.onError(showError);
|
.onError(showError);
|
||||||
|
|
||||||
|
ref
|
||||||
|
.watch(RecentEmojiController.provider.notifier)
|
||||||
|
.add(emoji)
|
||||||
|
.onError(showError);
|
||||||
},
|
},
|
||||||
icon: Text(emoji),
|
icon: Text(emoji),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue