Compare commits
89 Commits
develop
...
chore.try-
Author | SHA1 | Date |
---|---|---|
Diego Mello | 891b910772 | |
Diego Mello | d047cb0c49 | |
Diego Mello | 83b5e8a98a | |
Diego Mello | d860991c87 | |
Diego Mello | 7e849943fe | |
Diego Mello | 2b06b01bd6 | |
Diego Mello | 8678d079bc | |
Diego Mello | ff00ad169e | |
Diego Mello | 4e11189f7f | |
Diego Mello | 428fb5dccc | |
Diego Mello | ab53a5aaea | |
Diego Mello | 4dea3e7ce8 | |
Diego Mello | 868bfb7a4c | |
Diego Mello | e088d76724 | |
Diego Mello | e6ec8b4e39 | |
Diego Mello | 2683976d21 | |
Diego Mello | 976753c08b | |
Diego Mello | fd82771438 | |
Diego Mello | c610b6d7ec | |
Diego Mello | f71be55140 | |
Diego Mello | 8c9f7ffa54 | |
Diego Mello | 001f2a0c17 | |
Diego Mello | ffb31d399d | |
Diego Mello | 15bb21eb2f | |
Diego Mello | 9788e8a11f | |
Diego Mello | 2c62d9cb46 | |
Diego Mello | ae7398233a | |
Diego Mello | 7b526fe700 | |
Diego Mello | 654feb719c | |
Diego Mello | dbb9396042 | |
Diego Mello | c877a0600b | |
Diego Mello | 696a7e623d | |
Diego Mello | da113ac1d0 | |
Diego Mello | 1af737ee71 | |
Diego Mello | c867f2928f | |
Diego Mello | 87a5793f24 | |
Diego Mello | f5615c50f6 | |
Diego Mello | b2db5500b6 | |
Diego Mello | c6ecfa17a3 | |
Diego Mello | 595f010742 | |
Diego Mello | 0c4c361446 | |
Diego Mello | 53cda7ecb1 | |
Diego Mello | 04e49563f2 | |
Diego Mello | 36f0935e55 | |
Diego Mello | 2cefe12a91 | |
Diego Mello | 21dbc7e112 | |
Diego Mello | aaef77a58f | |
Diego Mello | cc5fe4c910 | |
Diego Mello | a593129a3c | |
Diego Mello | de6a897ec4 | |
Diego Mello | d42f623a2f | |
Diego Mello | 4aeda3f778 | |
Diego Mello | 34a30214c2 | |
Diego Mello | 79be07072c | |
Diego Mello | a73a535221 | |
Diego Mello | 4ca5e3a0a7 | |
Diego Mello | c0b3daa225 | |
Diego Mello | a130583ff4 | |
Diego Mello | 0b7c075560 | |
Diego Mello | edc67d424b | |
Diego Mello | fad04765d4 | |
Diego Mello | 7beaa62003 | |
Diego Mello | f67a4010bc | |
Diego Mello | 2ee4efd255 | |
Diego Mello | 4532a6929c | |
Diego Mello | 71dc0b8f50 | |
Diego Mello | 8ab84541f3 | |
Diego Mello | 363331c953 | |
Diego Mello | 360afcdd45 | |
Diego Mello | 83701d002f | |
Diego Mello | c0d5a84ccd | |
Diego Mello | 6b7b01af8d | |
Diego Mello | bac9eb79bb | |
Diego Mello | b9cafe9d31 | |
Diego Mello | a38bc37aaa | |
Diego Mello | 490e567c85 | |
Diego Mello | 45042661c5 | |
Diego Mello | e0b5030f6a | |
Diego Mello | 1ea3916e94 | |
Diego Mello | 537cd0032e | |
Diego Mello | e4f0fdb525 | |
Diego Mello | 86a7297abc | |
Diego Mello | 34f2da40aa | |
Diego Mello | 0317c4c27a | |
Diego Mello | 898a4a398b | |
Diego Mello | 6bb7db9993 | |
Diego Mello | 86d5529cfd | |
Diego Mello | 7bd4182bf7 | |
Diego Mello | b20c9b1632 |
|
@ -1,25 +0,0 @@
|
|||
package chat.rocket.reactnative;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
|
||||
public class MainDebugApplication extends MainApplication {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
|
||||
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
*
|
||||
* @param context
|
||||
* @param reactInstanceManager
|
||||
*/
|
||||
private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
|
||||
ReactNativeFlipper.initializeFlipper(context, reactInstanceManager);
|
||||
}
|
||||
}
|
|
@ -23,6 +23,8 @@ import com.facebook.react.ReactInstanceManager;
|
|||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.modules.network.NetworkingModule;
|
||||
import com.facebook.react.modules.network.CustomClientBuilder;
|
||||
import tech.bam.rnperformance.flipper.RNPerfMonitorPlugin;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
public class ReactNativeFlipper {
|
||||
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
|
||||
|
@ -33,6 +35,8 @@ public class ReactNativeFlipper {
|
|||
client.addPlugin(new DatabasesFlipperPlugin(context));
|
||||
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
|
||||
client.addPlugin(CrashReporterPlugin.getInstance());
|
||||
client.addPlugin(new RNPerfMonitorPlugin(reactInstanceManager));
|
||||
|
||||
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
|
||||
NetworkingModule.setCustomClientBuilder(
|
||||
new CustomClientBuilder() {
|
||||
|
|
|
@ -9,13 +9,16 @@ import com.facebook.react.ReactApplication;
|
|||
import com.facebook.react.ReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.config.ReactFeatureFlags;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import com.reactnativecommunity.viewpager.RNCViewPagerPackage;
|
||||
import com.facebook.react.bridge.JSIModulePackage;
|
||||
import com.swmansion.reanimated.ReanimatedJSIModulePackage;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import expo.modules.ApplicationLifecycleDispatcher;
|
||||
import expo.modules.ReactNativeHostWrapper;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -76,6 +79,7 @@ public class MainApplication extends Application implements ReactApplication {
|
|||
// If you opted-in for the New Architecture, we enable the TurboModule system
|
||||
ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
ApplicationLifecycleDispatcher.onApplicationCreate(this);
|
||||
}
|
||||
|
||||
|
@ -84,4 +88,35 @@ public class MainApplication extends Application implements ReactApplication {
|
|||
super.onConfigurationChanged(newConfig);
|
||||
ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
|
||||
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
*
|
||||
* @param context
|
||||
* @param reactInstanceManager
|
||||
*/
|
||||
private static void initializeFlipper(
|
||||
Context context, ReactInstanceManager reactInstanceManager) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
try {
|
||||
/*
|
||||
We use reflection here to pick up the class that initializes Flipper,
|
||||
since Flipper library is not available in release mode
|
||||
*/
|
||||
Class<?> aClass = Class.forName("chat.rocket.reactnative.ReactNativeFlipper");
|
||||
aClass
|
||||
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
|
||||
.invoke(null, context, reactInstanceManager);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ android.useAndroidX=true
|
|||
android.enableJetifier=true
|
||||
|
||||
# Version of flipper SDK to use with React Native
|
||||
FLIPPER_VERSION=0.125.0
|
||||
FLIPPER_VERSION=0.175.0
|
||||
|
||||
# Use this property to specify which architecture you want to build.
|
||||
# You can also override it from the CLI using
|
||||
|
|
|
@ -10,12 +10,12 @@ import { useFrequentlyUsedEmoji } from '../../lib/hooks';
|
|||
import CustomEmoji from '../EmojiPicker/CustomEmoji';
|
||||
import { useDimensions } from '../../dimensions';
|
||||
import sharedStyles from '../../views/Styles';
|
||||
import { IEmoji, TAnyMessageModel } from '../../definitions';
|
||||
import { IEmoji, TAnyMessage } from '../../definitions';
|
||||
import Touch from '../Touch';
|
||||
|
||||
export interface IHeader {
|
||||
handleReaction: (emoji: IEmoji | null, message: TAnyMessageModel) => void;
|
||||
message: TAnyMessageModel;
|
||||
handleReaction: (emoji: IEmoji | null, message: TAnyMessage) => void;
|
||||
message: TAnyMessage;
|
||||
isMasterDetail: boolean;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import { connect } from 'react-redux';
|
|||
import moment from 'moment';
|
||||
|
||||
import database from '../../lib/database';
|
||||
import { getMessageById } from '../../lib/database/services/Message';
|
||||
import I18n from '../../i18n';
|
||||
import log, { logEvent } from '../../lib/methods/helpers/log';
|
||||
import Navigation from '../../lib/navigation/appNavigation';
|
||||
|
@ -15,7 +16,7 @@ import { showConfirmationAlert } from '../../lib/methods/helpers/info';
|
|||
import { TActionSheetOptionsItem, useActionSheet, ACTION_SHEET_ANIMATION_DURATION } from '../ActionSheet';
|
||||
import Header, { HEADER_HEIGHT, IHeader } from './Header';
|
||||
import events from '../../lib/methods/helpers/log/events';
|
||||
import { IApplicationState, IEmoji, ILoggedUser, TAnyMessageModel, TSubscriptionModel } from '../../definitions';
|
||||
import { IApplicationState, IEmoji, ILoggedUser, TAnyMessage, TSubscriptionModel } from '../../definitions';
|
||||
import { getPermalinkMessage } from '../../lib/methods';
|
||||
import { getRoomTitle, getUidDirectMessage, hasPermission } from '../../lib/methods/helpers';
|
||||
import { Services } from '../../lib/services';
|
||||
|
@ -24,10 +25,10 @@ export interface IMessageActionsProps {
|
|||
room: TSubscriptionModel;
|
||||
tmid?: string;
|
||||
user: Pick<ILoggedUser, 'id'>;
|
||||
editInit: (message: TAnyMessageModel) => void;
|
||||
reactionInit: (message: TAnyMessageModel) => void;
|
||||
editInit: (message: TAnyMessage) => void;
|
||||
reactionInit: (message: TAnyMessage) => void;
|
||||
onReactionPress: (shortname: IEmoji, messageId: string) => void;
|
||||
replyInit: (message: TAnyMessageModel, mention: boolean) => void;
|
||||
replyInit: (message: TAnyMessage, mention: boolean) => void;
|
||||
isMasterDetail: boolean;
|
||||
isReadOnly: boolean;
|
||||
Message_AllowDeleting?: boolean;
|
||||
|
@ -46,7 +47,7 @@ export interface IMessageActionsProps {
|
|||
}
|
||||
|
||||
export interface IMessageActions {
|
||||
showMessageActions: (message: TAnyMessageModel) => Promise<void>;
|
||||
showMessageActions: (message: TAnyMessage) => Promise<void>;
|
||||
}
|
||||
|
||||
const MessageActions = React.memo(
|
||||
|
@ -109,9 +110,9 @@ const MessageActions = React.memo(
|
|||
}
|
||||
};
|
||||
|
||||
const isOwn = (message: TAnyMessageModel) => message.u && message.u._id === user.id;
|
||||
const isOwn = (message: TAnyMessage) => message.u && message.u._id === user.id;
|
||||
|
||||
const allowEdit = (message: TAnyMessageModel) => {
|
||||
const allowEdit = (message: TAnyMessage) => {
|
||||
if (isReadOnly) {
|
||||
return false;
|
||||
}
|
||||
|
@ -135,7 +136,7 @@ const MessageActions = React.memo(
|
|||
return true;
|
||||
};
|
||||
|
||||
const allowDelete = (message: TAnyMessageModel) => {
|
||||
const allowDelete = (message: TAnyMessage) => {
|
||||
if (isReadOnly) {
|
||||
return false;
|
||||
}
|
||||
|
@ -166,19 +167,19 @@ const MessageActions = React.memo(
|
|||
return true;
|
||||
};
|
||||
|
||||
const getPermalink = (message: TAnyMessageModel) => getPermalinkMessage(message);
|
||||
const getPermalink = (message: TAnyMessage) => getPermalinkMessage(message);
|
||||
|
||||
const handleReply = (message: TAnyMessageModel) => {
|
||||
const handleReply = (message: TAnyMessage) => {
|
||||
logEvent(events.ROOM_MSG_ACTION_REPLY);
|
||||
replyInit(message, true);
|
||||
};
|
||||
|
||||
const handleEdit = (message: TAnyMessageModel) => {
|
||||
const handleEdit = (message: TAnyMessage) => {
|
||||
logEvent(events.ROOM_MSG_ACTION_EDIT);
|
||||
editInit(message);
|
||||
};
|
||||
|
||||
const handleCreateDiscussion = (message: TAnyMessageModel) => {
|
||||
const handleCreateDiscussion = (message: TAnyMessage) => {
|
||||
logEvent(events.ROOM_MSG_ACTION_DISCUSSION);
|
||||
const params = { message, channel: room, showCloseModal: true };
|
||||
if (isMasterDetail) {
|
||||
|
@ -188,7 +189,7 @@ const MessageActions = React.memo(
|
|||
}
|
||||
};
|
||||
|
||||
const handleUnread = async (message: TAnyMessageModel) => {
|
||||
const handleUnread = async (message: TAnyMessage) => {
|
||||
logEvent(events.ROOM_MSG_ACTION_UNREAD);
|
||||
const { id: messageId, ts } = message;
|
||||
const { rid } = room;
|
||||
|
@ -213,7 +214,7 @@ const MessageActions = React.memo(
|
|||
}
|
||||
};
|
||||
|
||||
const handlePermalink = async (message: TAnyMessageModel) => {
|
||||
const handlePermalink = async (message: TAnyMessage) => {
|
||||
logEvent(events.ROOM_MSG_ACTION_PERMALINK);
|
||||
try {
|
||||
const permalink = await getPermalink(message);
|
||||
|
@ -224,13 +225,13 @@ const MessageActions = React.memo(
|
|||
}
|
||||
};
|
||||
|
||||
const handleCopy = async (message: TAnyMessageModel) => {
|
||||
const handleCopy = async (message: TAnyMessage) => {
|
||||
logEvent(events.ROOM_MSG_ACTION_COPY);
|
||||
await Clipboard.setString((message?.attachments?.[0]?.description || message.msg) ?? '');
|
||||
EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
|
||||
};
|
||||
|
||||
const handleShare = async (message: TAnyMessageModel) => {
|
||||
const handleShare = async (message: TAnyMessage) => {
|
||||
logEvent(events.ROOM_MSG_ACTION_SHARE);
|
||||
try {
|
||||
const permalink = await getPermalink(message);
|
||||
|
@ -242,12 +243,12 @@ const MessageActions = React.memo(
|
|||
}
|
||||
};
|
||||
|
||||
const handleQuote = (message: TAnyMessageModel) => {
|
||||
const handleQuote = (message: TAnyMessage) => {
|
||||
logEvent(events.ROOM_MSG_ACTION_QUOTE);
|
||||
replyInit(message, false);
|
||||
};
|
||||
|
||||
const handleReplyInDM = async (message: TAnyMessageModel) => {
|
||||
const handleReplyInDM = async (message: TAnyMessage) => {
|
||||
if (message?.u?.username) {
|
||||
const result = await Services.createDirectMessage(message.u.username);
|
||||
if (result.success) {
|
||||
|
@ -264,7 +265,7 @@ const MessageActions = React.memo(
|
|||
}
|
||||
};
|
||||
|
||||
const handleStar = async (message: TAnyMessageModel) => {
|
||||
const handleStar = async (message: TAnyMessage) => {
|
||||
logEvent(message.starred ? events.ROOM_MSG_ACTION_UNSTAR : events.ROOM_MSG_ACTION_STAR);
|
||||
try {
|
||||
await Services.toggleStarMessage(message.id, message.starred as boolean); // TODO: reevaluate `message.starred` type on IMessage
|
||||
|
@ -275,7 +276,7 @@ const MessageActions = React.memo(
|
|||
}
|
||||
};
|
||||
|
||||
const handlePin = async (message: TAnyMessageModel) => {
|
||||
const handlePin = async (message: TAnyMessage) => {
|
||||
logEvent(events.ROOM_MSG_ACTION_PIN);
|
||||
try {
|
||||
await Services.togglePinMessage(message.id, message.pinned as boolean); // TODO: reevaluate `message.pinned` type on IMessage
|
||||
|
@ -295,7 +296,7 @@ const MessageActions = React.memo(
|
|||
hideActionSheet();
|
||||
};
|
||||
|
||||
const handleReadReceipt = (message: TAnyMessageModel) => {
|
||||
const handleReadReceipt = (message: TAnyMessage) => {
|
||||
if (isMasterDetail) {
|
||||
Navigation.navigate('ModalStackNavigator', { screen: 'ReadReceiptsView', params: { messageId: message.id } });
|
||||
} else {
|
||||
|
@ -303,14 +304,18 @@ const MessageActions = React.memo(
|
|||
}
|
||||
};
|
||||
|
||||
const handleToggleTranslation = async (message: TAnyMessageModel) => {
|
||||
const handleToggleTranslation = async (message: TAnyMessage) => {
|
||||
try {
|
||||
if (!room.autoTranslateLanguage) {
|
||||
return;
|
||||
}
|
||||
const db = database.active;
|
||||
const messageRecord = await getMessageById(message.id);
|
||||
if (!messageRecord) {
|
||||
return;
|
||||
}
|
||||
await db.write(async () => {
|
||||
await message.update(m => {
|
||||
await messageRecord.update(m => {
|
||||
m.autoTranslate = !m.autoTranslate;
|
||||
m._updatedAt = new Date();
|
||||
});
|
||||
|
@ -324,7 +329,7 @@ const MessageActions = React.memo(
|
|||
}
|
||||
};
|
||||
|
||||
const handleReport = async (message: TAnyMessageModel) => {
|
||||
const handleReport = async (message: TAnyMessage) => {
|
||||
logEvent(events.ROOM_MSG_ACTION_REPORT);
|
||||
try {
|
||||
await Services.reportMessage(message.id);
|
||||
|
@ -335,14 +340,14 @@ const MessageActions = React.memo(
|
|||
}
|
||||
};
|
||||
|
||||
const handleDelete = (message: TAnyMessageModel) => {
|
||||
const handleDelete = (message: TAnyMessage) => {
|
||||
showConfirmationAlert({
|
||||
message: I18n.t('You_will_not_be_able_to_recover_this_message'),
|
||||
confirmationText: I18n.t('Delete'),
|
||||
onPress: async () => {
|
||||
try {
|
||||
logEvent(events.ROOM_MSG_ACTION_DELETE);
|
||||
await Services.deleteMessage(message.id, message.subscription ? message.subscription.id : '');
|
||||
await Services.deleteMessage(message.id, message.rid);
|
||||
} catch (e) {
|
||||
logEvent(events.ROOM_MSG_ACTION_DELETE_F);
|
||||
log(e);
|
||||
|
@ -351,7 +356,7 @@ const MessageActions = React.memo(
|
|||
});
|
||||
};
|
||||
|
||||
const getOptions = (message: TAnyMessageModel) => {
|
||||
const getOptions = (message: TAnyMessage) => {
|
||||
const options: TActionSheetOptionsItem[] = [];
|
||||
const videoConfBlock = message.t === 'videoconf';
|
||||
|
||||
|
@ -487,7 +492,7 @@ const MessageActions = React.memo(
|
|||
return options;
|
||||
};
|
||||
|
||||
const showMessageActions = async (message: TAnyMessageModel) => {
|
||||
const showMessageActions = async (message: TAnyMessage) => {
|
||||
logEvent(events.ROOM_SHOW_MSG_ACTIONS);
|
||||
await getPermissions();
|
||||
showActionSheet({
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Alert, Keyboard, NativeModules, Text, View, BackHandler } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
// import { KeyboardTrackingView } from 'react-native-keyboard-tracking-view';
|
||||
import { KeyboardAccessoryView } from 'react-native-ui-lib/keyboard';
|
||||
import ImagePicker, { Image, ImageOrVideo, Options } from 'react-native-image-crop-picker';
|
||||
import { dequal } from 'dequal';
|
||||
|
@ -169,7 +170,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
|||
id: ''
|
||||
},
|
||||
sharing: false,
|
||||
iOSScrollBehavior: NativeModules.KeyboardTrackingViewTempManager?.KeyboardTrackingScrollBehaviorFixedOffset,
|
||||
iOSScrollBehavior: NativeModules.KeyboardTrackingViewTempManager?.KeyboardTrackingScrollBehaviorScrollToBottomInvertedOnly,
|
||||
isActionsEnabled: true,
|
||||
getCustomEmoji: () => {}
|
||||
};
|
||||
|
@ -1290,7 +1291,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
|||
render() {
|
||||
console.count(`${this.constructor.name}.render calls`);
|
||||
const { showEmojiKeyboard } = this.state;
|
||||
const { user, baseUrl, theme, iOSScrollBehavior } = this.props;
|
||||
const { user, baseUrl, theme, iOSScrollBehavior, tmid, rid } = this.props;
|
||||
return (
|
||||
<MessageboxContext.Provider
|
||||
value={{
|
||||
|
@ -1309,11 +1310,10 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
|||
kbInitialProps={{ theme }}
|
||||
onKeyboardResigned={this.onKeyboardResigned}
|
||||
onItemSelected={this.onKeyboardItemSelected}
|
||||
trackInteractive
|
||||
requiresSameParentToManageScrollView
|
||||
addBottomView
|
||||
bottomViewColor={themes[theme].messageboxBackground}
|
||||
iOSScrollBehavior={iOSScrollBehavior}
|
||||
scrollViewNativeID={tmid || rid}
|
||||
/>
|
||||
</MessageboxContext.Provider>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { forwardRef, useImperativeHandle } from 'react';
|
||||
import Model from '@nozbe/watermelondb/Model';
|
||||
|
||||
import { getMessageById } from '../lib/database/services/Message';
|
||||
import { getThreadMessageById } from '../lib/database/services/ThreadMessage';
|
||||
import database from '../lib/database';
|
||||
import protectedFunction from '../lib/methods/helpers/protectedFunction';
|
||||
import { useActionSheet } from './ActionSheet';
|
||||
|
@ -27,16 +29,16 @@ const MessageErrorActions = forwardRef<IMessageErrorActions, { tmid?: string }>(
|
|||
const msgCollection = db.get('messages');
|
||||
const threadCollection = db.get('threads');
|
||||
|
||||
// Delete the object (it can be Message or ThreadMessage instance)
|
||||
deleteBatch.push(message.prepareDestroyPermanently());
|
||||
const msg = await getMessageById(message.id);
|
||||
if (msg) {
|
||||
deleteBatch.push(msg.prepareDestroyPermanently());
|
||||
}
|
||||
|
||||
// If it's a thread, we find and delete the whole tree, if necessary
|
||||
if (tmid) {
|
||||
try {
|
||||
const msg = await msgCollection.find(message.id);
|
||||
const msg = await getThreadMessageById(message.id);
|
||||
if (msg) {
|
||||
deleteBatch.push(msg.prepareDestroyPermanently());
|
||||
} catch {
|
||||
// Do nothing: message not found
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import { dequal } from 'dequal';
|
||||
|
||||
import I18n from '../../i18n';
|
||||
import styles from './styles';
|
||||
|
@ -45,9 +44,7 @@ const formatMsg = ({ lastMessage, type, showLastMessage, username, useRealName }
|
|||
return `${prefix}${lastMessage.msg}`;
|
||||
};
|
||||
|
||||
const arePropsEqual = (oldProps: any, newProps: any) => dequal(oldProps, newProps);
|
||||
|
||||
const LastMessage = React.memo(({ lastMessage, type, showLastMessage, username, alert, useRealName }: ILastMessageProps) => {
|
||||
const LastMessage = ({ lastMessage, type, showLastMessage, username, alert, useRealName }: ILastMessageProps) => {
|
||||
const { colors } = useTheme();
|
||||
return (
|
||||
<MarkdownPreview
|
||||
|
@ -63,6 +60,6 @@ const LastMessage = React.memo(({ lastMessage, type, showLastMessage, username,
|
|||
testID='room-item-last-message'
|
||||
/>
|
||||
);
|
||||
}, arePropsEqual);
|
||||
};
|
||||
|
||||
export default LastMessage;
|
||||
|
|
|
@ -20,7 +20,6 @@ const RoomItem = ({
|
|||
prid,
|
||||
name,
|
||||
avatar,
|
||||
width,
|
||||
username,
|
||||
showLastMessage,
|
||||
status = 'offline',
|
||||
|
@ -52,12 +51,13 @@ const RoomItem = ({
|
|||
showAvatar,
|
||||
displayMode,
|
||||
sourceType,
|
||||
hideMentionStatus
|
||||
hideMentionStatus,
|
||||
touchableRef
|
||||
}: IRoomItemProps) => (
|
||||
<Touchable
|
||||
ref={touchableRef}
|
||||
onPress={onPress}
|
||||
onLongPress={onLongPress}
|
||||
width={width}
|
||||
favorite={favorite}
|
||||
toggleFav={toggleFav}
|
||||
isRead={isRead}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React, { forwardRef, useImperativeHandle } from 'react';
|
||||
import Animated, {
|
||||
useAnimatedGestureHandler,
|
||||
useSharedValue,
|
||||
|
@ -13,227 +13,242 @@ import {
|
|||
HandlerStateChangeEventPayload,
|
||||
PanGestureHandlerEventPayload
|
||||
} from 'react-native-gesture-handler';
|
||||
import { useWindowDimensions } from 'react-native';
|
||||
|
||||
import Touch from '../Touch';
|
||||
import { ACTION_WIDTH, LONG_SWIPE, SMALL_SWIPE } from './styles';
|
||||
import { LeftActions, RightActions } from './Actions';
|
||||
import { ITouchableProps } from './interfaces';
|
||||
import { ITouchableProps, ITouchableRef } from './interfaces';
|
||||
import { useTheme } from '../../theme';
|
||||
import I18n from '../../i18n';
|
||||
import { MAX_SIDEBAR_WIDTH } from '../../lib/constants';
|
||||
import { useAppSelector } from '../../lib/hooks';
|
||||
|
||||
const Touchable = ({
|
||||
children,
|
||||
type,
|
||||
onPress,
|
||||
onLongPress,
|
||||
testID,
|
||||
width,
|
||||
favorite,
|
||||
isRead,
|
||||
rid,
|
||||
toggleFav,
|
||||
toggleRead,
|
||||
hideChannel,
|
||||
isFocused,
|
||||
swipeEnabled,
|
||||
displayMode
|
||||
}: ITouchableProps): React.ReactElement => {
|
||||
const { colors } = useTheme();
|
||||
const Touchable = forwardRef<ITouchableRef, ITouchableProps>(
|
||||
(
|
||||
{
|
||||
children,
|
||||
type,
|
||||
onPress,
|
||||
onLongPress,
|
||||
testID,
|
||||
favorite,
|
||||
isRead,
|
||||
rid,
|
||||
toggleFav,
|
||||
toggleRead,
|
||||
hideChannel,
|
||||
isFocused,
|
||||
swipeEnabled,
|
||||
displayMode
|
||||
},
|
||||
ref
|
||||
): React.ReactElement => {
|
||||
const { colors } = useTheme();
|
||||
const { width: deviceWidth } = useWindowDimensions();
|
||||
const isMasterDetail = useAppSelector(state => state.app.isMasterDetail);
|
||||
const width = isMasterDetail ? MAX_SIDEBAR_WIDTH : deviceWidth;
|
||||
|
||||
const rowOffSet = useSharedValue(0);
|
||||
const transX = useSharedValue(0);
|
||||
const rowState = useSharedValue(0); // 0: closed, 1: right opened, -1: left opened
|
||||
let _value = 0;
|
||||
const rowOffSet = useSharedValue(0);
|
||||
const transX = useSharedValue(0);
|
||||
const rowState = useSharedValue(0); // 0: closed, 1: right opened, -1: left opened
|
||||
let _value = 0;
|
||||
|
||||
const close = () => {
|
||||
rowState.value = 0;
|
||||
transX.value = withSpring(0, { overshootClamping: true });
|
||||
rowOffSet.value = 0;
|
||||
};
|
||||
const close = () => {
|
||||
console.log(`${rid} close`);
|
||||
rowState.value = 0;
|
||||
transX.value = withSpring(0, { overshootClamping: true });
|
||||
rowOffSet.value = 0;
|
||||
};
|
||||
|
||||
const handleToggleFav = () => {
|
||||
if (toggleFav) {
|
||||
toggleFav(rid, favorite);
|
||||
}
|
||||
close();
|
||||
};
|
||||
useImperativeHandle(ref, () => ({
|
||||
close
|
||||
}));
|
||||
|
||||
const handleToggleRead = () => {
|
||||
if (toggleRead) {
|
||||
toggleRead(rid, isRead);
|
||||
}
|
||||
};
|
||||
|
||||
const handleHideChannel = () => {
|
||||
if (hideChannel) {
|
||||
hideChannel(rid, type);
|
||||
}
|
||||
};
|
||||
|
||||
const onToggleReadPress = () => {
|
||||
handleToggleRead();
|
||||
close();
|
||||
};
|
||||
|
||||
const onHidePress = () => {
|
||||
handleHideChannel();
|
||||
close();
|
||||
};
|
||||
|
||||
const handlePress = () => {
|
||||
if (rowState.value !== 0) {
|
||||
const handleToggleFav = () => {
|
||||
if (toggleFav) {
|
||||
toggleFav(rid, favorite);
|
||||
}
|
||||
close();
|
||||
return;
|
||||
}
|
||||
if (onPress) {
|
||||
onPress();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const handleLongPress = () => {
|
||||
if (rowState.value !== 0) {
|
||||
const handleToggleRead = () => {
|
||||
if (toggleRead) {
|
||||
toggleRead(rid, isRead);
|
||||
}
|
||||
};
|
||||
|
||||
const handleHideChannel = () => {
|
||||
if (hideChannel) {
|
||||
hideChannel(rid, type);
|
||||
}
|
||||
};
|
||||
|
||||
const onToggleReadPress = () => {
|
||||
handleToggleRead();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if (onLongPress) {
|
||||
onLongPress();
|
||||
}
|
||||
};
|
||||
const onHidePress = () => {
|
||||
handleHideChannel();
|
||||
close();
|
||||
};
|
||||
|
||||
const onLongPressHandlerStateChange = ({ nativeEvent }: { nativeEvent: HandlerStateChangeEventPayload }) => {
|
||||
if (nativeEvent.state === State.ACTIVE) {
|
||||
handleLongPress();
|
||||
}
|
||||
};
|
||||
const handlePress = () => {
|
||||
if (rowState.value !== 0) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
if (onPress) {
|
||||
onPress();
|
||||
}
|
||||
};
|
||||
|
||||
const handleRelease = (event: PanGestureHandlerEventPayload) => {
|
||||
const { translationX } = event;
|
||||
_value += translationX;
|
||||
let toValue = 0;
|
||||
if (rowState.value === 0) {
|
||||
// if no option is opened
|
||||
if (translationX > 0 && translationX < LONG_SWIPE) {
|
||||
if (I18n.isRTL) {
|
||||
const handleLongPress = () => {
|
||||
if (rowState.value !== 0) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (onLongPress) {
|
||||
onLongPress();
|
||||
}
|
||||
};
|
||||
|
||||
const onLongPressHandlerStateChange = ({ nativeEvent }: { nativeEvent: HandlerStateChangeEventPayload }) => {
|
||||
if (nativeEvent.state === State.ACTIVE) {
|
||||
handleLongPress();
|
||||
}
|
||||
};
|
||||
|
||||
const handleRelease = (event: PanGestureHandlerEventPayload) => {
|
||||
const { translationX } = event;
|
||||
_value += translationX;
|
||||
let toValue = 0;
|
||||
if (rowState.value === 0) {
|
||||
// if no option is opened
|
||||
if (translationX > 0 && translationX < LONG_SWIPE) {
|
||||
if (I18n.isRTL) {
|
||||
toValue = 2 * ACTION_WIDTH;
|
||||
} else {
|
||||
toValue = ACTION_WIDTH;
|
||||
}
|
||||
rowState.value = -1;
|
||||
} else if (translationX >= LONG_SWIPE) {
|
||||
toValue = 0;
|
||||
if (I18n.isRTL) {
|
||||
handleHideChannel();
|
||||
} else {
|
||||
handleToggleRead();
|
||||
}
|
||||
} else if (translationX < 0 && translationX > -LONG_SWIPE) {
|
||||
// open trailing option if he swipe left
|
||||
if (I18n.isRTL) {
|
||||
toValue = -ACTION_WIDTH;
|
||||
} else {
|
||||
toValue = -2 * ACTION_WIDTH;
|
||||
}
|
||||
rowState.value = 1;
|
||||
} else if (translationX <= -LONG_SWIPE) {
|
||||
toValue = 0;
|
||||
rowState.value = 1;
|
||||
if (I18n.isRTL) {
|
||||
handleToggleRead();
|
||||
} else {
|
||||
handleHideChannel();
|
||||
}
|
||||
} else {
|
||||
toValue = 0;
|
||||
}
|
||||
} else if (rowState.value === -1) {
|
||||
// if left option is opened
|
||||
if (_value < SMALL_SWIPE) {
|
||||
toValue = 0;
|
||||
rowState.value = 0;
|
||||
} else if (_value > LONG_SWIPE) {
|
||||
toValue = 0;
|
||||
rowState.value = 0;
|
||||
if (I18n.isRTL) {
|
||||
handleHideChannel();
|
||||
} else {
|
||||
handleToggleRead();
|
||||
}
|
||||
} else if (I18n.isRTL) {
|
||||
toValue = 2 * ACTION_WIDTH;
|
||||
} else {
|
||||
toValue = ACTION_WIDTH;
|
||||
}
|
||||
rowState.value = -1;
|
||||
} else if (translationX >= LONG_SWIPE) {
|
||||
toValue = 0;
|
||||
if (I18n.isRTL) {
|
||||
handleHideChannel();
|
||||
} else {
|
||||
handleToggleRead();
|
||||
}
|
||||
} else if (translationX < 0 && translationX > -LONG_SWIPE) {
|
||||
// open trailing option if he swipe left
|
||||
if (I18n.isRTL) {
|
||||
} else if (rowState.value === 1) {
|
||||
// if right option is opened
|
||||
if (_value > -2 * SMALL_SWIPE) {
|
||||
toValue = 0;
|
||||
rowState.value = 0;
|
||||
} else if (_value < -LONG_SWIPE) {
|
||||
if (I18n.isRTL) {
|
||||
handleToggleRead();
|
||||
} else {
|
||||
handleHideChannel();
|
||||
}
|
||||
} else if (I18n.isRTL) {
|
||||
toValue = -ACTION_WIDTH;
|
||||
} else {
|
||||
toValue = -2 * ACTION_WIDTH;
|
||||
}
|
||||
rowState.value = 1;
|
||||
} else if (translationX <= -LONG_SWIPE) {
|
||||
toValue = 0;
|
||||
rowState.value = 1;
|
||||
if (I18n.isRTL) {
|
||||
handleToggleRead();
|
||||
} else {
|
||||
handleHideChannel();
|
||||
}
|
||||
} else {
|
||||
toValue = 0;
|
||||
}
|
||||
} else if (rowState.value === -1) {
|
||||
// if left option is opened
|
||||
if (_value < SMALL_SWIPE) {
|
||||
toValue = 0;
|
||||
rowState.value = 0;
|
||||
} else if (_value > LONG_SWIPE) {
|
||||
toValue = 0;
|
||||
rowState.value = 0;
|
||||
if (I18n.isRTL) {
|
||||
handleHideChannel();
|
||||
} else {
|
||||
handleToggleRead();
|
||||
}
|
||||
} else if (I18n.isRTL) {
|
||||
toValue = 2 * ACTION_WIDTH;
|
||||
} else {
|
||||
toValue = ACTION_WIDTH;
|
||||
transX.value = withSpring(toValue, { overshootClamping: true });
|
||||
rowOffSet.value = toValue;
|
||||
_value = toValue;
|
||||
};
|
||||
|
||||
const onGestureEvent = useAnimatedGestureHandler({
|
||||
onActive: event => {
|
||||
transX.value = event.translationX + rowOffSet.value;
|
||||
if (transX.value > 2 * width) transX.value = 2 * width;
|
||||
},
|
||||
onEnd: event => {
|
||||
runOnJS(handleRelease)(event);
|
||||
}
|
||||
} else if (rowState.value === 1) {
|
||||
// if right option is opened
|
||||
if (_value > -2 * SMALL_SWIPE) {
|
||||
toValue = 0;
|
||||
rowState.value = 0;
|
||||
} else if (_value < -LONG_SWIPE) {
|
||||
if (I18n.isRTL) {
|
||||
handleToggleRead();
|
||||
} else {
|
||||
handleHideChannel();
|
||||
}
|
||||
} else if (I18n.isRTL) {
|
||||
toValue = -ACTION_WIDTH;
|
||||
} else {
|
||||
toValue = -2 * ACTION_WIDTH;
|
||||
}
|
||||
}
|
||||
transX.value = withSpring(toValue, { overshootClamping: true });
|
||||
rowOffSet.value = toValue;
|
||||
_value = toValue;
|
||||
};
|
||||
});
|
||||
|
||||
const onGestureEvent = useAnimatedGestureHandler({
|
||||
onActive: event => {
|
||||
transX.value = event.translationX + rowOffSet.value;
|
||||
if (transX.value > 2 * width) transX.value = 2 * width;
|
||||
},
|
||||
onEnd: event => {
|
||||
runOnJS(handleRelease)(event);
|
||||
}
|
||||
});
|
||||
const animatedStyles = useAnimatedStyle(() => ({ transform: [{ translateX: transX.value }] }));
|
||||
|
||||
const animatedStyles = useAnimatedStyle(() => ({ transform: [{ translateX: transX.value }] }));
|
||||
|
||||
return (
|
||||
<LongPressGestureHandler onHandlerStateChange={onLongPressHandlerStateChange}>
|
||||
<Animated.View>
|
||||
<PanGestureHandler activeOffsetX={[-20, 20]} onGestureEvent={onGestureEvent} enabled={swipeEnabled}>
|
||||
<Animated.View>
|
||||
<LeftActions
|
||||
transX={transX}
|
||||
isRead={isRead}
|
||||
width={width}
|
||||
onToggleReadPress={onToggleReadPress}
|
||||
displayMode={displayMode}
|
||||
/>
|
||||
<RightActions
|
||||
transX={transX}
|
||||
favorite={favorite}
|
||||
width={width}
|
||||
toggleFav={handleToggleFav}
|
||||
onHidePress={onHidePress}
|
||||
displayMode={displayMode}
|
||||
/>
|
||||
<Animated.View style={animatedStyles}>
|
||||
<Touch
|
||||
onPress={handlePress}
|
||||
testID={testID}
|
||||
style={{
|
||||
backgroundColor: isFocused ? colors.chatComponentBackground : colors.backgroundColor
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Touch>
|
||||
return (
|
||||
<LongPressGestureHandler onHandlerStateChange={onLongPressHandlerStateChange}>
|
||||
<Animated.View>
|
||||
<PanGestureHandler activeOffsetX={[-20, 20]} onGestureEvent={onGestureEvent} enabled={swipeEnabled}>
|
||||
<Animated.View>
|
||||
<LeftActions
|
||||
transX={transX}
|
||||
isRead={isRead}
|
||||
width={width}
|
||||
onToggleReadPress={onToggleReadPress}
|
||||
displayMode={displayMode}
|
||||
/>
|
||||
<RightActions
|
||||
transX={transX}
|
||||
favorite={favorite}
|
||||
width={width}
|
||||
toggleFav={handleToggleFav}
|
||||
onHidePress={onHidePress}
|
||||
displayMode={displayMode}
|
||||
/>
|
||||
<Animated.View style={animatedStyles}>
|
||||
<Touch
|
||||
onPress={handlePress}
|
||||
testID={testID}
|
||||
style={{
|
||||
backgroundColor: isFocused ? colors.chatComponentBackground : colors.backgroundColor
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Touch>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</PanGestureHandler>
|
||||
</Animated.View>
|
||||
</LongPressGestureHandler>
|
||||
);
|
||||
};
|
||||
</PanGestureHandler>
|
||||
</Animated.View>
|
||||
</LongPressGestureHandler>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default Touchable;
|
||||
|
|
|
@ -1,136 +1,127 @@
|
|||
import React, { useEffect, useReducer, useRef } from 'react';
|
||||
import { Subscription } from 'rxjs';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
|
||||
import I18n from '../../i18n';
|
||||
import { useAppSelector } from '../../lib/hooks';
|
||||
import { getUserPresence } from '../../lib/methods';
|
||||
import { isGroupChat } from '../../lib/methods/helpers';
|
||||
import { formatDate } from '../../lib/methods/helpers/room';
|
||||
import { IRoomItemContainerProps } from './interfaces';
|
||||
import { IRoomItemContainerProps, ITouchableRef } from './interfaces';
|
||||
import RoomItem from './RoomItem';
|
||||
import { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from './styles';
|
||||
|
||||
export { ROW_HEIGHT, ROW_HEIGHT_CONDENSED };
|
||||
|
||||
const attrs = ['width', 'isFocused', 'showLastMessage', 'autoJoin', 'showAvatar', 'displayMode'];
|
||||
const RoomItemContainer = ({
|
||||
item,
|
||||
id,
|
||||
onPress,
|
||||
onLongPress,
|
||||
toggleFav,
|
||||
toggleRead,
|
||||
hideChannel,
|
||||
isFocused,
|
||||
showLastMessage,
|
||||
username,
|
||||
useRealName,
|
||||
autoJoin,
|
||||
showAvatar,
|
||||
displayMode,
|
||||
getRoomTitle = () => 'title',
|
||||
getRoomAvatar = () => '',
|
||||
getIsRead = () => false,
|
||||
swipeEnabled = true
|
||||
}: IRoomItemContainerProps): React.ReactElement => {
|
||||
const name = getRoomTitle(item);
|
||||
const testID = `rooms-list-view-item-${name}`;
|
||||
const avatar = getRoomAvatar(item);
|
||||
const isRead = getIsRead(item);
|
||||
const date = item.roomUpdatedAt && formatDate(item.roomUpdatedAt);
|
||||
const alert = item.alert || item.tunread?.length;
|
||||
const connected = useAppSelector(state => state.meteor.connected);
|
||||
const userStatus = useAppSelector(state => state.activeUsers[id || '']?.status);
|
||||
const isDirect = !!(item.t === 'd' && id && !isGroupChat(item));
|
||||
const touchableRef = useRef<ITouchableRef>(null);
|
||||
|
||||
const RoomItemContainer = React.memo(
|
||||
({
|
||||
item,
|
||||
id,
|
||||
onPress,
|
||||
onLongPress,
|
||||
width,
|
||||
toggleFav,
|
||||
toggleRead,
|
||||
hideChannel,
|
||||
isFocused,
|
||||
showLastMessage,
|
||||
username,
|
||||
useRealName,
|
||||
autoJoin,
|
||||
showAvatar,
|
||||
displayMode,
|
||||
getRoomTitle = () => 'title',
|
||||
getRoomAvatar = () => '',
|
||||
getIsRead = () => false,
|
||||
swipeEnabled = true
|
||||
}: IRoomItemContainerProps) => {
|
||||
const name = getRoomTitle(item);
|
||||
const testID = `rooms-list-view-item-${name}`;
|
||||
const avatar = getRoomAvatar(item);
|
||||
const isRead = getIsRead(item);
|
||||
const date = item.roomUpdatedAt && formatDate(item.roomUpdatedAt);
|
||||
const alert = item.alert || item.tunread?.length;
|
||||
const connected = useAppSelector(state => state.meteor.connected);
|
||||
const userStatus = useAppSelector(state => state.activeUsers[id || '']?.status);
|
||||
const [_, forceUpdate] = useReducer(x => x + 1, 1);
|
||||
const roomSubscription = useRef<Subscription | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const init = () => {
|
||||
if (item?.observe) {
|
||||
const observable = item.observe();
|
||||
roomSubscription.current = observable?.subscribe?.(() => {
|
||||
if (_) forceUpdate();
|
||||
});
|
||||
}
|
||||
};
|
||||
init();
|
||||
|
||||
return () => roomSubscription.current?.unsubscribe();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const isDirect = !!(item.t === 'd' && id && !isGroupChat(item));
|
||||
if (connected && isDirect) {
|
||||
getUserPresence(id);
|
||||
}
|
||||
}, [connected]);
|
||||
|
||||
const handleOnPress = () => onPress(item);
|
||||
|
||||
const handleOnLongPress = () => onLongPress && onLongPress(item);
|
||||
|
||||
let accessibilityLabel = '';
|
||||
if (item.unread === 1) {
|
||||
accessibilityLabel = `, ${item.unread} ${I18n.t('alert')}`;
|
||||
} else if (item.unread > 1) {
|
||||
accessibilityLabel = `, ${item.unread} ${I18n.t('alerts')}`;
|
||||
// When app reconnects, we need to fetch the rendered user's presence
|
||||
useEffect(() => {
|
||||
if (connected && isDirect) {
|
||||
getUserPresence(id);
|
||||
}
|
||||
if (item.userMentions > 0) {
|
||||
accessibilityLabel = `, ${I18n.t('you_were_mentioned')}`;
|
||||
}
|
||||
if (date) {
|
||||
accessibilityLabel = `, ${I18n.t('last_message')} ${date}`;
|
||||
}, [connected]);
|
||||
|
||||
/**
|
||||
* The component can be recycled by FlashList.
|
||||
* When rid changes and there's no user's status, we need to fetch it
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!userStatus && isDirect) {
|
||||
getUserPresence(id);
|
||||
}
|
||||
|
||||
const status = item.t === 'l' ? item.visitor?.status || item.v?.status : userStatus;
|
||||
// TODO: Remove this when we have a better way to close the swipeable
|
||||
touchableRef?.current?.close();
|
||||
}, [item.rid]);
|
||||
|
||||
return (
|
||||
<RoomItem
|
||||
name={name}
|
||||
avatar={avatar}
|
||||
isGroupChat={isGroupChat(item)}
|
||||
isRead={isRead}
|
||||
onPress={handleOnPress}
|
||||
onLongPress={handleOnLongPress}
|
||||
date={date}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
width={width}
|
||||
favorite={item.f}
|
||||
rid={item.rid}
|
||||
toggleFav={toggleFav}
|
||||
toggleRead={toggleRead}
|
||||
hideChannel={hideChannel}
|
||||
testID={testID}
|
||||
type={item.t}
|
||||
isFocused={isFocused}
|
||||
prid={item.prid}
|
||||
status={status}
|
||||
hideUnreadStatus={item.hideUnreadStatus}
|
||||
hideMentionStatus={item.hideMentionStatus}
|
||||
alert={alert}
|
||||
lastMessage={item.lastMessage}
|
||||
showLastMessage={showLastMessage}
|
||||
username={username}
|
||||
useRealName={useRealName}
|
||||
unread={item.unread}
|
||||
userMentions={item.userMentions}
|
||||
groupMentions={item.groupMentions}
|
||||
tunread={item.tunread}
|
||||
tunreadUser={item.tunreadUser}
|
||||
tunreadGroup={item.tunreadGroup}
|
||||
swipeEnabled={swipeEnabled}
|
||||
teamMain={item.teamMain}
|
||||
autoJoin={autoJoin}
|
||||
showAvatar={showAvatar}
|
||||
displayMode={displayMode}
|
||||
sourceType={item.source}
|
||||
/>
|
||||
);
|
||||
},
|
||||
(props, nextProps) => attrs.every(key => props[key] === nextProps[key])
|
||||
);
|
||||
const handleOnPress = () => onPress(item);
|
||||
|
||||
const handleOnLongPress = () => onLongPress && onLongPress(item);
|
||||
|
||||
let accessibilityLabel = '';
|
||||
if (item.unread === 1) {
|
||||
accessibilityLabel = `, ${item.unread} ${I18n.t('alert')}`;
|
||||
} else if (item.unread > 1) {
|
||||
accessibilityLabel = `, ${item.unread} ${I18n.t('alerts')}`;
|
||||
}
|
||||
if (item.userMentions > 0) {
|
||||
accessibilityLabel = `, ${I18n.t('you_were_mentioned')}`;
|
||||
}
|
||||
if (date) {
|
||||
accessibilityLabel = `, ${I18n.t('last_message')} ${date}`;
|
||||
}
|
||||
|
||||
const status = item.t === 'l' ? item.visitor?.status || item.v?.status : userStatus;
|
||||
|
||||
return (
|
||||
<RoomItem
|
||||
touchableRef={touchableRef}
|
||||
name={name}
|
||||
avatar={avatar}
|
||||
isGroupChat={isGroupChat(item)}
|
||||
isRead={isRead}
|
||||
onPress={handleOnPress}
|
||||
onLongPress={handleOnLongPress}
|
||||
date={date}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
favorite={item.f}
|
||||
rid={item.rid}
|
||||
toggleFav={toggleFav}
|
||||
toggleRead={toggleRead}
|
||||
hideChannel={hideChannel}
|
||||
testID={testID}
|
||||
type={item.t}
|
||||
isFocused={isFocused}
|
||||
prid={item.prid}
|
||||
status={status}
|
||||
hideUnreadStatus={item.hideUnreadStatus}
|
||||
hideMentionStatus={item.hideMentionStatus}
|
||||
alert={alert}
|
||||
lastMessage={item.lastMessage}
|
||||
showLastMessage={showLastMessage}
|
||||
username={username}
|
||||
useRealName={useRealName}
|
||||
unread={item.unread}
|
||||
userMentions={item.userMentions}
|
||||
groupMentions={item.groupMentions}
|
||||
tunread={item.tunread}
|
||||
tunreadUser={item.tunreadUser}
|
||||
tunreadGroup={item.tunreadGroup}
|
||||
swipeEnabled={swipeEnabled}
|
||||
teamMain={item.teamMain}
|
||||
autoJoin={autoJoin}
|
||||
showAvatar={showAvatar}
|
||||
displayMode={displayMode}
|
||||
sourceType={item.source}
|
||||
/>
|
||||
);
|
||||
};
|
||||
export default RoomItemContainer;
|
||||
|
|
|
@ -78,7 +78,6 @@ interface IBaseRoomItem extends IRoomItemTouchables {
|
|||
showAvatar: boolean;
|
||||
swipeEnabled: boolean;
|
||||
autoJoin?: boolean;
|
||||
width: number;
|
||||
username?: string;
|
||||
}
|
||||
|
||||
|
@ -116,6 +115,7 @@ export interface IRoomItemProps extends IBaseRoomItem {
|
|||
size?: number;
|
||||
sourceType: IOmnichannelSource;
|
||||
hideMentionStatus?: boolean;
|
||||
touchableRef: React.RefObject<ITouchableRef>;
|
||||
}
|
||||
|
||||
export interface ILastMessageProps {
|
||||
|
@ -127,11 +127,14 @@ export interface ILastMessageProps {
|
|||
alert: boolean;
|
||||
}
|
||||
|
||||
export interface ITouchableRef {
|
||||
close: () => void;
|
||||
}
|
||||
|
||||
export interface ITouchableProps extends IRoomItemTouchables {
|
||||
children: JSX.Element;
|
||||
type: SubscriptionType;
|
||||
testID: string;
|
||||
width: number;
|
||||
favorite: boolean;
|
||||
isRead: boolean;
|
||||
rid: string;
|
||||
|
|
|
@ -68,7 +68,7 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
|
|||
if (file && file.image_url) {
|
||||
return (
|
||||
<Image
|
||||
key={file.image_url}
|
||||
key={index}
|
||||
file={file}
|
||||
showAttachment={showAttachment}
|
||||
getCustomEmoji={getCustomEmoji}
|
||||
|
@ -81,7 +81,7 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
|
|||
if (file && file.audio_url) {
|
||||
return (
|
||||
<Audio
|
||||
key={file.audio_url}
|
||||
key={index}
|
||||
file={file}
|
||||
getCustomEmoji={getCustomEmoji}
|
||||
isReply={isReply}
|
||||
|
@ -95,7 +95,7 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
|
|||
if (file.video_url) {
|
||||
return (
|
||||
<Video
|
||||
key={file.video_url}
|
||||
key={index}
|
||||
file={file}
|
||||
showAttachment={showAttachment}
|
||||
getCustomEmoji={getCustomEmoji}
|
||||
|
|
|
@ -90,8 +90,8 @@ const Fields = React.memo(
|
|||
|
||||
return (
|
||||
<>
|
||||
{attachment.fields.map(field => (
|
||||
<View key={field.title} style={[styles.fieldContainer, { width: field.short ? '50%' : '100%' }]}>
|
||||
{attachment.fields.map((field, index) => (
|
||||
<View key={index} style={[styles.fieldContainer, { width: field.short ? '50%' : '100%' }]}>
|
||||
<Text testID='collapsibleQuoteTouchableFieldTitle' style={[styles.fieldTitle, { color: themes[theme].bodyText }]}>
|
||||
{field.title}
|
||||
</Text>
|
||||
|
|
|
@ -10,7 +10,7 @@ const Emoji = React.memo(
|
|||
const parsedContent = content.replace(/^:|:$/g, '');
|
||||
const emoji = getCustomEmoji(parsedContent);
|
||||
if (emoji) {
|
||||
return <CustomEmoji key={content} style={customEmojiStyle} emoji={emoji} />;
|
||||
return <CustomEmoji style={customEmojiStyle} emoji={emoji} />;
|
||||
}
|
||||
return <Text style={standardEmojiStyle}>{shortnameToUnicode(content)}</Text>;
|
||||
},
|
||||
|
|
|
@ -53,7 +53,6 @@ const Reaction = React.memo(({ reaction, getCustomEmoji, theme }: IMessageReacti
|
|||
<Touchable
|
||||
onPress={() => onReactionPress(reaction.emoji)}
|
||||
onLongPress={onReactionLongPress}
|
||||
key={reaction.emoji}
|
||||
testID={`message-reaction-${reaction.emoji}`}
|
||||
style={[
|
||||
styles.reactionButton,
|
||||
|
@ -83,8 +82,8 @@ const Reactions = React.memo(({ reactions, getCustomEmoji }: IMessageReactions)
|
|||
}
|
||||
return (
|
||||
<View style={styles.reactionsContainer}>
|
||||
{reactions.map(reaction => (
|
||||
<Reaction key={reaction.emoji} reaction={reaction} getCustomEmoji={getCustomEmoji} theme={theme} />
|
||||
{reactions.map((reaction, index) => (
|
||||
<Reaction key={index} reaction={reaction} getCustomEmoji={getCustomEmoji} theme={theme} />
|
||||
))}
|
||||
<AddReaction theme={theme} />
|
||||
</View>
|
||||
|
|
|
@ -184,8 +184,8 @@ const Fields = React.memo(
|
|||
|
||||
return (
|
||||
<View style={styles.fieldsContainer}>
|
||||
{attachment.fields.map(field => (
|
||||
<View key={field.title} style={[styles.fieldContainer, { width: field.short ? '50%' : '100%' }]}>
|
||||
{attachment.fields.map((field, index) => (
|
||||
<View key={index} style={[styles.fieldContainer, { width: field.short ? '50%' : '100%' }]}>
|
||||
<Text style={[styles.fieldTitle, { color: themes[theme].bodyText }]}>{field.title}</Text>
|
||||
<Markdown msg={field?.value || ''} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
|
||||
</View>
|
||||
|
|
|
@ -141,7 +141,7 @@ const Urls = React.memo(
|
|||
return null;
|
||||
}
|
||||
|
||||
return urls.map((url: IUrl, index: number) => <Url url={url} key={url.url} index={index} theme={theme} />);
|
||||
return urls.map((url: IUrl, index: number) => <Url url={url} key={index} index={index} theme={theme} />);
|
||||
},
|
||||
(oldProps, newProps) => dequal(oldProps.urls, newProps.urls)
|
||||
);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Keyboard, ViewStyle } from 'react-native';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Keyboard } from 'react-native';
|
||||
|
||||
import Message from './Message';
|
||||
import MessageContext from './Context';
|
||||
|
@ -8,64 +7,11 @@ import { debounce } from '../../lib/methods/helpers';
|
|||
import { getMessageTranslation } from './utils';
|
||||
import { TSupportedThemes, withTheme } from '../../theme';
|
||||
import openLink from '../../lib/methods/helpers/openLink';
|
||||
import { IAttachment, TAnyMessageModel, TGetCustomEmoji } from '../../definitions';
|
||||
import { IRoomInfoParam } from '../../views/SearchMessagesView';
|
||||
import { IAttachment } from '../../definitions';
|
||||
import { E2E_MESSAGE_TYPE, E2E_STATUS, messagesStatus } from '../../lib/constants';
|
||||
import { IMessageContainerProps, TAnyMessageContainerState } from './interfaces';
|
||||
|
||||
interface IMessageContainerProps {
|
||||
item: TAnyMessageModel;
|
||||
user: {
|
||||
id: string;
|
||||
username: string;
|
||||
token: string;
|
||||
};
|
||||
msg?: string;
|
||||
rid: string;
|
||||
timeFormat?: string;
|
||||
style?: ViewStyle;
|
||||
archived?: boolean;
|
||||
broadcast?: boolean;
|
||||
previousItem?: TAnyMessageModel;
|
||||
baseUrl: string;
|
||||
Message_GroupingPeriod?: number;
|
||||
isReadReceiptEnabled?: boolean;
|
||||
isThreadRoom: boolean;
|
||||
isSystemMessage?: boolean;
|
||||
useRealName?: boolean;
|
||||
autoTranslateRoom?: boolean;
|
||||
autoTranslateLanguage?: string;
|
||||
status?: number;
|
||||
isIgnored?: boolean;
|
||||
highlighted?: boolean;
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
onLongPress?: (item: TAnyMessageModel) => void;
|
||||
onReactionPress?: (emoji: string, id: string) => void;
|
||||
onEncryptedPress?: () => void;
|
||||
onDiscussionPress?: (item: TAnyMessageModel) => void;
|
||||
onThreadPress?: (item: TAnyMessageModel) => void;
|
||||
errorActionsShow?: (item: TAnyMessageModel) => void;
|
||||
replyBroadcast?: (item: TAnyMessageModel) => void;
|
||||
reactionInit?: (item: TAnyMessageModel) => void;
|
||||
fetchThreadName?: (tmid: string, id: string) => Promise<string | undefined>;
|
||||
showAttachment: (file: IAttachment) => void;
|
||||
onReactionLongPress?: (item: TAnyMessageModel) => void;
|
||||
navToRoomInfo: (navParam: IRoomInfoParam) => void;
|
||||
callJitsi?: () => void;
|
||||
blockAction?: (params: { actionId: string; appId: string; value: string; blockId: string; rid: string; mid: string }) => void;
|
||||
onAnswerButtonPress?: (message: string, tmid?: string, tshow?: boolean) => void;
|
||||
threadBadgeColor?: string;
|
||||
toggleFollowThread?: (isFollowingThread: boolean, tmid?: string) => Promise<void>;
|
||||
jumpToMessage?: (link: string) => void;
|
||||
onPress?: () => void;
|
||||
theme: TSupportedThemes;
|
||||
closeEmojiAndAction?: (action?: Function, params?: any) => void;
|
||||
}
|
||||
|
||||
interface IMessageContainerState {
|
||||
isManualUnignored: boolean;
|
||||
}
|
||||
|
||||
class MessageContainer extends React.Component<IMessageContainerProps, IMessageContainerState> {
|
||||
class MessageContainer extends React.Component<IMessageContainerProps, TAnyMessageContainerState> {
|
||||
static defaultProps = {
|
||||
getCustomEmoji: () => null,
|
||||
onLongPress: () => {},
|
||||
|
@ -79,45 +25,6 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
|
|||
|
||||
state = { isManualUnignored: false };
|
||||
|
||||
private subscription?: Subscription;
|
||||
|
||||
componentDidMount() {
|
||||
const { item } = this.props;
|
||||
if (item && item.observe) {
|
||||
const observable = item.observe();
|
||||
this.subscription = observable.subscribe(() => {
|
||||
this.forceUpdate();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps: IMessageContainerProps, nextState: IMessageContainerState) {
|
||||
const { isManualUnignored } = this.state;
|
||||
const { threadBadgeColor, isIgnored, highlighted, previousItem } = this.props;
|
||||
if (nextProps.highlighted !== highlighted) {
|
||||
return true;
|
||||
}
|
||||
if (nextProps.threadBadgeColor !== threadBadgeColor) {
|
||||
return true;
|
||||
}
|
||||
if (nextProps.isIgnored !== isIgnored) {
|
||||
return true;
|
||||
}
|
||||
if (nextState.isManualUnignored !== isManualUnignored) {
|
||||
return true;
|
||||
}
|
||||
if (nextProps.previousItem?._id !== previousItem?._id) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.subscription && this.subscription.unsubscribe) {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
onPressAction = () => {
|
||||
const { closeEmojiAndAction } = this.props;
|
||||
|
||||
|
@ -227,11 +134,11 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
|
|||
try {
|
||||
if (
|
||||
previousItem &&
|
||||
// @ts-ignore TODO: IMessage vs IMessageFromServer non-sense
|
||||
// @ts-ignore TODO: TAnyMessage vs TAnyMessageFromServer non-sense
|
||||
previousItem.ts.toDateString() === item.ts.toDateString() &&
|
||||
previousItem.u.username === item.u.username &&
|
||||
!(previousItem.groupable === false || item.groupable === false || broadcast === true) &&
|
||||
// @ts-ignore TODO: IMessage vs IMessageFromServer non-sense
|
||||
// @ts-ignore TODO: TAnyMessage vs TAnyMessageFromServer non-sense
|
||||
item.ts - previousItem.ts < Message_GroupingPeriod * 1000 &&
|
||||
previousItem.tmid === item.tmid &&
|
||||
item.t !== 'rm' &&
|
||||
|
@ -407,8 +314,8 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
|
|||
threadBadgeColor,
|
||||
toggleFollowThread,
|
||||
replies
|
||||
}}>
|
||||
{/* @ts-ignore*/}
|
||||
}}
|
||||
>
|
||||
<Message
|
||||
id={id}
|
||||
msg={message}
|
||||
|
|
|
@ -1,11 +1,65 @@
|
|||
import { MarkdownAST } from '@rocket.chat/message-parser';
|
||||
import { StyleProp, TextStyle } from 'react-native';
|
||||
import { StyleProp, TextStyle, ViewStyle } from 'react-native';
|
||||
import { ImageStyle } from 'react-native-fast-image';
|
||||
|
||||
import { IUserChannel } from '../markdown/interfaces';
|
||||
import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
||||
import { IAttachment, IThread, IUrl, IUserMention, IUserMessage, MessageType, TAnyMessageModel } from '../../definitions';
|
||||
import { IAttachment, IThread, IUrl, IUserMention, IUserMessage, MessageType, TAnyMessage } from '../../definitions';
|
||||
import { IRoomInfoParam } from '../../views/SearchMessagesView';
|
||||
import { TSupportedThemes } from '../../theme';
|
||||
|
||||
export interface IMessageContainerProps {
|
||||
item: TAnyMessage;
|
||||
user: {
|
||||
id: string;
|
||||
username: string;
|
||||
token: string;
|
||||
};
|
||||
msg?: string;
|
||||
rid: string;
|
||||
timeFormat?: string;
|
||||
style?: ViewStyle;
|
||||
archived?: boolean;
|
||||
broadcast?: boolean;
|
||||
previousItem?: TAnyMessage;
|
||||
baseUrl: string;
|
||||
Message_GroupingPeriod?: number;
|
||||
isReadReceiptEnabled?: boolean;
|
||||
isThreadRoom: boolean;
|
||||
isSystemMessage?: boolean;
|
||||
useRealName?: boolean;
|
||||
autoTranslateRoom?: boolean;
|
||||
autoTranslateLanguage?: string;
|
||||
status?: number;
|
||||
isIgnored?: boolean;
|
||||
highlighted?: boolean;
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
onLongPress?: (item: TAnyMessage) => void;
|
||||
onReactionPress?: (emoji: string, id: string) => void;
|
||||
onEncryptedPress?: () => void;
|
||||
onDiscussionPress?: (item: TAnyMessage) => void;
|
||||
onThreadPress?: (item: TAnyMessage) => void;
|
||||
errorActionsShow?: (item: TAnyMessage) => void;
|
||||
replyBroadcast?: (item: TAnyMessage) => void;
|
||||
reactionInit?: (item: TAnyMessage) => void;
|
||||
fetchThreadName?: (tmid: string, id: string) => Promise<string | undefined>;
|
||||
showAttachment: (file: IAttachment) => void;
|
||||
onReactionLongPress?: (item: TAnyMessage) => void;
|
||||
navToRoomInfo: (navParam: IRoomInfoParam) => void;
|
||||
callJitsi?: () => void;
|
||||
blockAction?: (params: { actionId: string; appId: string; value: string; blockId: string; rid: string; mid: string }) => void;
|
||||
onAnswerButtonPress?: (message: string, tmid?: string, tshow?: boolean) => void;
|
||||
threadBadgeColor?: string;
|
||||
toggleFollowThread?: (isFollowingThread: boolean, tmid?: string) => Promise<void>;
|
||||
jumpToMessage?: (link: string) => void;
|
||||
onPress?: () => void;
|
||||
theme: TSupportedThemes;
|
||||
closeEmojiAndAction?: (action?: Function, params?: any) => void;
|
||||
}
|
||||
|
||||
export interface TAnyMessageContainerState {
|
||||
isManualUnignored: boolean;
|
||||
}
|
||||
|
||||
export interface IMessageAttachments {
|
||||
attachments?: IAttachment[];
|
||||
|
@ -44,7 +98,6 @@ export interface IMessageCallButton {
|
|||
}
|
||||
|
||||
export interface IMessageContent {
|
||||
_id: string;
|
||||
isTemp: boolean;
|
||||
isInfo: string | boolean;
|
||||
tmid?: string;
|
||||
|
@ -119,7 +172,6 @@ export interface IMessage extends IMessageRepliedThread, IMessageInner, IMessage
|
|||
hasError: boolean;
|
||||
style: any;
|
||||
// style: ViewStyle;
|
||||
onLongPress?: (item: TAnyMessageModel) => void;
|
||||
isReadReceiptEnabled?: boolean;
|
||||
unread?: boolean;
|
||||
isIgnored: boolean;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable complexity */
|
||||
import { MessageTypesValues, TMessageModel } from '../../definitions/IMessage';
|
||||
import { MessageTypesValues, TAnyMessage } from '../../definitions/IMessage';
|
||||
import I18n from '../../i18n';
|
||||
import { DISCUSSION } from './constants';
|
||||
|
||||
|
@ -183,7 +183,7 @@ export const getInfoMessage = ({ type, role, msg, author, comment }: TInfoMessag
|
|||
}
|
||||
};
|
||||
|
||||
export const getMessageTranslation = (message: TMessageModel, autoTranslateLanguage: string): string | null => {
|
||||
export const getMessageTranslation = (message: TAnyMessage, autoTranslateLanguage: string): string | null => {
|
||||
if (!autoTranslateLanguage) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -4,11 +4,18 @@ import { MarkdownAST } from '@rocket.chat/message-parser';
|
|||
import { MessageTypeLoad } from '../lib/constants';
|
||||
import { IAttachment } from './IAttachment';
|
||||
import { IReaction } from './IReaction';
|
||||
import { TThreadMessageModel } from './IThreadMessage';
|
||||
import { TThreadModel } from './IThread';
|
||||
import { IThreadMessage } from './IThreadMessage';
|
||||
import { IThread } from './IThread';
|
||||
import { IUrl, IUrlFromServer } from './IUrl';
|
||||
|
||||
export type MessageType = 'jitsi_call_started' | 'discussion-created' | 'e2e' | 'load_more' | 'rm' | 'uj' | MessageTypeLoad | MessageTypesValues;
|
||||
export type MessageType =
|
||||
| 'jitsi_call_started'
|
||||
| 'discussion-created'
|
||||
| 'e2e'
|
||||
| 'rm'
|
||||
| 'uj'
|
||||
| MessageTypeLoad
|
||||
| MessageTypesValues;
|
||||
|
||||
export interface IUserMessage {
|
||||
_id: string;
|
||||
|
@ -139,9 +146,12 @@ export interface IMessage extends IMessageFromServer {
|
|||
editedAt?: string | Date;
|
||||
}
|
||||
|
||||
export type TMessageModel = IMessage & Model;
|
||||
export type TMessageModel = IMessage &
|
||||
Model & {
|
||||
asPlain: () => IMessage;
|
||||
};
|
||||
|
||||
export type TAnyMessageModel = TMessageModel | TThreadModel | TThreadMessageModel;
|
||||
export type TAnyMessage = IMessage | IThread | IThreadMessage;
|
||||
export type TTypeMessages = IMessageFromServer | ILoadMoreMessage | IMessage;
|
||||
|
||||
// Read receipts to ReadReceiptView and chat.getMessageReadReceipts
|
||||
|
|
|
@ -96,7 +96,6 @@ export interface ISubscription {
|
|||
avatarETag?: string;
|
||||
teamId?: string;
|
||||
teamMain?: boolean;
|
||||
unsubscribe: () => Promise<any>;
|
||||
separator?: boolean;
|
||||
onHold?: boolean;
|
||||
source?: IOmnichannelSource;
|
||||
|
@ -108,7 +107,10 @@ export interface ISubscription {
|
|||
uploads: RelationModified<TUploadModel>;
|
||||
}
|
||||
|
||||
export type TSubscriptionModel = ISubscription & Model;
|
||||
export type TSubscriptionModel = ISubscription &
|
||||
Model & {
|
||||
asPlain: () => ISubscription;
|
||||
};
|
||||
export type TSubscription = TSubscriptionModel | ISubscription;
|
||||
|
||||
// https://github.com/RocketChat/Rocket.Chat/blob/a88a96fcadd925b678ff27ada37075e029f78b5e/definition/ISubscription.ts#L8
|
||||
|
|
|
@ -38,4 +38,7 @@ export interface IThread extends IMessage {
|
|||
draftMessage?: string;
|
||||
}
|
||||
|
||||
export type TThreadModel = IThread & Model;
|
||||
export type TThreadModel = IThread &
|
||||
Model & {
|
||||
asPlain: () => IThread;
|
||||
};
|
||||
|
|
|
@ -6,4 +6,7 @@ export interface IThreadMessage extends IMessage {
|
|||
tmsg?: string;
|
||||
}
|
||||
|
||||
export type TThreadMessageModel = IThreadMessage & Model;
|
||||
export type TThreadMessageModel = IThreadMessage &
|
||||
Model & {
|
||||
asPlain: () => IThreadMessage;
|
||||
};
|
||||
|
|
|
@ -85,4 +85,47 @@ export default class Message extends Model {
|
|||
@json('md', sanitizer) md;
|
||||
|
||||
@field('comment') comment;
|
||||
|
||||
asPlain() {
|
||||
return {
|
||||
id: this.id,
|
||||
rid: this.subscription.id,
|
||||
msg: this.msg,
|
||||
t: this.t,
|
||||
ts: this.ts,
|
||||
u: this.u,
|
||||
alias: this.alias,
|
||||
parseUrls: this.parseUrls,
|
||||
groupable: this.groupable,
|
||||
avatar: this.avatar,
|
||||
emoji: this.emoji,
|
||||
attachments: this.attachments,
|
||||
urls: this.urls,
|
||||
_updatedAt: this._updatedAt,
|
||||
status: this.status,
|
||||
pinned: this.pinned,
|
||||
starred: this.starred,
|
||||
editedBy: this.editedBy,
|
||||
reactions: this.reactions,
|
||||
role: this.role,
|
||||
drid: this.drid,
|
||||
dcount: this.dcount,
|
||||
dlm: this.dlm,
|
||||
tmid: this.tmid,
|
||||
tcount: this.tcount,
|
||||
tlm: this.tlm,
|
||||
replies: this.replies,
|
||||
mentions: this.mentions,
|
||||
channels: this.channels,
|
||||
unread: this.unread,
|
||||
autoTranslate: this.autoTranslate,
|
||||
translations: this.translations,
|
||||
tmsg: this.tmsg,
|
||||
blocks: this.blocks,
|
||||
e2e: this.e2e,
|
||||
tshow: this.tshow,
|
||||
md: this.md,
|
||||
comment: this.comment
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,4 +136,68 @@ export default class Subscription extends Model {
|
|||
@field('on_hold') onHold;
|
||||
|
||||
@json('source', sanitizer) source;
|
||||
|
||||
// TODO: if this is proven to be the best way to do it, we should use TS to map through the properties
|
||||
asPlain() {
|
||||
return {
|
||||
_id: this._id,
|
||||
f: this.f,
|
||||
t: this.t,
|
||||
ts: this.ts,
|
||||
ls: this.ls,
|
||||
name: this.name,
|
||||
fname: this.fname,
|
||||
rid: this.rid,
|
||||
open: this.open,
|
||||
alert: this.alert,
|
||||
unread: this.unread,
|
||||
userMentions: this.userMentions,
|
||||
groupMentions: this.groupMentions,
|
||||
roomUpdatedAt: this.roomUpdatedAt,
|
||||
ro: this.ro,
|
||||
lastOpen: this.lastOpen,
|
||||
description: this.description,
|
||||
announcement: this.announcement,
|
||||
bannerClosed: this.bannerClosed,
|
||||
topic: this.topic,
|
||||
blocked: this.blocked,
|
||||
blocker: this.blocker,
|
||||
reactWhenReadOnly: this.reactWhenReadOnly,
|
||||
archived: this.archived,
|
||||
joinCodeRequired: this.joinCodeRequired,
|
||||
notifications: this.notifications,
|
||||
broadcast: this.broadcast,
|
||||
prid: this.prid,
|
||||
draftMessage: this.draftMessage,
|
||||
lastThreadSync: this.lastThreadSync,
|
||||
jitsiTimeout: this.jitsiTimeout,
|
||||
autoTranslate: this.autoTranslate,
|
||||
autoTranslateLanguage: this.autoTranslateLanguage,
|
||||
hideUnreadStatus: this.hideUnreadStatus,
|
||||
hideMentionStatus: this.hideMentionStatus,
|
||||
departmentId: this.departmentId,
|
||||
E2EKey: this.E2EKey,
|
||||
encrypted: this.encrypted,
|
||||
e2eKeyId: this.e2eKeyId,
|
||||
avatarETag: this.avatarETag,
|
||||
teamId: this.teamId,
|
||||
teamMain: this.teamMain,
|
||||
onHold: this.onHold,
|
||||
roles: this.roles,
|
||||
tunread: this.tunread,
|
||||
tunreadUser: this.tunreadUser,
|
||||
tunreadGroup: this.tunreadGroup,
|
||||
muted: this.muted,
|
||||
ignored: this.ignored,
|
||||
lastMessage: this.lastMessage,
|
||||
sysMes: this.sysMes,
|
||||
uids: this.uids,
|
||||
usernames: this.usernames,
|
||||
visitor: this.visitor,
|
||||
servedBy: this.servedBy,
|
||||
livechatData: this.livechatData,
|
||||
tags: this.tags,
|
||||
source: this.source
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,4 +77,42 @@ export default class Thread extends Model {
|
|||
@field('e2e') e2e;
|
||||
|
||||
@field('draft_message') draftMessage;
|
||||
|
||||
asPlain() {
|
||||
return {
|
||||
id: this.id,
|
||||
msg: this.msg,
|
||||
t: this.t,
|
||||
ts: this.ts,
|
||||
u: this.u,
|
||||
alias: this.alias,
|
||||
parseUrls: this.parseUrls,
|
||||
groupable: this.groupable,
|
||||
avatar: this.avatar,
|
||||
emoji: this.emoji,
|
||||
attachments: this.attachments,
|
||||
urls: this.urls,
|
||||
_updatedAt: this._updatedAt,
|
||||
status: this.status,
|
||||
pinned: this.pinned,
|
||||
starred: this.starred,
|
||||
editedBy: this.editedBy,
|
||||
reactions: this.reactions,
|
||||
role: this.role,
|
||||
drid: this.drid,
|
||||
dcount: this.dcount,
|
||||
dlm: this.dlm,
|
||||
tmid: this.tmid,
|
||||
tcount: this.tcount,
|
||||
tlm: this.tlm,
|
||||
replies: this.replies,
|
||||
mentions: this.mentions,
|
||||
channels: this.channels,
|
||||
unread: this.unread,
|
||||
autoTranslate: this.autoTranslate,
|
||||
translations: this.translations,
|
||||
e2e: this.e2e,
|
||||
draftMessage: this.draftMessage
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,4 +77,42 @@ export default class ThreadMessage extends Model {
|
|||
@field('draft_message') draftMessage;
|
||||
|
||||
@field('e2e') e2e;
|
||||
|
||||
asPlain() {
|
||||
return {
|
||||
id: this.id,
|
||||
msg: this.msg,
|
||||
t: this.t,
|
||||
ts: this.ts,
|
||||
u: this.u,
|
||||
rid: this.rid,
|
||||
alias: this.alias,
|
||||
parseUrls: this.parseUrls,
|
||||
groupable: this.groupable,
|
||||
avatar: this.avatar,
|
||||
emoji: this.emoji,
|
||||
attachments: this.attachments,
|
||||
urls: this.urls,
|
||||
_updatedAt: this._updatedAt,
|
||||
status: this.status,
|
||||
pinned: this.pinned,
|
||||
starred: this.starred,
|
||||
editedBy: this.editedBy,
|
||||
reactions: this.reactions,
|
||||
role: this.role,
|
||||
drid: this.drid,
|
||||
dcount: this.dcount,
|
||||
dlm: this.dlm,
|
||||
tcount: this.tcount,
|
||||
tlm: this.tlm,
|
||||
replies: this.replies,
|
||||
mentions: this.mentions,
|
||||
channels: this.channels,
|
||||
unread: this.unread,
|
||||
autoTranslate: this.autoTranslate,
|
||||
translations: this.translations,
|
||||
draftMessage: this.draftMessage,
|
||||
e2e: this.e2e
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
import log from './helpers/log';
|
||||
import { TMessageModel, TSubscriptionModel } from '../../definitions';
|
||||
import { IMessage, TSubscriptionModel } from '../../definitions';
|
||||
import { store } from '../store/auxStore';
|
||||
import { isGroupChat } from './helpers';
|
||||
import { getRoom } from './getRoom';
|
||||
|
||||
type TRoomType = 'p' | 'c' | 'd';
|
||||
|
||||
export async function getPermalinkMessage(message: TMessageModel): Promise<string | null> {
|
||||
if (!message.subscription) return null;
|
||||
export async function getPermalinkMessage(message: IMessage): Promise<string | null> {
|
||||
let room: TSubscriptionModel;
|
||||
try {
|
||||
room = await getRoom(message.subscription.id);
|
||||
room = await getRoom(message.rid);
|
||||
} catch (e) {
|
||||
log(e);
|
||||
return null;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||
import { Model } from '@nozbe/watermelondb';
|
||||
|
||||
import { getMessageById } from '../database/services/Message';
|
||||
import database from '../database';
|
||||
import log from './helpers/log';
|
||||
import { random } from './helpers';
|
||||
|
@ -66,14 +67,17 @@ async function sendMessageCall(message: any) {
|
|||
export async function resendMessage(message: TMessageModel, tmid?: string) {
|
||||
const db = database.active;
|
||||
try {
|
||||
await db.write(async () => {
|
||||
await message.update(m => {
|
||||
m.status = messagesStatus.TEMP;
|
||||
const messageRecord = await getMessageById(message.id);
|
||||
if (messageRecord) {
|
||||
await db.write(async () => {
|
||||
await messageRecord.update(m => {
|
||||
m.status = messagesStatus.TEMP;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
const m = await Encryption.encryptMessage({
|
||||
_id: message.id,
|
||||
rid: message.subscription ? message.subscription.id : '',
|
||||
rid: message.rid,
|
||||
msg: message.msg,
|
||||
...(tmid && { tmid })
|
||||
} as IMessage);
|
||||
|
|
|
@ -14,7 +14,7 @@ import { addUserTyping, clearUserTyping, removeUserTyping } from '../../../actio
|
|||
import { debounce } from '../helpers';
|
||||
import { subscribeRoom, unsubscribeRoom } from '../../../actions/room';
|
||||
import { Encryption } from '../../encryption';
|
||||
import { IMessage, TMessageModel, TSubscriptionModel, TThreadMessageModel, TThreadModel } from '../../../definitions';
|
||||
import { IMessage, TMessageModel, TThreadMessageModel, TThreadModel } from '../../../definitions';
|
||||
import { IDDPMessage } from '../../../definitions/IDDPMessage';
|
||||
import sdk from '../../services/sdk';
|
||||
import { readMessages } from '../readMessages';
|
||||
|
@ -33,7 +33,7 @@ export default class RoomSubscription {
|
|||
private _threadsBatch: { [key: string]: TThreadModel };
|
||||
private threadMessagesBatch: {};
|
||||
private _threadMessagesBatch: { [key: string]: TThreadMessageModel };
|
||||
private promises?: Promise<TSubscriptionModel[]>;
|
||||
private promises?: Promise<any>;
|
||||
private connectedListener?: Promise<any>;
|
||||
private disconnectedListener?: Promise<any>;
|
||||
private notifyRoomListener?: Promise<any>;
|
||||
|
@ -79,7 +79,7 @@ export default class RoomSubscription {
|
|||
if (this.promises) {
|
||||
try {
|
||||
const subscriptions = (await this.promises) || [];
|
||||
subscriptions.forEach(sub => sub.unsubscribe().catch(() => console.log('unsubscribeRoom')));
|
||||
subscriptions.forEach((sub: any) => sub.unsubscribe().catch(() => console.log('unsubscribeRoom')));
|
||||
} catch (e) {
|
||||
// do nothing
|
||||
}
|
||||
|
|
|
@ -106,6 +106,7 @@ const Drawer = createDrawerNavigator<MasterDetailDrawerParamList>();
|
|||
const DrawerNavigator = React.memo(() => (
|
||||
<Drawer.Navigator
|
||||
screenOptions={{ drawerType: 'permanent', headerShown: false, drawerStyle: { ...drawerStyle } }}
|
||||
// @ts-ignore
|
||||
drawerContent={({ navigation, state }) => <RoomsListView navigation={navigation} state={state} />}
|
||||
>
|
||||
<Drawer.Screen name='ChatsStackNavigator' component={ChatsStackNavigator} />
|
||||
|
|
|
@ -5,7 +5,7 @@ import { IItem } from '../views/TeamChannelsView';
|
|||
import { IOptionsField } from '../views/NotificationPreferencesView/options';
|
||||
import { IServer } from '../definitions/IServer';
|
||||
import { IAttachment } from '../definitions/IAttachment';
|
||||
import { IMessage, TAnyMessageModel, TMessageModel } from '../definitions/IMessage';
|
||||
import { IMessage, TAnyMessage, TMessageModel } from '../definitions/IMessage';
|
||||
import { ISubscription, SubscriptionType, TSubscriptionModel } from '../definitions/ISubscription';
|
||||
import { ICannedResponse } from '../definitions/ICannedResponse';
|
||||
import { TDataSelect } from '../definitions/IDataSelect';
|
||||
|
@ -37,7 +37,7 @@ export type ChatsStackParamList = {
|
|||
roomUserId?: string | null;
|
||||
usedCannedResponse?: string;
|
||||
status?: string;
|
||||
replyInDM?: TAnyMessageModel;
|
||||
replyInDM?: TAnyMessage;
|
||||
}
|
||||
| undefined; // Navigates back to RoomView already on stack
|
||||
RoomActionsView: {
|
||||
|
|
|
@ -27,7 +27,7 @@ import {
|
|||
SubscriptionType,
|
||||
IAttachment,
|
||||
IMessage,
|
||||
TAnyMessageModel,
|
||||
TAnyMessage,
|
||||
IUrl,
|
||||
TGetCustomEmoji,
|
||||
ICustomEmoji
|
||||
|
@ -160,7 +160,7 @@ class MessagesView extends React.Component<IMessagesViewProps, IMessagesViewStat
|
|||
|
||||
defineMessagesViewContent = (name: string) => {
|
||||
const { user, baseUrl, theme, useRealName } = this.props;
|
||||
const renderItemCommonProps = (item: TAnyMessageModel) => ({
|
||||
const renderItemCommonProps = (item: TAnyMessage) => ({
|
||||
item,
|
||||
baseUrl,
|
||||
user,
|
||||
|
@ -219,7 +219,7 @@ class MessagesView extends React.Component<IMessagesViewProps, IMessagesViewStat
|
|||
},
|
||||
noDataMsg: I18n.t('No_mentioned_messages'),
|
||||
testID: 'mentioned-messages-view',
|
||||
renderItem: (item: TAnyMessageModel) => <Message {...renderItemCommonProps(item)} msg={item.msg} theme={theme} />
|
||||
renderItem: (item: TAnyMessage) => <Message {...renderItemCommonProps(item)} msg={item.msg} theme={theme} />
|
||||
},
|
||||
// Starred Messages Screen
|
||||
Starred: {
|
||||
|
@ -230,7 +230,7 @@ class MessagesView extends React.Component<IMessagesViewProps, IMessagesViewStat
|
|||
},
|
||||
noDataMsg: I18n.t('No_starred_messages'),
|
||||
testID: 'starred-messages-view',
|
||||
renderItem: (item: TAnyMessageModel) => (
|
||||
renderItem: (item: TAnyMessage) => (
|
||||
<Message {...renderItemCommonProps(item)} msg={item.msg} onLongPress={() => this.onLongPress(item)} theme={theme} />
|
||||
),
|
||||
action: (message: IMessage) => ({
|
||||
|
@ -249,7 +249,7 @@ class MessagesView extends React.Component<IMessagesViewProps, IMessagesViewStat
|
|||
},
|
||||
noDataMsg: I18n.t('No_pinned_messages'),
|
||||
testID: 'pinned-messages-view',
|
||||
renderItem: (item: TAnyMessageModel) => (
|
||||
renderItem: (item: TAnyMessage) => (
|
||||
<Message {...renderItemCommonProps(item)} msg={item.msg} onLongPress={() => this.onLongPress(item)} theme={theme} />
|
||||
),
|
||||
action: () => ({ title: I18n.t('Unpin'), icon: 'pin', onPress: this.handleActionPress }),
|
||||
|
|
|
@ -1,42 +1,32 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { FlatListProps, StyleSheet } from 'react-native';
|
||||
import { FlatList } from 'react-native-gesture-handler';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { FlashList, FlashListProps } from '@shopify/flash-list';
|
||||
import Animated from 'react-native-reanimated';
|
||||
|
||||
import { isIOS } from '../../../lib/methods/helpers';
|
||||
import scrollPersistTaps from '../../../lib/methods/helpers/scrollPersistTaps';
|
||||
|
||||
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
|
||||
const AnimatedFlashList = Animated.createAnimatedComponent(FlashList);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
list: {
|
||||
flex: 1
|
||||
},
|
||||
contentContainer: {
|
||||
paddingTop: 10
|
||||
paddingTop: 8
|
||||
}
|
||||
});
|
||||
|
||||
export type TListRef = React.RefObject<FlatList & { getNode: () => FlatList }>;
|
||||
|
||||
export interface IListProps extends FlatListProps<any> {
|
||||
listRef: TListRef;
|
||||
}
|
||||
export type IListProps = FlashListProps<any>;
|
||||
|
||||
// @ts-ignore
|
||||
const List = ({ listRef, ...props }: IListProps) => (
|
||||
<AnimatedFlatList
|
||||
<AnimatedFlashList
|
||||
testID='room-view-messages'
|
||||
ref={listRef}
|
||||
keyExtractor={(item: any) => item.id}
|
||||
// @ts-ignore
|
||||
contentContainerStyle={styles.contentContainer}
|
||||
style={styles.list}
|
||||
inverted={isIOS}
|
||||
removeClippedSubviews={isIOS}
|
||||
initialNumToRender={7}
|
||||
inverted
|
||||
estimatedItemSize={48}
|
||||
onEndReachedThreshold={0.5}
|
||||
maxToRenderPerBatch={5}
|
||||
windowSize={10}
|
||||
{...props}
|
||||
{...scrollPersistTaps}
|
||||
/>
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
import React from 'react';
|
||||
import { RefreshControl as RNRefreshControl, RefreshControlProps, StyleSheet } from 'react-native';
|
||||
|
||||
import { useTheme } from '../../../theme';
|
||||
import { isAndroid } from '../../../lib/methods/helpers';
|
||||
|
||||
const style = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1
|
||||
},
|
||||
inverted: {
|
||||
scaleY: -1
|
||||
}
|
||||
});
|
||||
|
||||
interface IRefreshControl extends RefreshControlProps {
|
||||
children: React.ReactElement;
|
||||
}
|
||||
|
||||
const RefreshControl = ({ children, onRefresh, refreshing }: IRefreshControl): React.ReactElement => {
|
||||
const { colors } = useTheme();
|
||||
if (isAndroid) {
|
||||
return (
|
||||
<RNRefreshControl
|
||||
onRefresh={onRefresh}
|
||||
refreshing={refreshing}
|
||||
tintColor={colors.auxiliaryText}
|
||||
style={[style.container, style.inverted]}
|
||||
>
|
||||
{children}
|
||||
</RNRefreshControl>
|
||||
);
|
||||
}
|
||||
|
||||
const refreshControl = <RNRefreshControl onRefresh={onRefresh} refreshing={refreshing} tintColor={colors.auxiliaryText} />;
|
||||
|
||||
return React.cloneElement(children, { refreshControl });
|
||||
};
|
||||
|
||||
export default RefreshControl;
|
|
@ -2,35 +2,28 @@ import { Q } from '@nozbe/watermelondb';
|
|||
import { dequal } from 'dequal';
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import { FlatListProps, View, ViewToken, StyleSheet, Platform } from 'react-native';
|
||||
import { FlatListProps, ViewToken, RefreshControl } from 'react-native';
|
||||
import { event, Value } from 'react-native-reanimated';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import ActivityIndicator from '../../../containers/ActivityIndicator';
|
||||
import { TAnyMessageModel, TMessageModel, TThreadMessageModel, TThreadModel } from '../../../definitions';
|
||||
import { MessageType, TAnyMessage, TMessageModel, TThreadMessageModel, TThreadModel } from '../../../definitions';
|
||||
import database from '../../../lib/database';
|
||||
import { compareServerVersion, debounce } from '../../../lib/methods/helpers';
|
||||
import { animateNextTransition } from '../../../lib/methods/helpers/layoutAnimation';
|
||||
import { animateNextTransition, compareServerVersion, debounce } from '../../../lib/methods/helpers';
|
||||
// import { animateNextTransition } from '../../../lib/methods/helpers/layoutAnimation';
|
||||
import log from '../../../lib/methods/helpers/log';
|
||||
import EmptyRoom from '../EmptyRoom';
|
||||
// @ts-ignore
|
||||
import List, { IListProps, TListRef } from './List';
|
||||
import NavBottomFAB from './NavBottomFAB';
|
||||
import { loadMissedMessages, loadThreadMessages } from '../../../lib/methods';
|
||||
import { Services } from '../../../lib/services';
|
||||
import RefreshControl from './RefreshControl';
|
||||
import { MESSAGE_TYPE_ANY_LOAD, themes } from '../../../lib/constants';
|
||||
import { TMessage } from '../definitions';
|
||||
import { ThemeContext } from '../../../theme';
|
||||
|
||||
const QUERY_SIZE = 50;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
inverted: {
|
||||
...Platform.select({
|
||||
android: {
|
||||
scaleY: -1
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
const onScroll = ({ y }: { y: Value<number> }) =>
|
||||
event(
|
||||
[
|
||||
|
@ -60,7 +53,7 @@ export interface IListContainerProps {
|
|||
}
|
||||
|
||||
interface IListContainerState {
|
||||
messages: TAnyMessageModel[];
|
||||
messages: TMessage[];
|
||||
refreshing: boolean;
|
||||
highlightedMessage: string | null;
|
||||
}
|
||||
|
@ -104,30 +97,6 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
|||
console.timeEnd(`${this.constructor.name} mount`);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps: IListContainerProps, nextState: IListContainerState) {
|
||||
const { refreshing, highlightedMessage } = this.state;
|
||||
const { hideSystemMessages, tunread, ignored, loading } = this.props;
|
||||
if (loading !== nextProps.loading) {
|
||||
return true;
|
||||
}
|
||||
if (highlightedMessage !== nextState.highlightedMessage) {
|
||||
return true;
|
||||
}
|
||||
if (refreshing !== nextState.refreshing) {
|
||||
return true;
|
||||
}
|
||||
if (!dequal(hideSystemMessages, nextProps.hideSystemMessages)) {
|
||||
return true;
|
||||
}
|
||||
if (!dequal(tunread, nextProps.tunread)) {
|
||||
return true;
|
||||
}
|
||||
if (!dequal(ignored, nextProps.ignored)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: IListContainerProps) {
|
||||
const { hideSystemMessages } = this.props;
|
||||
if (!dequal(hideSystemMessages, prevProps.hideSystemMessages)) {
|
||||
|
@ -141,7 +110,7 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
|||
this.unsubscribeFocus();
|
||||
}
|
||||
this.clearHighlightedMessageTimeout();
|
||||
console.countReset(`${this.constructor.name}.render calls`);
|
||||
console.countReset(`${this.constructor.name}.render: ${this.props.tmid || this.props.rid} calls`);
|
||||
}
|
||||
|
||||
// clears previous highlighted message timeout, if exists
|
||||
|
@ -154,7 +123,7 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
|||
|
||||
query = async () => {
|
||||
this.count += QUERY_SIZE;
|
||||
const { rid, tmid, showMessageInMainThread, serverVersion } = this.props;
|
||||
const { rid, tmid, showMessageInMainThread, serverVersion, listRef } = this.props;
|
||||
const db = database.active;
|
||||
|
||||
// handle servers with version < 3.0.0
|
||||
|
@ -163,6 +132,8 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
|||
hideSystemMessages = [];
|
||||
}
|
||||
|
||||
const columnsToObserve = ['_updated_at', 'status'];
|
||||
|
||||
if (tmid) {
|
||||
try {
|
||||
this.thread = await db.get('threads').find(tmid);
|
||||
|
@ -172,7 +143,7 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
|||
this.messagesObservable = db
|
||||
.get('thread_messages')
|
||||
.query(Q.where('rid', tmid), Q.experimentalSortBy('ts', Q.desc), Q.experimentalSkip(0), Q.experimentalTake(this.count))
|
||||
.observe();
|
||||
.observeWithColumns(columnsToObserve);
|
||||
} else if (rid) {
|
||||
const whereClause = [
|
||||
Q.where('rid', rid),
|
||||
|
@ -186,14 +157,22 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
|||
this.messagesObservable = db
|
||||
.get('messages')
|
||||
.query(...whereClause)
|
||||
.observe();
|
||||
.observeWithColumns(columnsToObserve);
|
||||
}
|
||||
|
||||
if (rid) {
|
||||
this.unsubscribeMessages();
|
||||
this.messagesSubscription = this.messagesObservable?.subscribe(messages => {
|
||||
let data = messages.map(m => {
|
||||
if ((MESSAGE_TYPE_ANY_LOAD as MessageType[]).includes(m.t)) {
|
||||
return m;
|
||||
}
|
||||
|
||||
return m.asPlain();
|
||||
});
|
||||
|
||||
if (tmid && this.thread) {
|
||||
messages = [...messages, this.thread];
|
||||
data = [...messages, this.thread.asPlain()];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,14 +180,21 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
|||
* hide system message is enabled
|
||||
*/
|
||||
if (compareServerVersion(serverVersion, 'lowerThan', '3.16.0') || hideSystemMessages.length) {
|
||||
messages = messages.filter(m => !m.t || !hideSystemMessages?.includes(m.t));
|
||||
data = messages.filter(m => !m.t || !hideSystemMessages?.includes(m.t));
|
||||
}
|
||||
|
||||
if (this.mounted) {
|
||||
this.setState({ messages }, () => this.update());
|
||||
const { messages: prevMessages } = this.state;
|
||||
this.setState({ messages: data });
|
||||
|
||||
// animates only for new messages
|
||||
if (this.animated && this.viewableItems?.[0]?.index === 0 && prevMessages[0]?.id !== data[0]?.id) {
|
||||
listRef.current?.prepareForLayoutAnimationRender();
|
||||
animateNextTransition();
|
||||
}
|
||||
} else {
|
||||
// @ts-ignore
|
||||
this.state.messages = messages;
|
||||
this.state.messages = data;
|
||||
}
|
||||
// TODO: move it away from here
|
||||
this.readThreads();
|
||||
|
@ -233,7 +219,13 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
|||
}
|
||||
}, 300);
|
||||
|
||||
onEndReached = () => this.query();
|
||||
onEndReached = () => {
|
||||
const { messages } = this.state;
|
||||
if (messages.length < this.count) {
|
||||
return;
|
||||
}
|
||||
this.query();
|
||||
};
|
||||
|
||||
onRefresh = () =>
|
||||
this.setState({ refreshing: true }, async () => {
|
||||
|
@ -255,20 +247,13 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
|||
this.setState({ refreshing: false });
|
||||
});
|
||||
|
||||
update = () => {
|
||||
if (this.animated) {
|
||||
animateNextTransition();
|
||||
}
|
||||
this.forceUpdate();
|
||||
};
|
||||
|
||||
unsubscribeMessages = () => {
|
||||
if (this.messagesSubscription && this.messagesSubscription.unsubscribe) {
|
||||
this.messagesSubscription.unsubscribe();
|
||||
}
|
||||
};
|
||||
|
||||
getLastMessage = (): TMessageModel | TThreadMessageModel | null => {
|
||||
getLastMessage = (): TAnyMessage | null => {
|
||||
const { messages } = this.state;
|
||||
if (messages.length > 0) {
|
||||
return messages[0];
|
||||
|
@ -353,7 +338,7 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
|||
renderItem: FlatListProps<any>['renderItem'] = ({ item, index }) => {
|
||||
const { messages, highlightedMessage } = this.state;
|
||||
const { renderRow } = this.props;
|
||||
return <View style={styles.inverted}>{renderRow(item, messages[index + 1], highlightedMessage)}</View>;
|
||||
return renderRow(item, messages[index + 1], highlightedMessage);
|
||||
};
|
||||
|
||||
onViewableItemsChanged: FlatListProps<any>['onViewableItemsChanged'] = ({ viewableItems }) => {
|
||||
|
@ -361,28 +346,37 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
|||
};
|
||||
|
||||
render() {
|
||||
console.count(`${this.constructor.name}.render calls`);
|
||||
const { rid, tmid, listRef } = this.props;
|
||||
const { messages, refreshing } = this.state;
|
||||
const { rid, tmid, listRef, loading } = this.props;
|
||||
const { messages, refreshing, highlightedMessage } = this.state;
|
||||
console.count(`${this.constructor.name}.render: ${tmid || rid} calls`);
|
||||
return (
|
||||
<>
|
||||
<EmptyRoom rid={rid} length={messages.length} mounted={this.mounted} />
|
||||
<RefreshControl refreshing={refreshing} onRefresh={this.onRefresh}>
|
||||
<List
|
||||
onScroll={this.onScroll}
|
||||
scrollEventThrottle={16}
|
||||
listRef={listRef}
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
onEndReached={this.onEndReached}
|
||||
ListFooterComponent={this.renderFooter}
|
||||
onScrollToIndexFailed={this.handleScrollToIndexFailed}
|
||||
onViewableItemsChanged={this.onViewableItemsChanged}
|
||||
viewabilityConfig={this.viewabilityConfig}
|
||||
/>
|
||||
</RefreshControl>
|
||||
<NavBottomFAB y={this.y} onPress={this.jumpToBottom} isThread={!!tmid} />
|
||||
</>
|
||||
// FIXME: added context directly so we don't have to touch on withTheme's ref
|
||||
<ThemeContext.Consumer>
|
||||
{({ theme }) => (
|
||||
<>
|
||||
<EmptyRoom rid={rid} length={messages.length} mounted={this.mounted} />
|
||||
<List
|
||||
onScroll={this.onScroll}
|
||||
scrollEventThrottle={16}
|
||||
listRef={listRef}
|
||||
data={messages}
|
||||
extraData={{ loading, highlightedMessage }}
|
||||
// @ts-ignore
|
||||
renderItem={this.renderItem}
|
||||
onEndReached={this.onEndReached}
|
||||
ListFooterComponent={this.renderFooter}
|
||||
onScrollToIndexFailed={this.handleScrollToIndexFailed}
|
||||
onViewableItemsChanged={this.onViewableItemsChanged}
|
||||
viewabilityConfig={this.viewabilityConfig}
|
||||
nativeID={tmid || rid}
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={refreshing} onRefresh={this.onRefresh} tintColor={themes[theme!].auxiliaryText} />
|
||||
}
|
||||
/>
|
||||
<NavBottomFAB y={this.y} onPress={this.jumpToBottom} isThread={!!tmid} />
|
||||
</>
|
||||
)}
|
||||
</ThemeContext.Consumer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import { TAnyMessage, TMessageModel } from '../../definitions';
|
||||
|
||||
export type TMessage = TAnyMessage | TMessageModel;
|
|
@ -69,7 +69,7 @@ import {
|
|||
ISubscription,
|
||||
IVisitor,
|
||||
SubscriptionType,
|
||||
TAnyMessageModel,
|
||||
TAnyMessage,
|
||||
TMessageModel,
|
||||
TSubscriptionModel,
|
||||
TThreadModel,
|
||||
|
@ -78,7 +78,7 @@ import {
|
|||
TGetCustomEmoji
|
||||
} from '../../definitions';
|
||||
import { E2E_MESSAGE_TYPE, E2E_STATUS, MESSAGE_TYPE_ANY_LOAD, MessageTypeLoad, themes } from '../../lib/constants';
|
||||
import { TListRef } from './List/List';
|
||||
// import { TListRef } from './List/List';
|
||||
import { ModalStackParamList } from '../../stacks/MasterDetailStack/types';
|
||||
import {
|
||||
callJitsi,
|
||||
|
@ -101,6 +101,7 @@ import {
|
|||
import { Services } from '../../lib/services';
|
||||
import { withActionSheet, IActionSheetProvider } from '../../containers/ActionSheet';
|
||||
import { goRoom, TGoRoomItem } from '../../lib/methods/helpers/goRoom';
|
||||
import { TMessage } from './definitions';
|
||||
|
||||
type TStateAttrsUpdate = keyof IRoomViewState;
|
||||
|
||||
|
@ -193,7 +194,7 @@ interface IRoomViewState {
|
|||
member: any;
|
||||
lastOpen: Date | null;
|
||||
reactionsModalVisible: boolean;
|
||||
selectedMessage?: TAnyMessageModel;
|
||||
selectedMessage?: TAnyMessage;
|
||||
canAutoTranslate: boolean;
|
||||
loading: boolean;
|
||||
editing: boolean;
|
||||
|
@ -204,6 +205,12 @@ interface IRoomViewState {
|
|||
roomUserId?: string | null;
|
||||
}
|
||||
|
||||
const fetchRoomUpdate = (room: any) =>
|
||||
roomAttrsUpdate?.reduce((ret: any, attr) => {
|
||||
ret[attr] = room[attr];
|
||||
return ret;
|
||||
}, {});
|
||||
|
||||
class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||
private rid?: string;
|
||||
private t?: string;
|
||||
|
@ -213,7 +220,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
private messagebox: React.RefObject<MessageBoxType>;
|
||||
private list: React.RefObject<ListContainerType>;
|
||||
private joinCode: React.RefObject<IJoinCode>;
|
||||
private flatList: TListRef;
|
||||
private flatList: any;
|
||||
private mounted: boolean;
|
||||
private offset = 0;
|
||||
private subObserveQuery?: Subscription;
|
||||
|
@ -225,7 +232,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
private retryFindTimeout?: ReturnType<typeof setTimeout>;
|
||||
private messageErrorActions?: IMessageErrorActions | null;
|
||||
private messageActions?: IMessageActions | null;
|
||||
private replyInDM?: TAnyMessageModel;
|
||||
private replyInDM?: TAnyMessage;
|
||||
// Type of InteractionManager.runAfterInteractions
|
||||
private didMountInteraction?: {
|
||||
then: (onfulfilled?: (() => any) | undefined, onrejected?: (() => any) | undefined) => Promise<any>;
|
||||
|
@ -264,7 +271,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
this.state = {
|
||||
joined: true,
|
||||
room,
|
||||
roomUpdate: {},
|
||||
roomUpdate: fetchRoomUpdate(room),
|
||||
member: {},
|
||||
lastOpen: null,
|
||||
reactionsModalVisible: false,
|
||||
|
@ -286,7 +293,8 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
|
||||
this.setHeader();
|
||||
|
||||
if ('id' in room) {
|
||||
// TODO: Since we won't be using observables directly anymore, should we remove this?
|
||||
if ('observe' in room) {
|
||||
// @ts-ignore TODO: type guard isn't helping here :(
|
||||
this.observeRoom(room);
|
||||
} else if (this.rid) {
|
||||
|
@ -407,7 +415,13 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
if (insets.left !== prevProps.insets.left || insets.right !== prevProps.insets.right) {
|
||||
this.setHeader();
|
||||
}
|
||||
this.setReadOnly();
|
||||
if (
|
||||
!dequal(prevState.roomUpdate.muted, roomUpdate.muted) ||
|
||||
prevState.roomUpdate.archived !== roomUpdate.archived ||
|
||||
prevState.roomUpdate.ro !== roomUpdate.ro
|
||||
) {
|
||||
this.setReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
updateOmnichannel = async () => {
|
||||
|
@ -473,7 +487,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
EventEmitter.removeListener(KEY_COMMAND, this.handleCommands);
|
||||
}
|
||||
EventEmitter.removeListener('ROOM_REMOVED', this.handleRoomRemoved);
|
||||
console.countReset(`${this.constructor.name}.render calls`);
|
||||
console.countReset(`${this.constructor.name}.render: ${this.tmid || room.rid} calls`);
|
||||
}
|
||||
|
||||
canForwardGuest = async () => {
|
||||
|
@ -765,10 +779,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
observeRoom = (room: TSubscriptionModel) => {
|
||||
const observable = room.observe();
|
||||
this.subSubscription = observable.subscribe(changes => {
|
||||
const roomUpdate = roomAttrsUpdate.reduce((ret: any, attr) => {
|
||||
ret[attr] = changes[attr];
|
||||
return ret;
|
||||
}, {});
|
||||
const roomUpdate = fetchRoomUpdate(changes);
|
||||
if (this.mounted) {
|
||||
this.internalSetState({ room: changes, roomUpdate, isOnHold: !!changes?.onHold });
|
||||
} else {
|
||||
|
@ -780,7 +791,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
});
|
||||
};
|
||||
|
||||
errorActionsShow = (message: TAnyMessageModel) => {
|
||||
errorActionsShow = (message: TAnyMessage) => {
|
||||
this.messagebox?.current?.closeEmojiAndAction(this.messageErrorActions?.showMessageErrorActions, message);
|
||||
};
|
||||
|
||||
|
@ -789,12 +800,11 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
this.messagebox?.current?.closeEmojiAndAction(showActionSheet, options);
|
||||
};
|
||||
|
||||
onEditInit = (message: TAnyMessageModel) => {
|
||||
onEditInit = (message: TAnyMessage) => {
|
||||
const newMessage = {
|
||||
id: message.id,
|
||||
subscription: {
|
||||
// @ts-ignore TODO: we can remove this after we merge a PR separating IMessage vs IMessageFromServer
|
||||
id: message.subscription.id
|
||||
id: message.rid
|
||||
},
|
||||
msg: message?.attachments?.[0]?.description || message.msg
|
||||
} as TMessageModel;
|
||||
|
@ -805,7 +815,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
this.setState({ selectedMessage: undefined, editing: false });
|
||||
};
|
||||
|
||||
onEditRequest = async (message: TAnyMessageModel) => {
|
||||
onEditRequest = async (message: TAnyMessage) => {
|
||||
this.setState({ selectedMessage: undefined, editing: false });
|
||||
try {
|
||||
await Services.editMessage(message);
|
||||
|
@ -814,7 +824,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
}
|
||||
};
|
||||
|
||||
onReplyInit = (message: TAnyMessageModel, mention: boolean) => {
|
||||
onReplyInit = (message: TAnyMessage, mention: boolean) => {
|
||||
// If there's a thread already, we redirect to it
|
||||
if (mention && !!message.tlm) {
|
||||
return this.onThreadPress(message);
|
||||
|
@ -844,7 +854,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
}, 100);
|
||||
};
|
||||
|
||||
onReactionInit = (message: TAnyMessageModel) => {
|
||||
onReactionInit = (message: TAnyMessage) => {
|
||||
this.messagebox?.current?.closeEmojiAndAction(() => {
|
||||
this.setState({ selectedMessage: message }, this.showReactionPicker);
|
||||
});
|
||||
|
@ -855,7 +865,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
this.setState({ selectedMessage: undefined }, hideActionSheet);
|
||||
};
|
||||
|
||||
onMessageLongPress = (message: TAnyMessageModel) => {
|
||||
onMessageLongPress = (message: TAnyMessage) => {
|
||||
// if it's a thread message on main room, we disable the long press
|
||||
if (message.tmid && !this.tmid) {
|
||||
return;
|
||||
|
@ -885,7 +895,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
}
|
||||
};
|
||||
|
||||
onReactionLongPress = (message: TAnyMessageModel) => {
|
||||
onReactionLongPress = (message: TAnyMessage) => {
|
||||
this.setState({ selectedMessage: message });
|
||||
const { showActionSheet } = this.props;
|
||||
const { selectedMessage } = this.state;
|
||||
|
@ -911,7 +921,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
};
|
||||
|
||||
onDiscussionPress = debounce(
|
||||
async (item: TAnyMessageModel) => {
|
||||
async (item: TAnyMessage) => {
|
||||
const { isMasterDetail } = this.props;
|
||||
if (!item.drid) return;
|
||||
const sub = await getRoomInfo(item.drid);
|
||||
|
@ -946,7 +956,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
});
|
||||
};
|
||||
|
||||
onThreadPress = debounce((item: TAnyMessageModel) => this.navToThread(item), 1000, true);
|
||||
onThreadPress = debounce((item: TAnyMessage) => this.navToThread(item), 1000, true);
|
||||
|
||||
shouldNavigateToRoom = (message: IMessage) => {
|
||||
if (message.tmid && message.tmid === this.tmid) {
|
||||
|
@ -1048,9 +1058,9 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
const { rid } = this.state.room;
|
||||
const { user } = this.props;
|
||||
sendMessage(rid, message, this.tmid || tmid, user, tshow).then(() => {
|
||||
if (this.list && this.list.current) {
|
||||
this.list.current?.update();
|
||||
}
|
||||
// if (this.list && this.list.current) {
|
||||
// this.list.current?.update();
|
||||
// }
|
||||
this.setLastOpen(null);
|
||||
Review.pushPositiveEvent();
|
||||
});
|
||||
|
@ -1155,7 +1165,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
}
|
||||
};
|
||||
|
||||
navToThread = async (item: TAnyMessageModel | { tmid: string }) => {
|
||||
navToThread = async (item: TAnyMessage | { tmid: string }) => {
|
||||
const { roomUserId } = this.state;
|
||||
const { navigation } = this.props;
|
||||
|
||||
|
@ -1204,7 +1214,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
}
|
||||
};
|
||||
|
||||
navToRoom = async (message: TAnyMessageModel) => {
|
||||
navToRoom = async (message: TAnyMessage) => {
|
||||
const { isMasterDetail } = this.props;
|
||||
const roomInfo = await getRoomInfo(message.rid);
|
||||
|
||||
|
@ -1293,7 +1303,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
}
|
||||
};
|
||||
|
||||
isIgnored = (message: TAnyMessageModel): boolean => {
|
||||
isIgnored = (message: TAnyMessage): boolean => {
|
||||
const { room } = this.state;
|
||||
if ('id' in room) {
|
||||
return room?.ignored?.includes?.(message?.u?._id) ?? false;
|
||||
|
@ -1301,7 +1311,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
return false;
|
||||
};
|
||||
|
||||
onLoadMoreMessages = (loaderItem: TAnyMessageModel) => {
|
||||
onLoadMoreMessages = (loaderItem: TMessageModel) => {
|
||||
const { room } = this.state;
|
||||
return RoomServices.getMoreMessages({
|
||||
rid: room.rid,
|
||||
|
@ -1316,7 +1326,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
Navigation.navigate('CannedResponsesListView', { rid: room.rid });
|
||||
};
|
||||
|
||||
renderItem = (item: TAnyMessageModel, previousItem: TAnyMessageModel, highlightedMessage?: string) => {
|
||||
renderItem = (item: TMessage, previousItem: TMessage, highlightedMessage?: string) => {
|
||||
const { room, lastOpen, canAutoTranslate } = this.state;
|
||||
const { user, Message_GroupingPeriod, Message_TimeFormat, useRealName, baseUrl, Message_Read_Receipt_Enabled, theme } =
|
||||
this.props;
|
||||
|
@ -1337,7 +1347,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
if (item.t && MESSAGE_TYPE_ANY_LOAD.includes(item.t as MessageTypeLoad)) {
|
||||
content = (
|
||||
<LoadMore
|
||||
load={() => this.onLoadMoreMessages(item)}
|
||||
load={() => this.onLoadMoreMessages(item as TMessageModel)}
|
||||
type={item.t}
|
||||
runOnRender={item.t === MessageTypeLoad.MORE && !previousItem}
|
||||
/>
|
||||
|
@ -1518,10 +1528,10 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
};
|
||||
|
||||
render() {
|
||||
console.count(`${this.constructor.name}.render calls`);
|
||||
const { room, loading } = this.state;
|
||||
const { user, baseUrl, theme, navigation, Hide_System_Messages, width, serverVersion } = this.props;
|
||||
const { rid, t } = room;
|
||||
console.count(`${this.constructor.name}.render: ${this.tmid || rid} calls`);
|
||||
let sysMes;
|
||||
let bannerClosed;
|
||||
let announcement;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { SubscriptionType, TAnyMessageModel } from '../../../definitions';
|
||||
import { SubscriptionType, TMessageModel } from '../../../definitions';
|
||||
import { loadNextMessages, loadMessagesForRoom } from '../../../lib/methods';
|
||||
import { MessageTypeLoad } from '../../../lib/constants';
|
||||
|
||||
|
@ -11,7 +11,7 @@ const getMoreMessages = ({
|
|||
rid: string;
|
||||
t: SubscriptionType;
|
||||
tmid?: string;
|
||||
loaderItem: TAnyMessageModel;
|
||||
loaderItem: TMessageModel;
|
||||
}): Promise<void> => {
|
||||
if ([MessageTypeLoad.MORE, MessageTypeLoad.PREVIOUS_CHUNK].includes(loaderItem.t as MessageTypeLoad)) {
|
||||
return loadMessagesForRoom({
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React from 'react';
|
||||
import { BackHandler, FlatList, Keyboard, NativeEventSubscription, RefreshControl, Text, View } from 'react-native';
|
||||
import { BackHandler, Keyboard, NativeEventSubscription, RefreshControl, Text, View } from 'react-native';
|
||||
import { batch, connect } from 'react-redux';
|
||||
import { dequal } from 'dequal';
|
||||
import Orientation from 'react-native-orientation-locker';
|
||||
import { Q } from '@nozbe/watermelondb';
|
||||
import { withSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||
import { Header } from '@react-navigation/elements';
|
||||
import { FlashList } from '@shopify/flash-list';
|
||||
import { CompositeNavigationProp, RouteProp } from '@react-navigation/native';
|
||||
import { Dispatch } from 'redux';
|
||||
|
||||
|
@ -39,7 +39,6 @@ import {
|
|||
import { getUserSelector } from '../../selectors/login';
|
||||
import { goRoom } from '../../lib/methods/helpers/goRoom';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import { withDimensions } from '../../dimensions';
|
||||
import { getInquiryQueueSelector } from '../../ee/omnichannel/selectors/inquiry';
|
||||
import { IApplicationState, ISubscription, IUser, RootEnum, SubscriptionType, TSubscriptionModel } from '../../definitions';
|
||||
import styles from './styles';
|
||||
|
@ -55,10 +54,9 @@ import {
|
|||
hasPermission,
|
||||
isRead,
|
||||
debounce,
|
||||
isIOS,
|
||||
isTablet
|
||||
} from '../../lib/methods/helpers';
|
||||
import { E2E_BANNER_TYPE, DisplayMode, SortBy, MAX_SIDEBAR_WIDTH, themes } from '../../lib/constants';
|
||||
import { E2E_BANNER_TYPE, DisplayMode, SortBy, themes } from '../../lib/constants';
|
||||
import { Services } from '../../lib/services';
|
||||
|
||||
type TNavigation = CompositeNavigationProp<
|
||||
|
@ -71,7 +69,6 @@ interface IRoomsListViewProps {
|
|||
route: RouteProp<ChatsStackParamList, 'RoomsListView'>;
|
||||
theme: TSupportedThemes;
|
||||
dispatch: Dispatch;
|
||||
[key: string]: IUser | string | boolean | ISubscription[] | number | object | TEncryptionBanner;
|
||||
user: IUser;
|
||||
server: string;
|
||||
searchText: string;
|
||||
|
@ -87,29 +84,22 @@ interface IRoomsListViewProps {
|
|||
useRealName: boolean;
|
||||
isMasterDetail: boolean;
|
||||
subscribedRoom: string;
|
||||
width: number;
|
||||
insets: {
|
||||
left: number;
|
||||
right: number;
|
||||
};
|
||||
queueSize: number;
|
||||
inquiryEnabled: boolean;
|
||||
encryptionBanner: TEncryptionBanner;
|
||||
encryptionBanner: string;
|
||||
showAvatar: boolean;
|
||||
displayMode: string;
|
||||
createTeamPermission: [];
|
||||
createDirectMessagePermission: [];
|
||||
createPublicChannelPermission: [];
|
||||
createPrivateChannelPermission: [];
|
||||
createDiscussionPermission: [];
|
||||
createTeamPermission?: string[];
|
||||
createDirectMessagePermission?: string[];
|
||||
createPublicChannelPermission?: string[];
|
||||
createPrivateChannelPermission?: string[];
|
||||
createDiscussionPermission?: string[];
|
||||
}
|
||||
|
||||
interface IRoomsListViewState {
|
||||
searching?: boolean;
|
||||
search?: IRoomItem[];
|
||||
loading?: boolean;
|
||||
chatsUpdate?: string[] | { rid: string; alert?: boolean }[];
|
||||
omnichannelsUpdate?: string[];
|
||||
chats?: IRoomItem[];
|
||||
item?: ISubscription;
|
||||
canCreateRoom?: boolean;
|
||||
|
@ -120,7 +110,6 @@ interface IRoomItem extends ISubscription {
|
|||
outside?: boolean;
|
||||
}
|
||||
|
||||
const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12;
|
||||
const CHATS_HEADER = 'Chats';
|
||||
const UNREAD_HEADER = 'Unread';
|
||||
const FAVORITES_HEADER = 'Favorites';
|
||||
|
@ -132,53 +121,22 @@ const OMNICHANNEL_HEADER_IN_PROGRESS = 'Open_Livechats';
|
|||
const OMNICHANNEL_HEADER_ON_HOLD = 'On_hold_Livechats';
|
||||
const QUERY_SIZE = 20;
|
||||
|
||||
const filterIsUnread = (s: TSubscriptionModel) => (s.unread > 0 || s.tunread?.length > 0 || s.alert) && !s.hideUnreadStatus;
|
||||
const filterIsFavorite = (s: TSubscriptionModel) => s.f;
|
||||
const filterIsOmnichannel = (s: TSubscriptionModel) => s.t === 'l';
|
||||
const filterIsTeam = (s: TSubscriptionModel) => s.teamMain;
|
||||
const filterIsDiscussion = (s: TSubscriptionModel) => s.prid;
|
||||
const filterIsUnread = (s: any) => (s.unread > 0 || s.tunread?.length > 0 || s.alert) && !s.hideUnreadStatus;
|
||||
const filterIsFavorite = (s: any) => s.f;
|
||||
const filterIsOmnichannel = (s: any) => s.t === 'l';
|
||||
const filterIsTeam = (s: any) => s.teamMain;
|
||||
const filterIsDiscussion = (s: any) => s.prid;
|
||||
|
||||
const shouldUpdateProps = [
|
||||
'searchText',
|
||||
'loadingServer',
|
||||
'showServerDropdown',
|
||||
'useRealName',
|
||||
'StoreLastMessage',
|
||||
'theme',
|
||||
'isMasterDetail',
|
||||
'refreshing',
|
||||
'queueSize',
|
||||
'inquiryEnabled',
|
||||
'encryptionBanner',
|
||||
'createTeamPermission',
|
||||
'createDirectMessagePermission',
|
||||
'createPublicChannelPermission',
|
||||
'createPrivateChannelPermission',
|
||||
'createDiscussionPermission'
|
||||
];
|
||||
|
||||
const sortPreferencesShouldUpdate = ['sortBy', 'groupByType', 'showFavorites', 'showUnread'];
|
||||
|
||||
const displayPropsShouldUpdate = ['showAvatar', 'displayMode'];
|
||||
|
||||
const getItemLayout = (data: ISubscription[] | null | undefined, index: number, height: number) => ({
|
||||
length: height,
|
||||
offset: height * index,
|
||||
index
|
||||
});
|
||||
const keyExtractor = (item: ISubscription) => item.rid;
|
||||
|
||||
class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewState> {
|
||||
private animated: boolean;
|
||||
private mounted: boolean;
|
||||
private count: number;
|
||||
private unsubscribeFocus?: () => void;
|
||||
private unsubscribeBlur?: () => void;
|
||||
private sortPreferencesChanged?: boolean;
|
||||
private shouldUpdate?: boolean;
|
||||
private backHandler?: NativeEventSubscription;
|
||||
private querySubscription?: Subscription;
|
||||
private scroll?: FlatList;
|
||||
private scroll?: any;
|
||||
private useRealName?: boolean;
|
||||
|
||||
constructor(props: IRoomsListViewProps) {
|
||||
|
@ -187,14 +145,11 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
console.time(`${this.constructor.name} mount`);
|
||||
|
||||
this.animated = false;
|
||||
this.mounted = false;
|
||||
this.count = 0;
|
||||
this.state = {
|
||||
searching: false,
|
||||
search: [],
|
||||
loading: true,
|
||||
chatsUpdate: [] as TSubscriptionModel[],
|
||||
omnichannelsUpdate: [],
|
||||
chats: [],
|
||||
item: {} as ISubscription,
|
||||
canCreateRoom: false
|
||||
|
@ -206,7 +161,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
componentDidMount() {
|
||||
const { navigation, dispatch } = this.props;
|
||||
this.handleHasPermission();
|
||||
this.mounted = true;
|
||||
|
||||
if (isTablet) {
|
||||
EventEmitter.addEventListener(KEY_COMMAND, this.handleCommands);
|
||||
|
@ -214,16 +168,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
this.unsubscribeFocus = navigation.addListener('focus', () => {
|
||||
Orientation.unlockAllOrientations();
|
||||
this.animated = true;
|
||||
// Check if there were changes with sort preference, then call getSubscription to remount the list
|
||||
if (this.sortPreferencesChanged) {
|
||||
this.getSubscriptions();
|
||||
this.sortPreferencesChanged = false;
|
||||
}
|
||||
// Check if there were changes while not focused (it's set on sCU)
|
||||
if (this.shouldUpdate) {
|
||||
this.forceUpdate();
|
||||
this.shouldUpdate = false;
|
||||
}
|
||||
this.backHandler = BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
|
||||
});
|
||||
this.unsubscribeBlur = navigation.addListener('blur', () => {
|
||||
|
@ -253,81 +197,61 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps: IRoomsListViewProps, nextState: IRoomsListViewState) {
|
||||
const { chatsUpdate, searching, item, canCreateRoom, omnichannelsUpdate } = this.state;
|
||||
// eslint-disable-next-line react/destructuring-assignment
|
||||
const propsUpdated = shouldUpdateProps.some(key => nextProps[key] !== this.props[key]);
|
||||
if (propsUpdated) {
|
||||
shouldComponentUpdate(nextProps: Readonly<IRoomsListViewProps>, nextState: Readonly<IRoomsListViewState>): boolean {
|
||||
const {
|
||||
createTeamPermission,
|
||||
createPublicChannelPermission,
|
||||
createPrivateChannelPermission,
|
||||
createDirectMessagePermission,
|
||||
createDiscussionPermission
|
||||
} = this.props;
|
||||
if (
|
||||
!dequal(createTeamPermission, nextProps.createTeamPermission) ||
|
||||
!dequal(createPublicChannelPermission, nextProps.createPublicChannelPermission) ||
|
||||
!dequal(createPrivateChannelPermission, nextProps.createPrivateChannelPermission) ||
|
||||
!dequal(createDirectMessagePermission, nextProps.createDirectMessagePermission) ||
|
||||
!dequal(createDiscussionPermission, nextProps.createDiscussionPermission)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if some display props are changed to force update when focus this view again
|
||||
// eslint-disable-next-line react/destructuring-assignment
|
||||
const displayUpdated = displayPropsShouldUpdate.some(key => nextProps[key] !== this.props[key]);
|
||||
if (displayUpdated) {
|
||||
this.shouldUpdate = true;
|
||||
}
|
||||
|
||||
// check if some sort preferences are changed to getSubscription() when focus this view again
|
||||
// eslint-disable-next-line react/destructuring-assignment
|
||||
const sortPreferencesUpdate = sortPreferencesShouldUpdate.some(key => nextProps[key] !== this.props[key]);
|
||||
if (sortPreferencesUpdate) {
|
||||
this.sortPreferencesChanged = true;
|
||||
}
|
||||
|
||||
// Compare changes only once
|
||||
const chatsNotEqual = !dequal(nextState.chatsUpdate, chatsUpdate);
|
||||
|
||||
// If they aren't equal, set to update if focused
|
||||
if (chatsNotEqual) {
|
||||
this.shouldUpdate = true;
|
||||
}
|
||||
|
||||
const omnichannelsNotEqual = !dequal(nextState.omnichannelsUpdate, omnichannelsUpdate);
|
||||
|
||||
if (omnichannelsNotEqual) {
|
||||
this.shouldUpdate = true;
|
||||
}
|
||||
|
||||
if (nextState.searching !== searching) {
|
||||
const { chats, search } = this.state;
|
||||
if (!dequal(chats, nextState.chats) || !dequal(search, nextState.search)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nextState.canCreateRoom !== canCreateRoom) {
|
||||
const {
|
||||
sortBy,
|
||||
groupByType,
|
||||
showFavorites,
|
||||
showUnread,
|
||||
subscribedRoom,
|
||||
isMasterDetail,
|
||||
showAvatar,
|
||||
displayMode,
|
||||
encryptionBanner,
|
||||
showServerDropdown
|
||||
} = this.props;
|
||||
if (
|
||||
sortBy !== nextProps.sortBy ||
|
||||
groupByType !== nextProps.groupByType ||
|
||||
showFavorites !== nextProps.showFavorites ||
|
||||
showUnread !== nextProps.showUnread ||
|
||||
showAvatar !== nextProps.showAvatar ||
|
||||
displayMode !== nextProps.displayMode ||
|
||||
(subscribedRoom !== nextProps.subscribedRoom && isMasterDetail) ||
|
||||
isMasterDetail !== nextProps.isMasterDetail ||
|
||||
encryptionBanner !== nextProps.encryptionBanner ||
|
||||
showServerDropdown !== nextProps.showServerDropdown
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nextState.item?.rid !== item?.rid) {
|
||||
const { searching, loading, canCreateRoom } = this.state;
|
||||
if (searching !== nextState.searching || loading !== nextState.loading || canCreateRoom !== nextState.canCreateRoom) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Abort if it's not focused
|
||||
if (!nextProps.navigation.isFocused()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { loading, search } = this.state;
|
||||
const { width, insets, subscribedRoom } = this.props;
|
||||
if (nextState.loading !== loading) {
|
||||
return true;
|
||||
}
|
||||
if (nextProps.width !== width) {
|
||||
return true;
|
||||
}
|
||||
if (!dequal(nextState.search, search)) {
|
||||
return true;
|
||||
}
|
||||
if (nextProps.subscribedRoom !== subscribedRoom) {
|
||||
return true;
|
||||
}
|
||||
if (!dequal(nextProps.insets, insets)) {
|
||||
return true;
|
||||
}
|
||||
// If it's focused and there are changes, update
|
||||
if (chatsNotEqual || omnichannelsNotEqual) {
|
||||
this.shouldUpdate = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -339,7 +263,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
showUnread,
|
||||
subscribedRoom,
|
||||
isMasterDetail,
|
||||
insets,
|
||||
createTeamPermission,
|
||||
createPublicChannelPermission,
|
||||
createPrivateChannelPermission,
|
||||
|
@ -366,9 +289,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
if (isMasterDetail && item?.rid !== subscribedRoom && subscribedRoom !== prevProps.subscribedRoom) {
|
||||
this.setState({ item: { rid: subscribedRoom } as ISubscription });
|
||||
}
|
||||
if (insets.left !== prevProps.insets.left || insets.right !== prevProps.insets.right) {
|
||||
this.setHeader();
|
||||
}
|
||||
|
||||
if (
|
||||
!dequal(createTeamPermission, prevProps.createTeamPermission) ||
|
||||
|
@ -481,13 +401,14 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
| (Pick<IRoomsListViewState, keyof IRoomsListViewState> | IRoomsListViewState | null),
|
||||
callback?: () => void
|
||||
) => {
|
||||
this.setState(state, callback);
|
||||
if (this.animated) {
|
||||
this.scroll?.prepareForLayoutAnimationRender();
|
||||
animateNextTransition();
|
||||
}
|
||||
this.setState(state, callback);
|
||||
};
|
||||
|
||||
addRoomsGroup = (data: TSubscriptionModel[], header: string, allData: TSubscriptionModel[]) => {
|
||||
addRoomsGroup = (data: ISubscription[], header: string, allData: ISubscription[]) => {
|
||||
if (data.length > 0) {
|
||||
if (header) {
|
||||
allData.push({ rid: header, separator: true } as TSubscriptionModel);
|
||||
|
@ -498,6 +419,7 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
};
|
||||
|
||||
getSubscriptions = async () => {
|
||||
console.log('🚀 ~ file: index.tsx ~ line 408 ~ RoomsListView ~ getSubscriptions');
|
||||
this.unsubscribeQuery();
|
||||
|
||||
const { sortBy, showUnread, showFavorites, groupByType, user } = this.props;
|
||||
|
@ -506,6 +428,7 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
let observable;
|
||||
|
||||
const defaultWhereClause = [Q.where('archived', false), Q.where('open', true)] as (Q.WhereDescription | Q.SortBy)[];
|
||||
const columnsToObserve = ['alert', 'f', 'on_hold', 'room_updated_at'];
|
||||
|
||||
if (sortBy === SortBy.Alphabetical) {
|
||||
defaultWhereClause.push(Q.experimentalSortBy(`${this.useRealName ? 'fname' : 'name'}`, Q.asc));
|
||||
|
@ -518,28 +441,26 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
observable = await db
|
||||
.get('subscriptions')
|
||||
.query(...defaultWhereClause)
|
||||
.observeWithColumns(['alert', 'on_hold']);
|
||||
.observeWithColumns(columnsToObserve);
|
||||
// When we're NOT grouping
|
||||
} else {
|
||||
this.count += QUERY_SIZE;
|
||||
observable = await db
|
||||
.get('subscriptions')
|
||||
.query(...defaultWhereClause, Q.experimentalSkip(0), Q.experimentalTake(this.count))
|
||||
.observeWithColumns(['on_hold']);
|
||||
.observeWithColumns(columnsToObserve);
|
||||
}
|
||||
|
||||
this.querySubscription = observable.subscribe(data => {
|
||||
let tempChats = [] as TSubscriptionModel[];
|
||||
let chats = data;
|
||||
let tempChats: ISubscription[] = [];
|
||||
let chats = data.map(item => item.asPlain());
|
||||
|
||||
let omnichannelsUpdate: string[] = [];
|
||||
const isOmnichannelAgent = user?.roles?.includes('livechat-agent');
|
||||
if (isOmnichannelAgent) {
|
||||
const omnichannel = chats.filter(s => filterIsOmnichannel(s));
|
||||
const omnichannelInProgress = omnichannel.filter(s => !s.onHold);
|
||||
const omnichannelOnHold = omnichannel.filter(s => s.onHold);
|
||||
chats = chats.filter(s => !filterIsOmnichannel(s));
|
||||
omnichannelsUpdate = omnichannelInProgress.map(s => s.rid);
|
||||
tempChats = this.addRoomsGroup(omnichannelInProgress, OMNICHANNEL_HEADER_IN_PROGRESS, tempChats);
|
||||
tempChats = this.addRoomsGroup(omnichannelOnHold, OMNICHANNEL_HEADER_ON_HOLD, tempChats);
|
||||
}
|
||||
|
@ -574,12 +495,8 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
tempChats = chats;
|
||||
}
|
||||
|
||||
const chatsUpdate = tempChats.map(item => item.rid);
|
||||
|
||||
this.internalSetState({
|
||||
chats: tempChats,
|
||||
chatsUpdate,
|
||||
omnichannelsUpdate,
|
||||
loading: false
|
||||
});
|
||||
});
|
||||
|
@ -893,13 +810,14 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
};
|
||||
|
||||
onEndReached = () => {
|
||||
// Run only when we're not grouping by anything
|
||||
if (!this.isGrouping) {
|
||||
this.getSubscriptions();
|
||||
const { searching } = this.state;
|
||||
if (searching) {
|
||||
return;
|
||||
}
|
||||
this.getSubscriptions();
|
||||
};
|
||||
|
||||
getScrollRef = (ref: FlatList) => (this.scroll = ref);
|
||||
getScrollRef = (ref: any) => (this.scroll = ref);
|
||||
|
||||
renderListHeader = () => {
|
||||
const { searching } = this.state;
|
||||
|
@ -911,7 +829,7 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
goQueue={this.goQueue}
|
||||
queueSize={queueSize}
|
||||
inquiryEnabled={inquiryEnabled}
|
||||
encryptionBanner={encryptionBanner}
|
||||
encryptionBanner={encryptionBanner as TEncryptionBanner}
|
||||
user={user}
|
||||
/>
|
||||
);
|
||||
|
@ -938,8 +856,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
user: { username },
|
||||
StoreLastMessage,
|
||||
useRealName,
|
||||
isMasterDetail,
|
||||
width,
|
||||
showAvatar,
|
||||
displayMode
|
||||
} = this.props;
|
||||
|
@ -953,7 +869,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
username={username}
|
||||
showLastMessage={StoreLastMessage}
|
||||
onPress={this.onPressItem}
|
||||
width={isMasterDetail ? MAX_SIDEBAR_WIDTH : width}
|
||||
toggleFav={this.toggleFav}
|
||||
toggleRead={this.toggleRead}
|
||||
hideChannel={this.hideChannel}
|
||||
|
@ -978,48 +893,42 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
);
|
||||
};
|
||||
|
||||
renderScroll = () => {
|
||||
const { loading, chats, search, searching } = this.state;
|
||||
const { theme, refreshing, displayMode } = this.props;
|
||||
|
||||
const height = displayMode === DisplayMode.Condensed ? ROW_HEIGHT_CONDENSED : ROW_HEIGHT;
|
||||
|
||||
if (loading) {
|
||||
return <ActivityIndicator />;
|
||||
}
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
ref={this.getScrollRef}
|
||||
data={searching ? search : chats}
|
||||
extraData={searching ? search : chats}
|
||||
keyExtractor={keyExtractor}
|
||||
style={[styles.list, { backgroundColor: themes[theme].backgroundColor }]}
|
||||
renderItem={this.renderItem}
|
||||
ListHeaderComponent={this.renderListHeader}
|
||||
getItemLayout={(data, index) => getItemLayout(data, index, height)}
|
||||
removeClippedSubviews={isIOS}
|
||||
keyboardShouldPersistTaps='always'
|
||||
initialNumToRender={INITIAL_NUM_TO_RENDER}
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={refreshing} onRefresh={this.onRefresh} tintColor={themes[theme].auxiliaryText} />
|
||||
}
|
||||
windowSize={9}
|
||||
onEndReached={this.onEndReached}
|
||||
onEndReachedThreshold={0.5}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
render = () => {
|
||||
console.count(`${this.constructor.name}.render calls`);
|
||||
const { showServerDropdown, theme, navigation } = this.props;
|
||||
const { showServerDropdown, theme, navigation, refreshing, displayMode, queueSize, inquiryEnabled, encryptionBanner } =
|
||||
this.props;
|
||||
const { loading, chats, search, searching } = this.state;
|
||||
|
||||
const height = displayMode === DisplayMode.Condensed ? ROW_HEIGHT_CONDENSED : ROW_HEIGHT;
|
||||
|
||||
return (
|
||||
<SafeAreaView testID='rooms-list-view' style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<StatusBar />
|
||||
{this.renderHeader()}
|
||||
{this.renderScroll()}
|
||||
{loading ? (
|
||||
<ActivityIndicator />
|
||||
) : (
|
||||
<View style={[styles.container, { backgroundColor: themes[theme].backgroundColor }]}>
|
||||
<FlashList
|
||||
ref={this.getScrollRef}
|
||||
data={searching ? search : chats}
|
||||
extraData={{ theme, queueSize, inquiryEnabled, encryptionBanner }}
|
||||
keyExtractor={keyExtractor}
|
||||
renderItem={this.renderItem}
|
||||
getItemType={item => (item.separator ? 'section' : 'item')}
|
||||
ListHeaderComponent={this.renderListHeader}
|
||||
estimatedItemSize={height}
|
||||
keyboardShouldPersistTaps='always'
|
||||
refreshControl={
|
||||
searching ? undefined : (
|
||||
<RefreshControl refreshing={refreshing} onRefresh={this.onRefresh} tintColor={themes[theme].auxiliaryText} />
|
||||
)
|
||||
}
|
||||
onEndReached={this.isGrouping ? undefined : this.onEndReached}
|
||||
onEndReachedThreshold={this.isGrouping ? undefined : 0.5}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
{/* TODO - this ts-ignore is here because the route props, on IBaseScreen*/}
|
||||
{/* @ts-ignore*/}
|
||||
{showServerDropdown ? <ServerDropdown navigation={navigation} theme={theme} /> : null}
|
||||
|
@ -1041,8 +950,8 @@ const mapStateToProps = (state: IApplicationState) => ({
|
|||
groupByType: state.sortPreferences.groupByType,
|
||||
showFavorites: state.sortPreferences.showFavorites,
|
||||
showUnread: state.sortPreferences.showUnread,
|
||||
useRealName: state.settings.UI_Use_Real_Name,
|
||||
StoreLastMessage: state.settings.Store_Last_Message,
|
||||
useRealName: state.settings.UI_Use_Real_Name as boolean,
|
||||
StoreLastMessage: state.settings.Store_Last_Message as boolean,
|
||||
subscribedRoom: state.room.subscribedRoom,
|
||||
queueSize: getInquiryQueueSelector(state).length,
|
||||
inquiryEnabled: state.inquiry.enabled,
|
||||
|
@ -1056,4 +965,4 @@ const mapStateToProps = (state: IApplicationState) => ({
|
|||
createDiscussionPermission: state.permissions['start-discussion']
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(withDimensions(withTheme(withSafeAreaInsets(RoomsListView))));
|
||||
export default connect(mapStateToProps)(withTheme(RoomsListView));
|
||||
|
|
|
@ -6,9 +6,6 @@ export default StyleSheet.create({
|
|||
container: {
|
||||
flex: 1
|
||||
},
|
||||
list: {
|
||||
width: '100%'
|
||||
},
|
||||
dropdownContainerHeader: {
|
||||
height: 41,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
|
|
|
@ -340,7 +340,9 @@ describe('E2E Encryption', () => {
|
|||
});
|
||||
|
||||
it('should add server and create new user', async () => {
|
||||
await sleep(5000);
|
||||
await waitFor(element(by.id('rooms-list-header-server-dropdown-button')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000);
|
||||
await element(by.id('rooms-list-header-server-dropdown-button')).tap();
|
||||
await waitFor(element(by.id('rooms-list-header-server-dropdown')))
|
||||
.toBeVisible()
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
import { expect } from 'detox';
|
||||
|
||||
import { navigateToRegister, platformTypes, TTextMatcher } from '../../helpers/app';
|
||||
import { navigateToRegister } from '../../helpers/app';
|
||||
import data from '../../data';
|
||||
|
||||
describe('Create user screen', () => {
|
||||
let alertButtonType: string;
|
||||
let textMatcher: TTextMatcher;
|
||||
before(async () => {
|
||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
||||
await navigateToRegister();
|
||||
});
|
||||
|
||||
|
@ -65,17 +62,17 @@ describe('Create user screen', () => {
|
|||
// await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||
// });
|
||||
|
||||
it('should submit username already taken and raise error', async () => {
|
||||
await element(by.id('register-view-name')).replaceText(data.registeringUser.username);
|
||||
await element(by.id('register-view-username')).replaceText(data.users.existing.username);
|
||||
await element(by.id('register-view-email')).replaceText(data.registeringUser.email);
|
||||
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
|
||||
await element(by.id('register-view-submit')).tap();
|
||||
await waitFor(element(by[textMatcher]('Username is already in use')).atIndex(0))
|
||||
.toExist()
|
||||
.withTimeout(10000);
|
||||
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||
});
|
||||
// it('should submit username already taken and raise error', async () => {
|
||||
// await element(by.id('register-view-name')).replaceText(data.registeringUser.username);
|
||||
// await element(by.id('register-view-username')).replaceText(data.users.existing.username);
|
||||
// await element(by.id('register-view-email')).replaceText(data.registeringUser.email);
|
||||
// await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
|
||||
// await element(by.id('register-view-submit')).tap();
|
||||
// await waitFor(element(by[textMatcher]('Username is already in use')).atIndex(0))
|
||||
// .toExist()
|
||||
// .withTimeout(10000);
|
||||
// await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||
// });
|
||||
|
||||
it('should register', async () => {
|
||||
await element(by.id('register-view-name')).replaceText(data.registeringUser.username);
|
||||
|
|
|
@ -187,12 +187,19 @@ describe('Room', () => {
|
|||
.toExist()
|
||||
.withTimeout(5000);
|
||||
await element(by[textMatcher]('Load Newer')).atIndex(0).tap();
|
||||
await waitFor(element(by[textMatcher]('204')))
|
||||
.toExist()
|
||||
.withTimeout(5000);
|
||||
await waitFor(element(by[textMatcher]('Load Newer')))
|
||||
.toExist()
|
||||
.withTimeout(5000);
|
||||
await element(by[textMatcher]('Load Newer')).atIndex(0).tap();
|
||||
await waitFor(element(by[textMatcher]('Load Newer')))
|
||||
.toNotExist()
|
||||
.withTimeout(5000);
|
||||
await expect(element(by[textMatcher]('Load More'))).toNotExist();
|
||||
await expect(element(by[textMatcher]('201'))).toExist();
|
||||
await expect(element(by[textMatcher]('202'))).toExist();
|
||||
await expect(element(by[textMatcher]('253'))).toExist();
|
||||
await expect(element(by[textMatcher]('252'))).toExist();
|
||||
await tapBack();
|
||||
});
|
||||
});
|
||||
|
|
5
index.js
5
index.js
|
@ -1,11 +1,16 @@
|
|||
import 'react-native-gesture-handler';
|
||||
import 'react-native-console-time-polyfill';
|
||||
import { AppRegistry } from 'react-native';
|
||||
import { connectToDevTools } from 'react-devtools-core';
|
||||
|
||||
import { name as appName, share as shareName } from './app.json';
|
||||
|
||||
if (__DEV__) {
|
||||
require('./app/ReactotronConfig');
|
||||
connectToDevTools({
|
||||
host: 'localhost',
|
||||
port: 8097
|
||||
});
|
||||
} else {
|
||||
console.log = () => {};
|
||||
console.time = () => {};
|
||||
|
|
|
@ -364,6 +364,11 @@ PODS:
|
|||
- React-Core
|
||||
- react-native-document-picker (8.1.2):
|
||||
- React-Core
|
||||
- react-native-flipper-performance-plugin (0.3.1):
|
||||
- React-Core
|
||||
- react-native-flipper-performance-plugin/FBDefines (= 0.3.1)
|
||||
- react-native-flipper-performance-plugin/FBDefines (0.3.1):
|
||||
- React-Core
|
||||
- react-native-jitsi-meet (3.6.0):
|
||||
- JitsiMeetSDK (= 3.6.0)
|
||||
- React
|
||||
|
@ -522,6 +527,8 @@ PODS:
|
|||
- RNFBApp
|
||||
- RNFileViewer (2.1.5):
|
||||
- React-Core
|
||||
- RNFlashList (1.2.2):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.4.2):
|
||||
- React-Core
|
||||
- RNImageCropPicker (0.36.3):
|
||||
|
@ -629,6 +636,7 @@ DEPENDENCIES:
|
|||
- "react-native-cameraroll (from `../node_modules/@react-native-community/cameraroll`)"
|
||||
- "react-native-cookies (from `../node_modules/@react-native-cookies/cookies`)"
|
||||
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
|
||||
- react-native-flipper-performance-plugin (from `../node_modules/react-native-flipper-performance-plugin`)
|
||||
- react-native-jitsi-meet (from `../node_modules/react-native-jitsi-meet`)
|
||||
- react-native-mmkv-storage (from `../node_modules/react-native-mmkv-storage`)
|
||||
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
|
||||
|
@ -668,6 +676,7 @@ DEPENDENCIES:
|
|||
- "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
|
||||
- "RNFBCrashlytics (from `../node_modules/@react-native-firebase/crashlytics`)"
|
||||
- RNFileViewer (from `../node_modules/react-native-file-viewer`)
|
||||
- "RNFlashList (from `../node_modules/@shopify/flash-list`)"
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||
- RNLocalize (from `../node_modules/react-native-localize`)
|
||||
|
@ -783,6 +792,8 @@ EXTERNAL SOURCES:
|
|||
:path: "../node_modules/@react-native-cookies/cookies"
|
||||
react-native-document-picker:
|
||||
:path: "../node_modules/react-native-document-picker"
|
||||
react-native-flipper-performance-plugin:
|
||||
:path: "../node_modules/react-native-flipper-performance-plugin"
|
||||
react-native-jitsi-meet:
|
||||
:path: "../node_modules/react-native-jitsi-meet"
|
||||
react-native-mmkv-storage:
|
||||
|
@ -861,6 +872,8 @@ EXTERNAL SOURCES:
|
|||
:path: "../node_modules/@react-native-firebase/crashlytics"
|
||||
RNFileViewer:
|
||||
:path: "../node_modules/react-native-file-viewer"
|
||||
RNFlashList:
|
||||
:path: "../node_modules/@shopify/flash-list"
|
||||
RNGestureHandler:
|
||||
:path: "../node_modules/react-native-gesture-handler"
|
||||
RNImageCropPicker:
|
||||
|
@ -949,6 +962,7 @@ SPEC CHECKSUMS:
|
|||
react-native-cameraroll: 2957f2bce63ae896a848fbe0d5352c1bd4d20866
|
||||
react-native-cookies: f54fcded06bb0cda05c11d86788020b43528a26c
|
||||
react-native-document-picker: f5ec1a712ca2a975c233117f044817bb8393cad4
|
||||
react-native-flipper-performance-plugin: 2b873b68da3e368afeaf29c9c7a8c2b0ff908c4f
|
||||
react-native-jitsi-meet: 3e3ac5d0445091154119f94342efd55c8b1124ce
|
||||
react-native-mmkv-storage: 8ba3c0216a6df283ece11205b442a3e435aec4e5
|
||||
react-native-netinfo: e849fc21ca2f4128a5726c801a82fc6f4a6db50d
|
||||
|
@ -988,6 +1002,7 @@ SPEC CHECKSUMS:
|
|||
RNFBApp: b1b5a80a676a07dea17e778bda7c1e8b69b2f5ec
|
||||
RNFBCrashlytics: 357955a1564721ca9001960e57b395c6a319f9be
|
||||
RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592
|
||||
RNFlashList: 13d14d9502661134ad3ba892f81d76bdcbd79755
|
||||
RNGestureHandler: 61628a2c859172551aa2100d3e73d1e57878392f
|
||||
RNImageCropPicker: 97289cd94fb01ab79db4e5c92938be4d0d63415d
|
||||
RNLocalize: 82a569022724d35461e2dc5b5d015a13c3ca995b
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
0C6E2DE448364EA896869ADF /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B37C79D9BD0742CE936B6982 /* libc++.tbd */; };
|
||||
0DAF353368B2DE2714B6DCE8 /* libPods-defaults-Rocket.Chat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F1EEB258E879574E6F9EADA /* libPods-defaults-Rocket.Chat.a */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
1E01C81C2511208400FEF824 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E01C81B2511208400FEF824 /* URL+Extensions.swift */; };
|
||||
|
@ -80,9 +79,8 @@
|
|||
1EFEB5982493B6640072EDC0 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EFEB5972493B6640072EDC0 /* NotificationService.swift */; };
|
||||
1EFEB59C2493B6640072EDC0 /* NotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 1EFEB5952493B6640072EDC0 /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 06BB44DD4855498082A744AD /* libz.tbd */; };
|
||||
4BC950FF98C56CFA992BBAFE /* libPods-defaults-ShareRocketChatRN.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3982B430BE28C2D93FD9AF5C /* libPods-defaults-ShareRocketChatRN.a */; };
|
||||
4C4C8603EF082F0A33A95522 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D5C142B655F8EFD006792C /* ExpoModulesProvider.swift */; };
|
||||
58B1112437C7F012923203ED /* libPods-defaults-RocketChatRN.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 674E4FB148AE2FB17415683F /* libPods-defaults-RocketChatRN.a */; };
|
||||
77BB45FF3B406BBA2A3C36F9 /* libPods-defaults-NotificationService.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 10533AE1624775EF2CE700C5 /* libPods-defaults-NotificationService.a */; };
|
||||
7A006F14229C83B600803143 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7A006F13229C83B600803143 /* GoogleService-Info.plist */; };
|
||||
7A0D62D2242AB187006D5C06 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A0D62D1242AB187006D5C06 /* LaunchScreen.storyboard */; };
|
||||
7A14FCED257FEB3A005BDCD4 /* Experimental.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A14FCEC257FEB3A005BDCD4 /* Experimental.xcassets */; };
|
||||
|
@ -143,10 +141,12 @@
|
|||
7AE10C0728A59530003593CB /* Inter.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7AE10C0528A59530003593CB /* Inter.ttf */; };
|
||||
7AE10C0828A59530003593CB /* Inter.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7AE10C0528A59530003593CB /* Inter.ttf */; };
|
||||
85160EB6C143E0493FE5F014 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194D9A8897F4A486C2C6F89A /* ExpoModulesProvider.swift */; };
|
||||
A965681B9D9B1DB968676F54 /* libPods-defaults-NotificationService.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DEC0A8A825375FCCDCDFEFE2 /* libPods-defaults-NotificationService.a */; };
|
||||
A891D4519F3C3C0DF281382E /* libPods-defaults-RocketChatRN.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA66A470302CC036893877E3 /* libPods-defaults-RocketChatRN.a */; };
|
||||
BC404914E86821389EEB543D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 391C4F7AA7023CD41EEBD106 /* ExpoModulesProvider.swift */; };
|
||||
D344DEDBA103E81285F48C9F /* libPods-defaults-Rocket.Chat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 09A9622AB95BAF321135704F /* libPods-defaults-Rocket.Chat.a */; };
|
||||
D94D81FB9E10756FAA03F203 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016747EF3B9FED8DE2C9DA14 /* ExpoModulesProvider.swift */; };
|
||||
DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BA7E862283664608B3894E34 /* libWatermelonDB.a */; };
|
||||
E5BA08EDF1C874FF35785B16 /* libPods-defaults-ShareRocketChatRN.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 421FD6D28D6DECEEC09F100E /* libPods-defaults-ShareRocketChatRN.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -210,8 +210,9 @@
|
|||
/* Begin PBXFileReference section */
|
||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
|
||||
016747EF3B9FED8DE2C9DA14 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-defaults-ShareRocketChatRN/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||
04CABACAE3DF5FF44121FC30 /* Pods-defaults-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.debug.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
06BB44DD4855498082A744AD /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
09A9622AB95BAF321135704F /* libPods-defaults-Rocket.Chat.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-defaults-Rocket.Chat.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
10533AE1624775EF2CE700C5 /* libPods-defaults-NotificationService.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-defaults-NotificationService.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07F961A680F5B00A75B9A /* Rocket.Chat Experimental.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Rocket.Chat Experimental.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = RocketChatRN/AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RocketChatRN/Images.xcassets; sourceTree = "<group>"; };
|
||||
|
@ -264,14 +265,13 @@
|
|||
1EFEB5972493B6640072EDC0 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
|
||||
1EFEB5992493B6640072EDC0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
1EFEB5A12493B67D0072EDC0 /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = "<group>"; };
|
||||
28F09CD56CC780BB681DA43A /* Pods-defaults-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.release.xcconfig"; sourceTree = "<group>"; };
|
||||
391C4F7AA7023CD41EEBD106 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-defaults-Rocket.Chat/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||
3982B430BE28C2D93FD9AF5C /* libPods-defaults-ShareRocketChatRN.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-defaults-ShareRocketChatRN.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3AD43034372030994471D0E9 /* Pods-defaults-Rocket.Chat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.release.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.release.xcconfig"; sourceTree = "<group>"; };
|
||||
421FD6D28D6DECEEC09F100E /* libPods-defaults-ShareRocketChatRN.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-defaults-ShareRocketChatRN.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
45D5C142B655F8EFD006792C /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-defaults-RocketChatRN/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||
48A6FD916DB2F924F1360A4A /* Pods-defaults-RocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
5F1EEB258E879574E6F9EADA /* libPods-defaults-Rocket.Chat.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-defaults-Rocket.Chat.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
5CA29716AE736DD49CEC421A /* Pods-defaults-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.debug.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
60B2A6A31FC4588700BD58E5 /* RocketChatRN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = RocketChatRN.entitlements; path = RocketChatRN/RocketChatRN.entitlements; sourceTree = "<group>"; };
|
||||
674E4FB148AE2FB17415683F /* libPods-defaults-RocketChatRN.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-defaults-RocketChatRN.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
77A439FBC388926A1D8F1B98 /* Pods-defaults-RocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
7A006F13229C83B600803143 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
7A0D62D1242AB187006D5C06 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
7A14FCEC257FEB3A005BDCD4 /* Experimental.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Experimental.xcassets; sourceTree = "<group>"; };
|
||||
|
@ -282,14 +282,14 @@
|
|||
7AAB3E52257E6A6E00707CF6 /* Rocket.Chat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Rocket.Chat.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
7ACD4853222860DE00442C55 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
7AE10C0528A59530003593CB /* Inter.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Inter.ttf; sourceTree = "<group>"; };
|
||||
7E01AFB7FFC99A24DE24A9E7 /* Pods-defaults-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.release.xcconfig"; sourceTree = "<group>"; };
|
||||
8009E8CCFAA4804CCED401D8 /* Pods-defaults-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
94EB1DBE281212E61157DDEE /* Pods-defaults-ShareRocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-ShareRocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-ShareRocketChatRN/Pods-defaults-ShareRocketChatRN.release.xcconfig"; sourceTree = "<group>"; };
|
||||
AC87BFDE8CC75468C2E87328 /* Pods-defaults-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.release.xcconfig"; sourceTree = "<group>"; };
|
||||
8CF5ED249C29001A33922AC8 /* Pods-defaults-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.release.xcconfig"; sourceTree = "<group>"; };
|
||||
9EF17496557D766CD7CC65C8 /* Pods-defaults-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
B37C79D9BD0742CE936B6982 /* libc++.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
|
||||
BA7E862283664608B3894E34 /* libWatermelonDB.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libWatermelonDB.a; sourceTree = "<group>"; };
|
||||
C84BF59D4FEA8C08AD41906D /* Pods-defaults-ShareRocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-ShareRocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-ShareRocketChatRN/Pods-defaults-ShareRocketChatRN.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
DEC0A8A825375FCCDCDFEFE2 /* libPods-defaults-NotificationService.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-defaults-NotificationService.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D2549B70E3F3979B2FB2F170 /* Pods-defaults-Rocket.Chat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.release.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.release.xcconfig"; sourceTree = "<group>"; };
|
||||
E956695E229DFCCB2DB61EE2 /* Pods-defaults-ShareRocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-ShareRocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-ShareRocketChatRN/Pods-defaults-ShareRocketChatRN.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
FA35FD80EDA9584432506DDA /* Pods-defaults-ShareRocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-ShareRocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-ShareRocketChatRN/Pods-defaults-ShareRocketChatRN.release.xcconfig"; sourceTree = "<group>"; };
|
||||
FA66A470302CC036893877E3 /* libPods-defaults-RocketChatRN.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-defaults-RocketChatRN.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -310,7 +310,7 @@
|
|||
7ACD4897222860DE00442C55 /* JavaScriptCore.framework in Frameworks */,
|
||||
24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */,
|
||||
DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */,
|
||||
58B1112437C7F012923203ED /* libPods-defaults-RocketChatRN.a in Frameworks */,
|
||||
A891D4519F3C3C0DF281382E /* libPods-defaults-RocketChatRN.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -319,7 +319,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1E25743422CBA2CF005A877F /* JavaScriptCore.framework in Frameworks */,
|
||||
4BC950FF98C56CFA992BBAFE /* libPods-defaults-ShareRocketChatRN.a in Frameworks */,
|
||||
E5BA08EDF1C874FF35785B16 /* libPods-defaults-ShareRocketChatRN.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -327,7 +327,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A965681B9D9B1DB968676F54 /* libPods-defaults-NotificationService.a in Frameworks */,
|
||||
77BB45FF3B406BBA2A3C36F9 /* libPods-defaults-NotificationService.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -348,7 +348,7 @@
|
|||
7AAB3E3D257E6A6E00707CF6 /* JavaScriptCore.framework in Frameworks */,
|
||||
7AAB3E3E257E6A6E00707CF6 /* libz.tbd in Frameworks */,
|
||||
7AAB3E3F257E6A6E00707CF6 /* libWatermelonDB.a in Frameworks */,
|
||||
0DAF353368B2DE2714B6DCE8 /* libPods-defaults-Rocket.Chat.a in Frameworks */,
|
||||
D344DEDBA103E81285F48C9F /* libPods-defaults-Rocket.Chat.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -499,14 +499,14 @@
|
|||
7AC2B09613AA7C3FEBAC9F57 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8009E8CCFAA4804CCED401D8 /* Pods-defaults-NotificationService.debug.xcconfig */,
|
||||
7E01AFB7FFC99A24DE24A9E7 /* Pods-defaults-NotificationService.release.xcconfig */,
|
||||
04CABACAE3DF5FF44121FC30 /* Pods-defaults-Rocket.Chat.debug.xcconfig */,
|
||||
3AD43034372030994471D0E9 /* Pods-defaults-Rocket.Chat.release.xcconfig */,
|
||||
48A6FD916DB2F924F1360A4A /* Pods-defaults-RocketChatRN.debug.xcconfig */,
|
||||
AC87BFDE8CC75468C2E87328 /* Pods-defaults-RocketChatRN.release.xcconfig */,
|
||||
C84BF59D4FEA8C08AD41906D /* Pods-defaults-ShareRocketChatRN.debug.xcconfig */,
|
||||
94EB1DBE281212E61157DDEE /* Pods-defaults-ShareRocketChatRN.release.xcconfig */,
|
||||
9EF17496557D766CD7CC65C8 /* Pods-defaults-NotificationService.debug.xcconfig */,
|
||||
28F09CD56CC780BB681DA43A /* Pods-defaults-NotificationService.release.xcconfig */,
|
||||
5CA29716AE736DD49CEC421A /* Pods-defaults-Rocket.Chat.debug.xcconfig */,
|
||||
D2549B70E3F3979B2FB2F170 /* Pods-defaults-Rocket.Chat.release.xcconfig */,
|
||||
77A439FBC388926A1D8F1B98 /* Pods-defaults-RocketChatRN.debug.xcconfig */,
|
||||
8CF5ED249C29001A33922AC8 /* Pods-defaults-RocketChatRN.release.xcconfig */,
|
||||
E956695E229DFCCB2DB61EE2 /* Pods-defaults-ShareRocketChatRN.debug.xcconfig */,
|
||||
FA35FD80EDA9584432506DDA /* Pods-defaults-ShareRocketChatRN.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
|
@ -597,10 +597,10 @@
|
|||
7ACD4853222860DE00442C55 /* JavaScriptCore.framework */,
|
||||
B37C79D9BD0742CE936B6982 /* libc++.tbd */,
|
||||
06BB44DD4855498082A744AD /* libz.tbd */,
|
||||
DEC0A8A825375FCCDCDFEFE2 /* libPods-defaults-NotificationService.a */,
|
||||
5F1EEB258E879574E6F9EADA /* libPods-defaults-Rocket.Chat.a */,
|
||||
674E4FB148AE2FB17415683F /* libPods-defaults-RocketChatRN.a */,
|
||||
3982B430BE28C2D93FD9AF5C /* libPods-defaults-ShareRocketChatRN.a */,
|
||||
10533AE1624775EF2CE700C5 /* libPods-defaults-NotificationService.a */,
|
||||
09A9622AB95BAF321135704F /* libPods-defaults-Rocket.Chat.a */,
|
||||
FA66A470302CC036893877E3 /* libPods-defaults-RocketChatRN.a */,
|
||||
421FD6D28D6DECEEC09F100E /* libPods-defaults-ShareRocketChatRN.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
|
@ -620,7 +620,7 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "RocketChatRN" */;
|
||||
buildPhases = (
|
||||
E368867D90711EA1666BFF6A /* [CP] Check Pods Manifest.lock */,
|
||||
D9ECCB381CCB547C6D9734F3 /* [CP] Check Pods Manifest.lock */,
|
||||
7AA5C63E23E30D110005C4A7 /* Start Packager */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
|
@ -629,8 +629,8 @@
|
|||
1EC6ACF422CB9FC300A41C61 /* Embed App Extensions */,
|
||||
1E1EA8082326CCE300E22452 /* ShellScript */,
|
||||
7AAE9EB32891A0D20024F559 /* Upload source maps to Bugsnag */,
|
||||
DE93C39DFDB4F3759B84670D /* [CP] Embed Pods Frameworks */,
|
||||
52CE06391F137AA82A402A69 /* [CP] Copy Pods Resources */,
|
||||
A4C45440ECC8DF4C333E90AC /* [CP] Embed Pods Frameworks */,
|
||||
A820EB1B8BCA486D6F111B28 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -647,12 +647,12 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 1EC6ACF322CB9FC300A41C61 /* Build configuration list for PBXNativeTarget "ShareRocketChatRN" */;
|
||||
buildPhases = (
|
||||
943E61A9039C6FE02871CAD9 /* [CP] Check Pods Manifest.lock */,
|
||||
1C5A0A2393598AD05D7E91C9 /* [CP] Check Pods Manifest.lock */,
|
||||
1EC6ACAC22CB9FC300A41C61 /* Sources */,
|
||||
1EC6ACAD22CB9FC300A41C61 /* Frameworks */,
|
||||
1EC6ACAE22CB9FC300A41C61 /* Resources */,
|
||||
1EFE4DC322CBF36300B766B7 /* ShellScript */,
|
||||
1FB8D9B08356E6AC6201714D /* [CP] Copy Pods Resources */,
|
||||
826C4D7E61DA0A8A695A5BF0 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -667,11 +667,11 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 1EFEB5A02493B6640072EDC0 /* Build configuration list for PBXNativeTarget "NotificationService" */;
|
||||
buildPhases = (
|
||||
AAFC671179263417C34C729A /* [CP] Check Pods Manifest.lock */,
|
||||
443ECB36C026E4E5891D0289 /* [CP] Check Pods Manifest.lock */,
|
||||
1EFEB5912493B6640072EDC0 /* Sources */,
|
||||
1EFEB5922493B6640072EDC0 /* Frameworks */,
|
||||
1EFEB5932493B6640072EDC0 /* Resources */,
|
||||
996816F401E32166714ABD9E /* [CP] Copy Pods Resources */,
|
||||
A02AEE64373B898BFED7C77A /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -686,7 +686,7 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 7AAB3E4F257E6A6E00707CF6 /* Build configuration list for PBXNativeTarget "Rocket.Chat" */;
|
||||
buildPhases = (
|
||||
CDFA7A6FA541A8BED7CE9EE7 /* [CP] Check Pods Manifest.lock */,
|
||||
439D1EFA5403CEE68343332F /* [CP] Check Pods Manifest.lock */,
|
||||
7AAB3E13257E6A6E00707CF6 /* Start Packager */,
|
||||
7AAB3E14257E6A6E00707CF6 /* Sources */,
|
||||
7AAB3E32257E6A6E00707CF6 /* Frameworks */,
|
||||
|
@ -695,8 +695,8 @@
|
|||
7AAB3E48257E6A6E00707CF6 /* Embed App Extensions */,
|
||||
7AAB3E4B257E6A6E00707CF6 /* ShellScript */,
|
||||
7A10288726B1D15200E47EF8 /* Upload source maps to Bugsnag */,
|
||||
CCA2F3534731DC8EE1FAB416 /* [CP] Embed Pods Frameworks */,
|
||||
DEE9CFB76371CE33773CB435 /* [CP] Copy Pods Resources */,
|
||||
6B58CF06B9125764FD3EEB12 /* [CP] Embed Pods Frameworks */,
|
||||
5E4E13E42C9F5F48755B0D71 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -846,6 +846,28 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "export EXTRA_PACKAGER_ARGS=\"--sourcemap-output $TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\"\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
|
||||
};
|
||||
1C5A0A2393598AD05D7E91C9 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-defaults-ShareRocketChatRN-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
1E1EA8082326CCE300E22452 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -880,69 +902,57 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "export EXTRA_PACKAGER_ARGS=\"--sourcemap-output $TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\"\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
|
||||
};
|
||||
1FB8D9B08356E6AC6201714D /* [CP] Copy Pods Resources */ = {
|
||||
439D1EFA5403CEE68343332F /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-defaults-ShareRocketChatRN/Pods-defaults-ShareRocketChatRN-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/iosMath/mathFonts.bundle",
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Fontisto.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/mathFonts.bundle",
|
||||
"$(DERIVED_FILE_DIR)/Pods-defaults-Rocket.Chat-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-ShareRocketChatRN/Pods-defaults-ShareRocketChatRN-resources.sh\"\n";
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
52CE06391F137AA82A402A69 /* [CP] Copy Pods Resources */ = {
|
||||
443ECB36C026E4E5891D0289 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-defaults-NotificationService-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
5E4E13E42C9F5F48755B0D71 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
|
||||
|
@ -989,7 +999,31 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
6B58CF06B9125764FD3EEB12 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/JitsiMeetSDK.framework/JitsiMeetSDK",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/WebRTC.framework/WebRTC",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/hermes.framework/hermes",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JitsiMeetSDK.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
7A10288726B1D15200E47EF8 /* Upload source maps to Bugsnag */ = {
|
||||
|
@ -1095,29 +1129,63 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "SOURCE_MAP=\"$TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\" ../node_modules/@bugsnag/react-native/bugsnag-react-native-xcode.sh\n";
|
||||
};
|
||||
943E61A9039C6FE02871CAD9 /* [CP] Check Pods Manifest.lock */ = {
|
||||
826C4D7E61DA0A8A695A5BF0 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-defaults-ShareRocketChatRN/Pods-defaults-ShareRocketChatRN-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/iosMath/mathFonts.bundle",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-defaults-ShareRocketChatRN-checkManifestLockResult.txt",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Fontisto.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/mathFonts.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-ShareRocketChatRN/Pods-defaults-ShareRocketChatRN-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
996816F401E32166714ABD9E /* [CP] Copy Pods Resources */ = {
|
||||
A02AEE64373B898BFED7C77A /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
@ -1173,75 +1241,7 @@
|
|||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
AAFC671179263417C34C729A /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-defaults-NotificationService-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
CCA2F3534731DC8EE1FAB416 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/JitsiMeetSDK.framework/JitsiMeetSDK",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/WebRTC.framework/WebRTC",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/hermes.framework/hermes",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JitsiMeetSDK.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
CDFA7A6FA541A8BED7CE9EE7 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-defaults-Rocket.Chat-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DE93C39DFDB4F3759B84670D /* [CP] Embed Pods Frameworks */ = {
|
||||
A4C45440ECC8DF4C333E90AC /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
@ -1265,13 +1265,13 @@
|
|||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DEE9CFB76371CE33773CB435 /* [CP] Copy Pods Resources */ = {
|
||||
A820EB1B8BCA486D6F111B28 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
|
||||
|
@ -1318,10 +1318,10 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E368867D90711EA1666BFF6A /* [CP] Check Pods Manifest.lock */ = {
|
||||
D9ECCB381CCB547C6D9734F3 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
@ -1500,7 +1500,7 @@
|
|||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 48A6FD916DB2F924F1360A4A /* Pods-defaults-RocketChatRN.debug.xcconfig */;
|
||||
baseConfigurationReference = 77A439FBC388926A1D8F1B98 /* Pods-defaults-RocketChatRN.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
|
@ -1557,7 +1557,7 @@
|
|||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = AC87BFDE8CC75468C2E87328 /* Pods-defaults-RocketChatRN.release.xcconfig */;
|
||||
baseConfigurationReference = 8CF5ED249C29001A33922AC8 /* Pods-defaults-RocketChatRN.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
|
@ -1613,7 +1613,7 @@
|
|||
};
|
||||
1EC6ACBC22CB9FC300A41C61 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C84BF59D4FEA8C08AD41906D /* Pods-defaults-ShareRocketChatRN.debug.xcconfig */;
|
||||
baseConfigurationReference = E956695E229DFCCB2DB61EE2 /* Pods-defaults-ShareRocketChatRN.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
|
@ -1681,7 +1681,7 @@
|
|||
};
|
||||
1EC6ACBD22CB9FC300A41C61 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 94EB1DBE281212E61157DDEE /* Pods-defaults-ShareRocketChatRN.release.xcconfig */;
|
||||
baseConfigurationReference = FA35FD80EDA9584432506DDA /* Pods-defaults-ShareRocketChatRN.release.xcconfig */;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
|
@ -1748,7 +1748,7 @@
|
|||
};
|
||||
1EFEB59D2493B6640072EDC0 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 8009E8CCFAA4804CCED401D8 /* Pods-defaults-NotificationService.debug.xcconfig */;
|
||||
baseConfigurationReference = 9EF17496557D766CD7CC65C8 /* Pods-defaults-NotificationService.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
|
@ -1785,7 +1785,7 @@
|
|||
};
|
||||
1EFEB59E2493B6640072EDC0 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7E01AFB7FFC99A24DE24A9E7 /* Pods-defaults-NotificationService.release.xcconfig */;
|
||||
baseConfigurationReference = 28F09CD56CC780BB681DA43A /* Pods-defaults-NotificationService.release.xcconfig */;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
|
@ -1822,7 +1822,7 @@
|
|||
};
|
||||
7AAB3E50257E6A6E00707CF6 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 04CABACAE3DF5FF44121FC30 /* Pods-defaults-Rocket.Chat.debug.xcconfig */;
|
||||
baseConfigurationReference = 5CA29716AE736DD49CEC421A /* Pods-defaults-Rocket.Chat.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
|
@ -1876,7 +1876,7 @@
|
|||
};
|
||||
7AAB3E51257E6A6E00707CF6 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 3AD43034372030994471D0E9 /* Pods-defaults-Rocket.Chat.release.xcconfig */;
|
||||
baseConfigurationReference = D2549B70E3F3979B2FB2F170 /* Pods-defaults-Rocket.Chat.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
|
|
11
package.json
11
package.json
|
@ -18,7 +18,8 @@
|
|||
"generate-source-maps-ios": "react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ios-release.bundle --sourcemap-output ios-release.bundle.map",
|
||||
"postinstall": "patch-package && jetify",
|
||||
"prepare": "husky install",
|
||||
"build-icon-set": "node scripts/build-icon-set.js"
|
||||
"build-icon-set": "node scripts/build-icon-set.js",
|
||||
"devtools": "react-devtools"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts,tsx}": [
|
||||
|
@ -55,6 +56,7 @@
|
|||
"@rocket.chat/message-parser": "^0.31.14",
|
||||
"@rocket.chat/sdk": "RocketChat/Rocket.Chat.js.SDK#mobile",
|
||||
"@rocket.chat/ui-kit": "^0.31.19",
|
||||
"@shopify/flash-list": "^1.2.2",
|
||||
"bytebuffer": "^5.0.1",
|
||||
"color2k": "1.2.4",
|
||||
"commonmark": "git+https://github.com/RocketChat/commonmark.js.git",
|
||||
|
@ -126,8 +128,8 @@
|
|||
"react-native-ui-lib": "RocketChat/react-native-ui-lib",
|
||||
"react-native-vector-icons": "9.1.0",
|
||||
"react-native-webview": "10.3.2",
|
||||
"react-redux": "^8.0.5",
|
||||
"reactotron-react-native": "^5.0.3",
|
||||
"react-redux": "8.0.5",
|
||||
"reactotron-react-native": "5.0.3",
|
||||
"redux": "4.2.0",
|
||||
"redux-immutable-state-invariant": "2.1.0",
|
||||
"redux-saga": "1.1.3",
|
||||
|
@ -206,7 +208,10 @@
|
|||
"otp.js": "1.2.0",
|
||||
"patch-package": "6.4.7",
|
||||
"prettier": "^2.3.2",
|
||||
"react-devtools": "4.27.0",
|
||||
"react-devtools-core": "4.27.0",
|
||||
"react-dom": "17.0.1",
|
||||
"react-native-flipper-performance-plugin": "^0.3.1",
|
||||
"react-test-renderer": "17.0.2",
|
||||
"reactotron-redux": "3.1.3",
|
||||
"reactotron-redux-saga": "4.2.3",
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
diff --git a/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutView.swift b/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutView.swift
|
||||
index c2146c5..5ce7900 100644
|
||||
--- a/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutView.swift
|
||||
+++ b/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutView.swift
|
||||
@@ -231,7 +231,10 @@ import UIKit
|
||||
|
||||
/// Fixes footer position along with rest of the items
|
||||
private func fixFooter() {
|
||||
- guard !disableAutoLayout, let parentScrollView = getScrollView() else {
|
||||
+ guard !disableAutoLayout,
|
||||
+ // Fixing layout during animation can interfere with it.
|
||||
+ layer.animationKeys()?.isEmpty ?? true,
|
||||
+ let parentScrollView = getScrollView() else {
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
diff --git a/node_modules/react-native-ui-lib/lib/components/Keyboard/KeyboardInput/KeyboardAccessoryView.js b/node_modules/react-native-ui-lib/lib/components/Keyboard/KeyboardInput/KeyboardAccessoryView.js
|
||||
index cfe1d35..7ce5105 100644
|
||||
--- a/node_modules/react-native-ui-lib/lib/components/Keyboard/KeyboardInput/KeyboardAccessoryView.js
|
||||
+++ b/node_modules/react-native-ui-lib/lib/components/Keyboard/KeyboardInput/KeyboardAccessoryView.js
|
||||
@@ -123,7 +123,13 @@ class KeyboardAccessoryView extends Component {
|
||||
* Whether or not to handle SafeArea
|
||||
* default: true
|
||||
*/
|
||||
- useSafeArea: PropTypes.bool
|
||||
+ useSafeArea: PropTypes.bool,
|
||||
+
|
||||
+ /**
|
||||
+ * iOS only.
|
||||
+ * Scroll view to track
|
||||
+ */
|
||||
+ scrollViewNativeID: PropTypes.string
|
||||
};
|
||||
|
||||
static iosScrollBehaviors = IOS_SCROLL_BEHAVIORS;
|
||||
@@ -256,7 +262,8 @@ class KeyboardAccessoryView extends Component {
|
||||
kbComponent,
|
||||
onItemSelected,
|
||||
onRequestShowKeyboard,
|
||||
- useSafeArea
|
||||
+ useSafeArea,
|
||||
+ scrollViewNativeID
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@@ -271,6 +278,7 @@ class KeyboardAccessoryView extends Component {
|
||||
addBottomView={addBottomView}
|
||||
bottomViewColor={this.props.bottomViewColor}
|
||||
allowHitsOutsideBounds={allowHitsOutsideBounds}
|
||||
+ scrollViewNativeID={scrollViewNativeID}
|
||||
>
|
||||
{renderContent && renderContent()}
|
||||
<CustomKeyboardView
|
||||
diff --git a/node_modules/react-native-ui-lib/lib/ios/.DS_Store b/node_modules/react-native-ui-lib/lib/ios/.DS_Store
|
||||
new file mode 100644
|
||||
index 0000000..e69de29
|
||||
diff --git a/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardinput/rctcustomInputcontroller/RCTCustomInputControllerTemp.h b/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardinput/rctcustomInputcontroller/RCTCustomInputControllerTemp.h
|
||||
index b3864d0..e78322f 100644
|
||||
--- a/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardinput/rctcustomInputcontroller/RCTCustomInputControllerTemp.h
|
||||
+++ b/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardinput/rctcustomInputcontroller/RCTCustomInputControllerTemp.h
|
||||
@@ -8,7 +8,7 @@
|
||||
#if __has_include(<React/RCTEventEmitter.h>)
|
||||
#import <React/RCTEventEmitter.h>
|
||||
#else
|
||||
-#import "RCTEventEmitter.h"
|
||||
+#import <React/RCTEventEmitter.h>
|
||||
#endif
|
||||
|
||||
@interface RCTCustomInputControllerTemp : RCTEventEmitter
|
||||
diff --git a/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardinput/rctcustomInputcontroller/RCTCustomKeyboardViewControllerTemp.h b/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardinput/rctcustomInputcontroller/RCTCustomKeyboardViewControllerTemp.h
|
||||
index 4344724..2786051 100644
|
||||
--- a/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardinput/rctcustomInputcontroller/RCTCustomKeyboardViewControllerTemp.h
|
||||
+++ b/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardinput/rctcustomInputcontroller/RCTCustomKeyboardViewControllerTemp.h
|
||||
@@ -10,7 +10,7 @@
|
||||
#if __has_include(<React/RCTRootView.h>)
|
||||
#import <React/RCTRootView.h>
|
||||
#else
|
||||
-#import "RCTRootView.h"
|
||||
+#import <React/RCTRootView.h>
|
||||
#endif
|
||||
|
||||
@interface RCTCustomKeyboardViewControllerTemp : UIInputViewController
|
||||
diff --git a/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardtrackingview/KeyboardTrackingViewTempManager.m b/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardtrackingview/KeyboardTrackingViewTempManager.m
|
||||
index 8f8446e..728bedd 100644
|
||||
--- a/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardtrackingview/KeyboardTrackingViewTempManager.m
|
||||
+++ b/node_modules/react-native-ui-lib/lib/ios/reactnativeuilib/keyboardtrackingview/KeyboardTrackingViewTempManager.m
|
||||
@@ -43,7 +43,6 @@ @interface KeyboardTrackingViewTemp : UIView
|
||||
@property (nonatomic, strong) UIScrollView *scrollViewToManage;
|
||||
@property (nonatomic) BOOL scrollIsInverted;
|
||||
@property (nonatomic) BOOL revealKeyboardInteractive;
|
||||
-@property (nonatomic) BOOL isDraggingScrollView;
|
||||
@property (nonatomic) BOOL manageScrollView;
|
||||
@property (nonatomic) BOOL requiresSameParentToManageScrollView;
|
||||
@property (nonatomic) NSUInteger deferedInitializeAccessoryViewsCount;
|
||||
@@ -54,6 +53,7 @@ @interface KeyboardTrackingViewTemp : UIView
|
||||
@property (nonatomic) BOOL useSafeArea;
|
||||
@property (nonatomic) BOOL scrollToFocusedInput;
|
||||
@property (nonatomic) BOOL allowHitsOutsideBounds;
|
||||
+@property (nonatomic) NSString* scrollViewNativeID;
|
||||
|
||||
@end
|
||||
|
||||
@@ -84,6 +84,7 @@ -(instancetype)init
|
||||
self.addBottomView = NO;
|
||||
self.bottomViewColor = nil;
|
||||
self.scrollToFocusedInput = NO;
|
||||
+ self.scrollIsInverted = YES;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(rctContentDidAppearNotification:) name:RCTContentDidAppearNotification object:nil];
|
||||
}
|
||||
@@ -170,7 +171,6 @@ -(void)layoutSubviews
|
||||
- (void)initializeAccessoryViewsAndHandleInsets
|
||||
{
|
||||
NSArray<UIView*>* allSubviews = [self getBreadthFirstSubviewsForView:[self getRootView]];
|
||||
- NSMutableArray<RCTScrollView*>* rctScrollViewsArray = [NSMutableArray array];
|
||||
|
||||
for (UIView* subview in allSubviews)
|
||||
{
|
||||
@@ -179,24 +179,13 @@ - (void)initializeAccessoryViewsAndHandleInsets
|
||||
{
|
||||
if(_scrollViewToManage == nil)
|
||||
{
|
||||
- if(_requiresSameParentToManageScrollView && [subview isKindOfClass:[RCTScrollView class]] && subview.superview == self.superview)
|
||||
+ if([subview isKindOfClass:[RCTScrollView class]])
|
||||
{
|
||||
- _scrollViewToManage = ((RCTScrollView*)subview).scrollView;
|
||||
+ RCTScrollView *scrollView = (RCTScrollView*)subview;
|
||||
+ if (subview.nativeID && [subview.nativeID isEqualToString:self.scrollViewNativeID]) {
|
||||
+ _scrollViewToManage = scrollView.scrollView;
|
||||
+ }
|
||||
}
|
||||
- else if(!_requiresSameParentToManageScrollView && [subview isKindOfClass:[UIScrollView class]])
|
||||
- {
|
||||
- _scrollViewToManage = (UIScrollView*)subview;
|
||||
- }
|
||||
-
|
||||
- if(_scrollViewToManage != nil)
|
||||
- {
|
||||
- _scrollIsInverted = CGAffineTransformEqualToTransform(_scrollViewToManage.superview.transform, CGAffineTransformMakeScale(1, -1));
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if([subview isKindOfClass:[RCTScrollView class]])
|
||||
- {
|
||||
- [rctScrollViewsArray addObject:(RCTScrollView*)subview];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,15 +235,15 @@ - (void)initializeAccessoryViewsAndHandleInsets
|
||||
}
|
||||
}
|
||||
|
||||
- for (RCTScrollView *scrollView in rctScrollViewsArray)
|
||||
- {
|
||||
- if(scrollView.scrollView == _scrollViewToManage)
|
||||
- {
|
||||
- [scrollView removeScrollListener:self];
|
||||
- [scrollView addScrollListener:self];
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
+// for (RCTScrollView *scrollView in [_rctScrollViewsArray allValues])
|
||||
+// {
|
||||
+// if(scrollView.scrollView == _scrollViewToManage)
|
||||
+// {
|
||||
+// [scrollView removeScrollListener:self];
|
||||
+// [scrollView addScrollListener:self];
|
||||
+// break;
|
||||
+// }
|
||||
+// }
|
||||
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_10_3
|
||||
if (@available(iOS 11.0, *)) {
|
||||
@@ -412,9 +401,6 @@ - (void)_updateScrollViewInsets
|
||||
CGFloat bottomSafeArea = [self getBottomSafeArea];
|
||||
CGFloat bottomInset = MAX(self.bounds.size.height, _ObservingInputAccessoryViewTemp.keyboardHeight + _ObservingInputAccessoryViewTemp.height);
|
||||
|
||||
- CGFloat originalBottomInset = self.scrollIsInverted ? insets.top : insets.bottom;
|
||||
- CGPoint originalOffset = self.scrollViewToManage.contentOffset;
|
||||
-
|
||||
bottomInset += (_ObservingInputAccessoryViewTemp.keyboardHeight == 0 ? bottomSafeArea : 0);
|
||||
if(self.scrollIsInverted)
|
||||
{
|
||||
@@ -426,20 +412,11 @@ - (void)_updateScrollViewInsets
|
||||
}
|
||||
self.scrollViewToManage.contentInset = insets;
|
||||
|
||||
- if(self.scrollBehavior == KeyboardTrackingScrollBehaviorScrollToBottomInvertedOnly && _scrollIsInverted)
|
||||
+ BOOL firstTime = _ObservingInputAccessoryViewTemp.keyboardHeight == 0 && _ObservingInputAccessoryViewTemp.keyboardState == KeyboardStateHidden;
|
||||
+ BOOL willOpen = _ObservingInputAccessoryViewTemp.keyboardHeight != 0 && _ObservingInputAccessoryViewTemp.keyboardState == KeyboardStateHidden;
|
||||
+ if(firstTime || willOpen)
|
||||
{
|
||||
- BOOL fisrtTime = _ObservingInputAccessoryViewTemp.keyboardHeight == 0 && _ObservingInputAccessoryViewTemp.keyboardState == KeyboardStateHidden;
|
||||
- BOOL willOpen = _ObservingInputAccessoryViewTemp.keyboardHeight != 0 && _ObservingInputAccessoryViewTemp.keyboardState == KeyboardStateHidden;
|
||||
- BOOL isOpen = _ObservingInputAccessoryViewTemp.keyboardHeight != 0 && _ObservingInputAccessoryViewTemp.keyboardState == KeyboardStateShown;
|
||||
- if(fisrtTime || willOpen || (isOpen && !self.isDraggingScrollView))
|
||||
- {
|
||||
- [self.scrollViewToManage setContentOffset:CGPointMake(self.scrollViewToManage.contentOffset.x, -self.scrollViewToManage.contentInset.top) animated:!fisrtTime];
|
||||
- }
|
||||
- }
|
||||
- else if(self.scrollBehavior == KeyboardTrackingScrollBehaviorFixedOffset && !self.isDraggingScrollView)
|
||||
- {
|
||||
- CGFloat insetsDiff = (bottomInset - originalBottomInset) * (self.scrollIsInverted ? -1 : 1);
|
||||
- self.scrollViewToManage.contentOffset = CGPointMake(originalOffset.x, originalOffset.y + insetsDiff);
|
||||
+ [self.scrollViewToManage setContentOffset:CGPointMake(self.scrollViewToManage.contentOffset.x, -self.scrollViewToManage.contentInset.top) animated:!firstTime];
|
||||
}
|
||||
|
||||
insets = self.scrollViewToManage.contentInset;
|
||||
@@ -468,7 +445,6 @@ -(void)addBottomViewIfNecessary
|
||||
if (self.addBottomView && _bottomView == nil)
|
||||
{
|
||||
_bottomView = [UIView new];
|
||||
- // _bottomView.backgroundColor = [UIColor whiteColor];
|
||||
if (self.bottomViewColor)
|
||||
{
|
||||
_bottomView.backgroundColor = [self colorFromHexString:self.bottomViewColor];
|
||||
@@ -607,21 +583,6 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
||||
}
|
||||
}
|
||||
|
||||
-- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
|
||||
-{
|
||||
- self.isDraggingScrollView = YES;
|
||||
-}
|
||||
-
|
||||
-- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
|
||||
-{
|
||||
- self.isDraggingScrollView = NO;
|
||||
-}
|
||||
-
|
||||
-- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
|
||||
-{
|
||||
- self.isDraggingScrollView = NO;
|
||||
-}
|
||||
-
|
||||
- (CGFloat)getKeyboardHeight
|
||||
{
|
||||
return _ObservingInputAccessoryViewTemp ? _ObservingInputAccessoryViewTemp.keyboardHeight : 0;
|
||||
@@ -664,6 +625,7 @@ @implementation KeyboardTrackingViewTempManager
|
||||
RCT_REMAP_VIEW_PROPERTY(useSafeArea, useSafeArea, BOOL)
|
||||
RCT_REMAP_VIEW_PROPERTY(scrollToFocusedInput, scrollToFocusedInput, BOOL)
|
||||
RCT_REMAP_VIEW_PROPERTY(allowHitsOutsideBounds, allowHitsOutsideBounds, BOOL)
|
||||
+RCT_EXPORT_VIEW_PROPERTY(scrollViewNativeID, NSString)
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
Loading…
Reference in New Issue