Skip to content

Commit

Permalink
feat(reactions): added add reaction button to message menu + emoji se…
Browse files Browse the repository at this point in the history
…lector

Signed-off-by: m-doescode <[email protected]>
  • Loading branch information
m-doescode committed Mar 7, 2025
1 parent 8b1129e commit fb7cb63
Show file tree
Hide file tree
Showing 10 changed files with 444 additions and 10 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@
"intl-pluralrules": "^2.0.1",
"mobx": "^6.13.6",
"mobx-react-lite": "^4.1.0",
"patch-package": "^8.0.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-error-boundary": "^5.0.0",
"react-i18next": "^15.4.1",
"react-native": "^0.78.0",
"react-native-device-info": "^14.0.4",
"react-native-drawer-layout": "^4.1.1",
"react-native-emoji-selector": "^0.2.0",
"react-native-gesture-handler": "^2.24.0",
"react-native-get-random-values": "^1.11.0",
"react-native-keyboard-controller": "^1.16.6",
Expand Down
30 changes: 30 additions & 0 deletions patches/react-native-emoji-selector+0.2.0.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
diff --git a/node_modules/react-native-emoji-selector/index.js b/node_modules/react-native-emoji-selector/index.js
index 0737acd..a1d1f2c 100644
--- a/node_modules/react-native-emoji-selector/index.js
+++ b/node_modules/react-native-emoji-selector/index.js
@@ -70,6 +70,7 @@ const categoryKeys = Object.keys(Categories);

