Compare commits

..

1 Commits

Author SHA1 Message Date
Reinaldo Neto 011c99d406 [FIX] Update the number of members from a room 2023-03-07 18:20:02 -03:00
11 changed files with 49 additions and 43 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,31 +1,34 @@
import React from 'react'; import React from 'react';
import { useWindowDimensions } from 'react-native';
import { FlatList } from 'react-native-gesture-handler'; import { FlatList } from 'react-native-gesture-handler';
import { IEmoji } from '../../definitions/IEmoji';
import scrollPersistTaps from '../../lib/methods/helpers/scrollPersistTaps';
import { PressableEmoji } from './PressableEmoji';
import { EMOJI_BUTTON_SIZE } from './styles'; import { EMOJI_BUTTON_SIZE } from './styles';
import scrollPersistTaps from '../../lib/methods/helpers/scrollPersistTaps';
import { IEmoji } from '../../definitions/IEmoji';
import { PressableEmoji } from './PressableEmoji';
interface IEmojiCategoryProps { interface IEmojiCategoryProps {
emojis: IEmoji[]; emojis: IEmoji[];
onEmojiSelected: (emoji: IEmoji) => void; onEmojiSelected: (emoji: IEmoji) => void;
tabLabel?: string; // needed for react-native-scrollable-tab-view only tabLabel?: string; // needed for react-native-scrollable-tab-view only
parentWidth: number;
} }
const EmojiCategory = ({ onEmojiSelected, emojis, parentWidth }: IEmojiCategoryProps): React.ReactElement | null => { const EmojiCategory = ({ onEmojiSelected, emojis }: IEmojiCategoryProps): React.ReactElement | null => {
if (!parentWidth) { const { width } = useWindowDimensions();
return null;
}
const numColumns = Math.trunc(parentWidth / EMOJI_BUTTON_SIZE); const numColumns = Math.trunc(width / EMOJI_BUTTON_SIZE);
const marginHorizontal = (parentWidth % EMOJI_BUTTON_SIZE) / 2; const marginHorizontal = (width % EMOJI_BUTTON_SIZE) / 2;
const renderItem = ({ item }: { item: IEmoji }) => <PressableEmoji emoji={item} onPress={onEmojiSelected} />; const renderItem = ({ item }: { item: IEmoji }) => <PressableEmoji emoji={item} onPress={onEmojiSelected} />;
if (!width) {
return null;
}
return ( return (
<FlatList <FlatList
key={`emoji-category-${parentWidth}`} // needed to update the numColumns when the width changes
key={`emoji-category-${width}`}
keyExtractor={item => (typeof item === 'string' ? item : item.name)} keyExtractor={item => (typeof item === 'string' ? item : item.name)}
data={emojis} data={emojis}
renderItem={renderItem} renderItem={renderItem}

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React from 'react';
import { View } from 'react-native'; import { View } from 'react-native';
import ScrollableTabView from 'react-native-scrollable-tab-view'; import ScrollableTabView from 'react-native-scrollable-tab-view';
@ -20,8 +20,6 @@ const EmojiPicker = ({
searchedEmojis = [] searchedEmojis = []
}: IEmojiPickerProps): React.ReactElement | null => { }: IEmojiPickerProps): React.ReactElement | null => {
const { colors } = useTheme(); const { colors } = useTheme();
const [parentWidth, setParentWidth] = useState(0);
const { frequentlyUsed, loaded } = useFrequentlyUsedEmoji(); const { frequentlyUsed, loaded } = useFrequentlyUsedEmoji();
const allCustomEmojis: ICustomEmojis = useAppSelector( const allCustomEmojis: ICustomEmojis = useAppSelector(
@ -52,14 +50,7 @@ const EmojiPicker = ({
if (!emojis.length) { if (!emojis.length) {
return null; return null;
} }
return ( return <EmojiCategory emojis={emojis} onEmojiSelected={(emoji: IEmoji) => handleEmojiSelect(emoji)} tabLabel={label} />;
<EmojiCategory
parentWidth={parentWidth}
emojis={emojis}
onEmojiSelected={(emoji: IEmoji) => handleEmojiSelect(emoji)}
tabLabel={label}
/>
);
}; };
if (!loaded) { if (!loaded) {
@ -67,13 +58,9 @@ const EmojiPicker = ({
} }
return ( return (
<View style={styles.emojiPickerContainer} onLayout={e => setParentWidth(e.nativeEvent.layout.width)}> <View style={styles.emojiPickerContainer}>
{searching ? ( {searching ? (
<EmojiCategory <EmojiCategory emojis={searchedEmojis} onEmojiSelected={(emoji: IEmoji) => handleEmojiSelect(emoji)} />
emojis={searchedEmojis}
onEmojiSelected={(emoji: IEmoji) => handleEmojiSelect(emoji)}
parentWidth={parentWidth}
/>
) : ( ) : (
<ScrollableTabView <ScrollableTabView
renderTabBar={() => <TabBar />} renderTabBar={() => <TabBar />}

View File

@ -18,7 +18,7 @@ const MessageAvatar = React.memo(({ isHeader, avatar, author, small, navToRoomIn
style={small ? styles.avatarSmall : styles.avatar} style={small ? styles.avatarSmall : styles.avatar}
text={avatar ? '' : author.username} text={avatar ? '' : author.username}
size={small ? 20 : 36} size={small ? 20 : 36}
borderRadius={4} borderRadius={small ? 2 : 4}
onPress={author._id === user.id ? undefined : () => navToRoomInfo(navParam)} onPress={author._id === user.id ? undefined : () => navToRoomInfo(navParam)}
getCustomEmoji={getCustomEmoji} getCustomEmoji={getCustomEmoji}
avatar={avatar} avatar={avatar}

View File

@ -247,8 +247,6 @@ const Reply = React.memo(
> >
<View style={styles.attachmentContainer}> <View style={styles.attachmentContainer}>
<Title attachment={attachment} timeFormat={timeFormat} theme={theme} /> <Title attachment={attachment} timeFormat={timeFormat} theme={theme} />
<Description attachment={attachment} getCustomEmoji={getCustomEmoji} theme={theme} />
<UrlImage image={attachment.thumb_url} />
<Attachments <Attachments
attachments={attachment.attachments} attachments={attachment.attachments}
getCustomEmoji={getCustomEmoji} getCustomEmoji={getCustomEmoji}
@ -257,6 +255,8 @@ const Reply = React.memo(
isReply isReply
id={messageId} id={messageId}
/> />
<UrlImage image={attachment.thumb_url} />
<Description attachment={attachment} getCustomEmoji={getCustomEmoji} theme={theme} />
<Fields attachment={attachment} getCustomEmoji={getCustomEmoji} theme={theme} /> <Fields attachment={attachment} getCustomEmoji={getCustomEmoji} theme={theme} />
{loading ? ( {loading ? (
<View style={[styles.backdrop]}> <View style={[styles.backdrop]}>

View File

@ -102,6 +102,7 @@ export interface ISubscription {
onHold?: boolean; onHold?: boolean;
source?: IOmnichannelSource; source?: IOmnichannelSource;
hideMentionStatus?: boolean; hideMentionStatus?: boolean;
usersCount?: number;
// https://nozbe.github.io/WatermelonDB/Relation.html#relation-api // https://nozbe.github.io/WatermelonDB/Relation.html#relation-api
messages: RelationModified<TMessageModel>; messages: RelationModified<TMessageModel>;
threads: RelationModified<TThreadModel>; threads: RelationModified<TThreadModel>;

View File

@ -137,5 +137,7 @@ export default class Subscription extends Model {
@field('on_hold') onHold; @field('on_hold') onHold;
@field('users_count') usersCount;
@json('source', sanitizer) source; @json('source', sanitizer) source;
} }

View File

@ -257,6 +257,15 @@ export default schemaMigrations({
columns: [{ name: 'e2e_suggested_key', type: 'string', isOptional: true }] columns: [{ name: 'e2e_suggested_key', type: 'string', isOptional: true }]
}) })
] ]
},
{
toVersion: 21,
steps: [
addColumns({
table: 'subscriptions',
columns: [{ name: 'users_count', type: 'string', isOptional: true }]
})
]
} }
] ]
}); });

View File

@ -1,7 +1,7 @@
import { appSchema, tableSchema } from '@nozbe/watermelondb'; import { appSchema, tableSchema } from '@nozbe/watermelondb';
export default appSchema({ export default appSchema({
version: 20, version: 21,
tables: [ tables: [
tableSchema({ tableSchema({
name: 'subscriptions', name: 'subscriptions',
@ -63,7 +63,8 @@ export default appSchema({
{ name: 'team_main', type: 'boolean', isOptional: true }, // Use `Q.notEq(true)` to get false or null { name: 'team_main', type: 'boolean', isOptional: true }, // Use `Q.notEq(true)` to get false or null
{ name: 'on_hold', type: 'boolean', isOptional: true }, { name: 'on_hold', type: 'boolean', isOptional: true },
{ name: 'source', type: 'string', isOptional: true }, { name: 'source', type: 'string', isOptional: true },
{ name: 'hide_mention_status', type: 'boolean', isOptional: true } { name: 'hide_mention_status', type: 'boolean', isOptional: true },
{ name: 'users_count', type: 'number', isOptional: true }
] ]
}), }),
tableSchema({ tableSchema({

View File

@ -85,6 +85,9 @@ export const merge = (
if (room && 'source' in room) { if (room && 'source' in room) {
mergedSubscription.source = room?.source; mergedSubscription.source = room?.source;
} }
if (room && 'usersCount' in room) {
mergedSubscription.usersCount = room.usersCount;
}
} }
if (!mergedSubscription.name) { if (!mergedSubscription.name) {

View File

@ -85,7 +85,7 @@ interface IRoomActionsViewProps extends IActionSheetProvider, IBaseScreen<ChatsS
interface IRoomActionsViewState { interface IRoomActionsViewState {
room: TSubscriptionModel; room: TSubscriptionModel;
membersCount: number; membersCount?: number;
member: Partial<IUser>; member: Partial<IUser>;
joined: boolean; joined: boolean;
canViewMembers: boolean; canViewMembers: boolean;
@ -152,7 +152,7 @@ class RoomActionsView extends React.Component<IRoomActionsViewProps, IRoomAction
this.roomObservable = room.observe(); this.roomObservable = room.observe();
this.subscription = this.roomObservable.subscribe(changes => { this.subscription = this.roomObservable.subscribe(changes => {
if (this.mounted) { if (this.mounted) {
this.setState({ room: changes }); this.setState({ room: changes, membersCount: changes.usersCount });
} else { } else {
// @ts-ignore // @ts-ignore
this.state.room = changes; this.state.room = changes;
@ -1050,7 +1050,7 @@ class RoomActionsView extends React.Component<IRoomActionsViewProps, IRoomAction
<> <>
<List.Item <List.Item
title='Members' title='Members'
subtitle={membersCount > 0 ? `${membersCount} ${I18n.t('members')}` : undefined} subtitle={membersCount && membersCount > 0 ? `${membersCount} ${I18n.t('members')}` : undefined}
onPress={() => this.onPressTouchable({ route: 'RoomMembersView', params: { rid, room, joined: this.joined } })} onPress={() => this.onPressTouchable({ route: 'RoomMembersView', params: { rid, room, joined: this.joined } })}
testID='room-actions-members' testID='room-actions-members'
left={() => <List.Icon name='team' />} left={() => <List.Icon name='team' />}