const TabBar = ({ theme, activeCategory, onPress, width }) => {
const tabSize = width / categoryKeys.length;
+ if (tabSize - 12 < 1) return;

return categoryKeys.map(c => {
const category = Categories[c];
@@ -80,7 +81,7 @@ const TabBar = ({ theme, activeCategory, onPress, width }) => {
onPress={() => onPress(category)}
style={{
flex: 1,
- height: tabSize,
+ height: tabSize + 12,
borderColor: category === activeCategory ? theme : "#EEEEEE",
borderBottomWidth: 2,
alignItems: "center",
@@ -91,7 +92,7 @@ const TabBar = ({ theme, activeCategory, onPress, width }) => {
style={{
textAlign: "center",
paddingBottom: 8,
- fontSize: tabSize - 24
+ fontSize: tabSize - 12
}}
>
{category.symbol}
5 changes: 5 additions & 0 deletions src/Generic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,11 @@ export const app = {
`[FUNCTIONS] Tried to run uninitialised function openMessage (args: ${m})`,
);
},
openAddReaction: (m: Message | null) => {
console.log(
`[FUNCTIONS] Tried to run uninitialised function openAddReaction (args: ${m})`
);
},
openChannelContextMenu: (c: Channel | null) => {
console.log(
`[FUNCTIONS] Tried to run uninitialised function openChannelContextMenu (args: ${c})`,
Expand Down
2 changes: 2 additions & 0 deletions src/Modals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
ServerSettingsSheet,
SettingsSheet,
StatusSheet,
AddReactionSheet
} from '@clerotri/components/sheets';

// Modals appear to break on the new architecture unless you wrap them in a View. see also https://github.com/react-navigation/react-navigation/issues/12301#issuecomment-2501692557
Expand Down Expand Up @@ -179,6 +180,7 @@ export const Modals = observer(() => {
<MemberListSheet />
<PinnedMessagesSheet />
<ServerInfoSheet />
<AddReactionSheet />
<FixedModal
visible={!!imageViewerState.i}
transparent={true}
Expand Down
12 changes: 9 additions & 3 deletions src/components/common/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import {StyleSheet} from 'react-native';
import BottomSheetCore, {
BottomSheetBackdrop,
BottomSheetScrollView,
BottomSheetView
} from '@gorhom/bottom-sheet';
import {observer} from 'mobx-react-lite';

import {commonValues, Theme, ThemeContext} from '@clerotri/lib/themes';

export const BottomSheet = observer(
({sheetRef, children}: {sheetRef: any; children: any}) => {
({sheetRef, innerScroll, children}: {sheetRef: any; innerScroll?: boolean; children: any}) => {
const {currentTheme} = useContext(ThemeContext);
const localStyles = useMemo(
() => generateLocalStyles(currentTheme),
Expand All @@ -28,8 +29,13 @@ export const BottomSheet = observer(
backdropComponent={BottomSheetBackdrop}
style={localStyles.sheet}
backgroundStyle={localStyles.sheetBackground}
handleIndicatorStyle={localStyles.handleIndicator}>
<BottomSheetScrollView>{children}</BottomSheetScrollView>
handleIndicatorStyle={localStyles.handleIndicator}
enableContentPanningGesture={!innerScroll}>
{innerScroll ? (
<BottomSheetView style={{ flexDirection: 'column', flex: 1 }}>{children}</BottomSheetView>
) : (
<BottomSheetScrollView>{children}</BottomSheetScrollView>
)}
</BottomSheetCore>
);
},
Expand Down
27 changes: 27 additions & 0 deletions src/components/common/messaging/MessageReactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import {useContext} from 'react';
import {Pressable, View} from 'react-native';
import {action} from 'mobx';
import {observer} from 'mobx-react-lite';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';

import type {Message} from 'revolt.js';

import {app} from '@clerotri/Generic';
import {client} from '@clerotri/lib/client';
import {Text} from '@clerotri/components/common/atoms';
import {Image} from '@clerotri/crossplat/Image';
Expand Down Expand Up @@ -66,6 +68,31 @@ export const MessageReactions = observer(
</Pressable>
);
})}

<Pressable
key={`message-${msg._id}-add-reaction}`}
onPress={action(() => {
msg.channel?.havePermission('React')
? app.openAddReaction(msg)
: showToast('You cannot react to this message.');
})}
style={{
padding: commonValues.sizes.small,
borderRadius: commonValues.sizes.small,
borderColor: currentTheme.backgroundTertiary,
backgroundColor: currentTheme.backgroundSecondary,
borderWidth: commonValues.sizes.xs,
marginEnd: commonValues.sizes.small,
marginVertical: commonValues.sizes.xs,
}}>
<View style={{flexDirection: 'row'}}>
<MaterialIcon
name="add-reaction"
size={20}
color={currentTheme.foregroundPrimary}
/>
</View>
</Pressable>
</View>
);
}
Expand Down
67 changes: 67 additions & 0 deletions src/components/sheets/AddReactionSheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useContext, useRef, useState, useMemo } from 'react';
import { View, Text } from 'react-native';
import { observer } from 'mobx-react-lite';
import EmojiSelector from 'react-native-emoji-selector';
// import EmojiPicker from 'emoji-picker-react';

import type BottomSheetCore from '@gorhom/bottom-sheet';

import type { Message } from 'revolt.js';

import { client } from '@clerotri/lib/client';
import { showToast } from '@clerotri/lib/utils';
import { app, setFunction } from '@clerotri/Generic';
import { BottomSheet } from '@clerotri/components/common/BottomSheet';
import { ThemeContext } from '@clerotri/lib/themes';
import { useBackHandler } from '@clerotri/lib/ui';

export const AddReactionSheet = observer(() => {
const { currentTheme } = useContext(ThemeContext);

const [message, setMessage] = useState(null as Message | null);

const sheetRef = useRef<BottomSheetCore>(null);

useBackHandler(() => {
if (message) {
sheetRef.current?.close();
return true;
}

return false;
});

setFunction('openAddReaction', async (m: Message | null) => {
setMessage(m);
m ? sheetRef.current?.expand() : sheetRef.current?.close();
});

function selectEmoji(emoji: string) {
if (!message) return;

const reaction = message.reactions.get(emoji) || [];

message.channel?.havePermission('React')
? !Array.from(reaction).includes(client.user?._id!)
? message.react(emoji)
: message.unreact(emoji)
: showToast('You cannot react to this message.');
app.openAddReaction(null);
}

return (
// BottomSheet cannot wrap our children in a scroll view because it will
// create a nested set of scroll views which causes issues
<BottomSheet innerScroll={true} sheetRef={sheetRef}>
<View style={{ paddingHorizontal: 16, flex: 1 }}>
{!message ? (
<></>
) : (
<EmojiSelector
onEmojiSelected={selectEmoji}
columns={8} />
)}
</View>
</BottomSheet>
);
});
18 changes: 17 additions & 1 deletion src/components/sheets/MessageMenuSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,23 @@ export const MessageMenuSheet = observer(() => {
}}>
<ReplyMessage message={message} showSymbol={false} />
</View>
{message.channel?.havePermission('SendMessage') ? (
{message.channel?.havePermission('React') ? (
<ContextButton
onPress={() => {
app.openAddReaction(message);
app.openMessage(null);
}}>
<View style={styles.iconContainer}>
<MaterialIcon
name="add-reaction"
size={20}
color={currentTheme.foregroundPrimary}
/>
</View>
<Text>Add Reaction</Text>
</ContextButton>
) : null}
{message.channel?.havePermission('SendMessage') && settings.get('ui.messaging.showReactions') ? (
<ContextButton
onPress={() => {
let replyingMessages = [...app.getReplyingMessages()];
Expand Down
1 change: 1 addition & 0 deletions src/components/sheets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export {ServerInviteSheet} from './ServerInviteSheet';
export {ServerSettingsSheet} from './ServerSettingsSheet';
export {SettingsSheet} from './SettingsSheet';
export {StatusSheet} from './StatusSheet';
export {AddReactionSheet} from './AddReactionSheet';
Loading

0 comments on commit fb7cb63

Please sign in to comment.