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.bridge.ReactContext;
|
||||||
import com.facebook.react.modules.network.NetworkingModule;
|
import com.facebook.react.modules.network.NetworkingModule;
|
||||||
import com.facebook.react.modules.network.CustomClientBuilder;
|
import com.facebook.react.modules.network.CustomClientBuilder;
|
||||||
|
import tech.bam.rnperformance.flipper.RNPerfMonitorPlugin;
|
||||||
|
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
public class ReactNativeFlipper {
|
public class ReactNativeFlipper {
|
||||||
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
|
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
|
||||||
|
@ -33,6 +35,8 @@ public class ReactNativeFlipper {
|
||||||
client.addPlugin(new DatabasesFlipperPlugin(context));
|
client.addPlugin(new DatabasesFlipperPlugin(context));
|
||||||
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
|
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
|
||||||
client.addPlugin(CrashReporterPlugin.getInstance());
|
client.addPlugin(CrashReporterPlugin.getInstance());
|
||||||
|
client.addPlugin(new RNPerfMonitorPlugin(reactInstanceManager));
|
||||||
|
|
||||||
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
|
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
|
||||||
NetworkingModule.setCustomClientBuilder(
|
NetworkingModule.setCustomClientBuilder(
|
||||||
new CustomClientBuilder() {
|
new CustomClientBuilder() {
|
||||||
|
|
|
@ -9,13 +9,16 @@ import com.facebook.react.ReactApplication;
|
||||||
import com.facebook.react.ReactNativeHost;
|
import com.facebook.react.ReactNativeHost;
|
||||||
import com.facebook.react.ReactPackage;
|
import com.facebook.react.ReactPackage;
|
||||||
import com.facebook.react.config.ReactFeatureFlags;
|
import com.facebook.react.config.ReactFeatureFlags;
|
||||||
|
import com.facebook.react.ReactInstanceManager;
|
||||||
import com.facebook.soloader.SoLoader;
|
import com.facebook.soloader.SoLoader;
|
||||||
import com.reactnativecommunity.viewpager.RNCViewPagerPackage;
|
import com.reactnativecommunity.viewpager.RNCViewPagerPackage;
|
||||||
import com.facebook.react.bridge.JSIModulePackage;
|
import com.facebook.react.bridge.JSIModulePackage;
|
||||||
import com.swmansion.reanimated.ReanimatedJSIModulePackage;
|
import com.swmansion.reanimated.ReanimatedJSIModulePackage;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import expo.modules.ApplicationLifecycleDispatcher;
|
import expo.modules.ApplicationLifecycleDispatcher;
|
||||||
import expo.modules.ReactNativeHostWrapper;
|
import expo.modules.ReactNativeHostWrapper;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
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
|
// If you opted-in for the New Architecture, we enable the TurboModule system
|
||||||
ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||||
SoLoader.init(this, /* native exopackage */ false);
|
SoLoader.init(this, /* native exopackage */ false);
|
||||||
|
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||||
ApplicationLifecycleDispatcher.onApplicationCreate(this);
|
ApplicationLifecycleDispatcher.onApplicationCreate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,4 +88,35 @@ public class MainApplication extends Application implements ReactApplication {
|
||||||
super.onConfigurationChanged(newConfig);
|
super.onConfigurationChanged(newConfig);
|
||||||
ApplicationLifecycleDispatcher.onConfigurationChanged(this, 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
|
android.enableJetifier=true
|
||||||
|
|
||||||
# Version of flipper SDK to use with React Native
|
# 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.
|
# Use this property to specify which architecture you want to build.
|
||||||
# You can also override it from the CLI using
|
# You can also override it from the CLI using
|
||||||
|
|
|
@ -10,12 +10,12 @@ import { useFrequentlyUsedEmoji } from '../../lib/hooks';
|
||||||
import CustomEmoji from '../EmojiPicker/CustomEmoji';
|
import CustomEmoji from '../EmojiPicker/CustomEmoji';
|
||||||
import { useDimensions } from '../../dimensions';
|
import { useDimensions } from '../../dimensions';
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
import { IEmoji, TAnyMessageModel } from '../../definitions';
|
import { IEmoji, TAnyMessage } from '../../definitions';
|
||||||
import Touch from '../Touch';
|
import Touch from '../Touch';
|
||||||
|
|
||||||
export interface IHeader {
|
export interface IHeader {
|
||||||
handleReaction: (emoji: IEmoji | null, message: TAnyMessageModel) => void;
|
handleReaction: (emoji: IEmoji | null, message: TAnyMessage) => void;
|
||||||
message: TAnyMessageModel;
|
message: TAnyMessage;
|
||||||
isMasterDetail: boolean;
|
isMasterDetail: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { connect } from 'react-redux';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
import database from '../../lib/database';
|
import database from '../../lib/database';
|
||||||
|
import { getMessageById } from '../../lib/database/services/Message';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import log, { logEvent } from '../../lib/methods/helpers/log';
|
import log, { logEvent } from '../../lib/methods/helpers/log';
|
||||||
import Navigation from '../../lib/navigation/appNavigation';
|
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 { TActionSheetOptionsItem, useActionSheet, ACTION_SHEET_ANIMATION_DURATION } from '../ActionSheet';
|
||||||
import Header, { HEADER_HEIGHT, IHeader } from './Header';
|
import Header, { HEADER_HEIGHT, IHeader } from './Header';
|
||||||
import events from '../../lib/methods/helpers/log/events';
|
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 { getPermalinkMessage } from '../../lib/methods';
|
||||||
import { getRoomTitle, getUidDirectMessage, hasPermission } from '../../lib/methods/helpers';
|
import { getRoomTitle, getUidDirectMessage, hasPermission } from '../../lib/methods/helpers';
|
||||||
import { Services } from '../../lib/services';
|
import { Services } from '../../lib/services';
|
||||||
|
@ -24,10 +25,10 @@ export interface IMessageActionsProps {
|
||||||
room: TSubscriptionModel;
|
room: TSubscriptionModel;
|
||||||
tmid?: string;
|
tmid?: string;
|
||||||
user: Pick<ILoggedUser, 'id'>;
|
user: Pick<ILoggedUser, 'id'>;
|
||||||
editInit: (message: TAnyMessageModel) => void;
|
editInit: (message: TAnyMessage) => void;
|
||||||
reactionInit: (message: TAnyMessageModel) => void;
|
reactionInit: (message: TAnyMessage) => void;
|
||||||
onReactionPress: (shortname: IEmoji, messageId: string) => void;
|
onReactionPress: (shortname: IEmoji, messageId: string) => void;
|
||||||
replyInit: (message: TAnyMessageModel, mention: boolean) => void;
|
replyInit: (message: TAnyMessage, mention: boolean) => void;
|
||||||
isMasterDetail: boolean;
|
isMasterDetail: boolean;
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
Message_AllowDeleting?: boolean;
|
Message_AllowDeleting?: boolean;
|
||||||
|
@ -46,7 +47,7 @@ export interface IMessageActionsProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IMessageActions {
|
export interface IMessageActions {
|
||||||
showMessageActions: (message: TAnyMessageModel) => Promise<void>;
|
showMessageActions: (message: TAnyMessage) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MessageActions = React.memo(
|
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) {
|
if (isReadOnly) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +136,7 @@ const MessageActions = React.memo(
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const allowDelete = (message: TAnyMessageModel) => {
|
const allowDelete = (message: TAnyMessage) => {
|
||||||
if (isReadOnly) {
|
if (isReadOnly) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -166,19 +167,19 @@ const MessageActions = React.memo(
|
||||||
return true;
|
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);
|
logEvent(events.ROOM_MSG_ACTION_REPLY);
|
||||||
replyInit(message, true);
|
replyInit(message, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEdit = (message: TAnyMessageModel) => {
|
const handleEdit = (message: TAnyMessage) => {
|
||||||
logEvent(events.ROOM_MSG_ACTION_EDIT);
|
logEvent(events.ROOM_MSG_ACTION_EDIT);
|
||||||
editInit(message);
|
editInit(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCreateDiscussion = (message: TAnyMessageModel) => {
|
const handleCreateDiscussion = (message: TAnyMessage) => {
|
||||||
logEvent(events.ROOM_MSG_ACTION_DISCUSSION);
|
logEvent(events.ROOM_MSG_ACTION_DISCUSSION);
|
||||||
const params = { message, channel: room, showCloseModal: true };
|
const params = { message, channel: room, showCloseModal: true };
|
||||||
if (isMasterDetail) {
|
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);
|
logEvent(events.ROOM_MSG_ACTION_UNREAD);
|
||||||
const { id: messageId, ts } = message;
|
const { id: messageId, ts } = message;
|
||||||
const { rid } = room;
|
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);
|
logEvent(events.ROOM_MSG_ACTION_PERMALINK);
|
||||||
try {
|
try {
|
||||||
const permalink = await getPermalink(message);
|
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);
|
logEvent(events.ROOM_MSG_ACTION_COPY);
|
||||||
await Clipboard.setString((message?.attachments?.[0]?.description || message.msg) ?? '');
|
await Clipboard.setString((message?.attachments?.[0]?.description || message.msg) ?? '');
|
||||||
EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
|
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);
|
logEvent(events.ROOM_MSG_ACTION_SHARE);
|
||||||
try {
|
try {
|
||||||
const permalink = await getPermalink(message);
|
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);
|
logEvent(events.ROOM_MSG_ACTION_QUOTE);
|
||||||
replyInit(message, false);
|
replyInit(message, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleReplyInDM = async (message: TAnyMessageModel) => {
|
const handleReplyInDM = async (message: TAnyMessage) => {
|
||||||
if (message?.u?.username) {
|
if (message?.u?.username) {
|
||||||
const result = await Services.createDirectMessage(message.u.username);
|
const result = await Services.createDirectMessage(message.u.username);
|
||||||
if (result.success) {
|
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);
|
logEvent(message.starred ? events.ROOM_MSG_ACTION_UNSTAR : events.ROOM_MSG_ACTION_STAR);
|
||||||
try {
|
try {
|
||||||
await Services.toggleStarMessage(message.id, message.starred as boolean); // TODO: reevaluate `message.starred` type on IMessage
|
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);
|
logEvent(events.ROOM_MSG_ACTION_PIN);
|
||||||
try {
|
try {
|
||||||
await Services.togglePinMessage(message.id, message.pinned as boolean); // TODO: reevaluate `message.pinned` type on IMessage
|
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();
|
hideActionSheet();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleReadReceipt = (message: TAnyMessageModel) => {
|
const handleReadReceipt = (message: TAnyMessage) => {
|
||||||
if (isMasterDetail) {
|
if (isMasterDetail) {
|
||||||
Navigation.navigate('ModalStackNavigator', { screen: 'ReadReceiptsView', params: { messageId: message.id } });
|
Navigation.navigate('ModalStackNavigator', { screen: 'ReadReceiptsView', params: { messageId: message.id } });
|
||||||
} else {
|
} else {
|
||||||
|
@ -303,14 +304,18 @@ const MessageActions = React.memo(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleToggleTranslation = async (message: TAnyMessageModel) => {
|
const handleToggleTranslation = async (message: TAnyMessage) => {
|
||||||
try {
|
try {
|
||||||
if (!room.autoTranslateLanguage) {
|
if (!room.autoTranslateLanguage) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
|
const messageRecord = await getMessageById(message.id);
|
||||||
|
if (!messageRecord) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await db.write(async () => {
|
await db.write(async () => {
|
||||||
await message.update(m => {
|
await messageRecord.update(m => {
|
||||||
m.autoTranslate = !m.autoTranslate;
|
m.autoTranslate = !m.autoTranslate;
|
||||||
m._updatedAt = new Date();
|
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);
|
logEvent(events.ROOM_MSG_ACTION_REPORT);
|
||||||
try {
|
try {
|
||||||
await Services.reportMessage(message.id);
|
await Services.reportMessage(message.id);
|
||||||
|
@ -335,14 +340,14 @@ const MessageActions = React.memo(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = (message: TAnyMessageModel) => {
|
const handleDelete = (message: TAnyMessage) => {
|
||||||
showConfirmationAlert({
|
showConfirmationAlert({
|
||||||
message: I18n.t('You_will_not_be_able_to_recover_this_message'),
|
message: I18n.t('You_will_not_be_able_to_recover_this_message'),
|
||||||
confirmationText: I18n.t('Delete'),
|
confirmationText: I18n.t('Delete'),
|
||||||
onPress: async () => {
|
onPress: async () => {
|
||||||
try {
|
try {
|
||||||
logEvent(events.ROOM_MSG_ACTION_DELETE);
|
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) {
|
} catch (e) {
|
||||||
logEvent(events.ROOM_MSG_ACTION_DELETE_F);
|
logEvent(events.ROOM_MSG_ACTION_DELETE_F);
|
||||||
log(e);
|
log(e);
|
||||||
|
@ -351,7 +356,7 @@ const MessageActions = React.memo(
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOptions = (message: TAnyMessageModel) => {
|
const getOptions = (message: TAnyMessage) => {
|
||||||
const options: TActionSheetOptionsItem[] = [];
|
const options: TActionSheetOptionsItem[] = [];
|
||||||
const videoConfBlock = message.t === 'videoconf';
|
const videoConfBlock = message.t === 'videoconf';
|
||||||
|
|
||||||
|
@ -487,7 +492,7 @@ const MessageActions = React.memo(
|
||||||
return options;
|
return options;
|
||||||
};
|
};
|
||||||
|
|
||||||
const showMessageActions = async (message: TAnyMessageModel) => {
|
const showMessageActions = async (message: TAnyMessage) => {
|
||||||
logEvent(events.ROOM_SHOW_MSG_ACTIONS);
|
logEvent(events.ROOM_SHOW_MSG_ACTIONS);
|
||||||
await getPermissions();
|
await getPermissions();
|
||||||
showActionSheet({
|
showActionSheet({
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Alert, Keyboard, NativeModules, Text, View, BackHandler } from 'react-native';
|
import { Alert, Keyboard, NativeModules, Text, View, BackHandler } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
// import { KeyboardTrackingView } from 'react-native-keyboard-tracking-view';
|
||||||
import { KeyboardAccessoryView } from 'react-native-ui-lib/keyboard';
|
import { KeyboardAccessoryView } from 'react-native-ui-lib/keyboard';
|
||||||
import ImagePicker, { Image, ImageOrVideo, Options } from 'react-native-image-crop-picker';
|
import ImagePicker, { Image, ImageOrVideo, Options } from 'react-native-image-crop-picker';
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
|
@ -169,7 +170,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
id: ''
|
id: ''
|
||||||
},
|
},
|
||||||
sharing: false,
|
sharing: false,
|
||||||
iOSScrollBehavior: NativeModules.KeyboardTrackingViewTempManager?.KeyboardTrackingScrollBehaviorFixedOffset,
|
iOSScrollBehavior: NativeModules.KeyboardTrackingViewTempManager?.KeyboardTrackingScrollBehaviorScrollToBottomInvertedOnly,
|
||||||
isActionsEnabled: true,
|
isActionsEnabled: true,
|
||||||
getCustomEmoji: () => {}
|
getCustomEmoji: () => {}
|
||||||
};
|
};
|
||||||
|
@ -1290,7 +1291,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
render() {
|
render() {
|
||||||
console.count(`${this.constructor.name}.render calls`);
|
console.count(`${this.constructor.name}.render calls`);
|
||||||
const { showEmojiKeyboard } = this.state;
|
const { showEmojiKeyboard } = this.state;
|
||||||
const { user, baseUrl, theme, iOSScrollBehavior } = this.props;
|
const { user, baseUrl, theme, iOSScrollBehavior, tmid, rid } = this.props;
|
||||||
return (
|
return (
|
||||||
<MessageboxContext.Provider
|
<MessageboxContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
@ -1309,11 +1310,10 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
kbInitialProps={{ theme }}
|
kbInitialProps={{ theme }}
|
||||||
onKeyboardResigned={this.onKeyboardResigned}
|
onKeyboardResigned={this.onKeyboardResigned}
|
||||||
onItemSelected={this.onKeyboardItemSelected}
|
onItemSelected={this.onKeyboardItemSelected}
|
||||||
trackInteractive
|
|
||||||
requiresSameParentToManageScrollView
|
|
||||||
addBottomView
|
addBottomView
|
||||||
bottomViewColor={themes[theme].messageboxBackground}
|
bottomViewColor={themes[theme].messageboxBackground}
|
||||||
iOSScrollBehavior={iOSScrollBehavior}
|
iOSScrollBehavior={iOSScrollBehavior}
|
||||||
|
scrollViewNativeID={tmid || rid}
|
||||||
/>
|
/>
|
||||||
</MessageboxContext.Provider>
|
</MessageboxContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { forwardRef, useImperativeHandle } from 'react';
|
import { forwardRef, useImperativeHandle } from 'react';
|
||||||
import Model from '@nozbe/watermelondb/Model';
|
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 database from '../lib/database';
|
||||||
import protectedFunction from '../lib/methods/helpers/protectedFunction';
|
import protectedFunction from '../lib/methods/helpers/protectedFunction';
|
||||||
import { useActionSheet } from './ActionSheet';
|
import { useActionSheet } from './ActionSheet';
|
||||||
|
@ -27,16 +29,16 @@ const MessageErrorActions = forwardRef<IMessageErrorActions, { tmid?: string }>(
|
||||||
const msgCollection = db.get('messages');
|
const msgCollection = db.get('messages');
|
||||||
const threadCollection = db.get('threads');
|
const threadCollection = db.get('threads');
|
||||||
|
|
||||||
// Delete the object (it can be Message or ThreadMessage instance)
|
const msg = await getMessageById(message.id);
|
||||||
deleteBatch.push(message.prepareDestroyPermanently());
|
if (msg) {
|
||||||
|
deleteBatch.push(msg.prepareDestroyPermanently());
|
||||||
|
}
|
||||||
|
|
||||||
// If it's a thread, we find and delete the whole tree, if necessary
|
// If it's a thread, we find and delete the whole tree, if necessary
|
||||||
if (tmid) {
|
if (tmid) {
|
||||||
try {
|
const msg = await getThreadMessageById(message.id);
|
||||||
const msg = await msgCollection.find(message.id);
|
if (msg) {
|
||||||
deleteBatch.push(msg.prepareDestroyPermanently());
|
deleteBatch.push(msg.prepareDestroyPermanently());
|
||||||
} catch {
|
|
||||||
// Do nothing: message not found
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { dequal } from 'dequal';
|
|
||||||
|
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
@ -45,9 +44,7 @@ const formatMsg = ({ lastMessage, type, showLastMessage, username, useRealName }
|
||||||
return `${prefix}${lastMessage.msg}`;
|
return `${prefix}${lastMessage.msg}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const arePropsEqual = (oldProps: any, newProps: any) => dequal(oldProps, newProps);
|
const LastMessage = ({ lastMessage, type, showLastMessage, username, alert, useRealName }: ILastMessageProps) => {
|
||||||
|
|
||||||
const LastMessage = React.memo(({ lastMessage, type, showLastMessage, username, alert, useRealName }: ILastMessageProps) => {
|
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
return (
|
return (
|
||||||
<MarkdownPreview
|
<MarkdownPreview
|
||||||
|
@ -63,6 +60,6 @@ const LastMessage = React.memo(({ lastMessage, type, showLastMessage, username,
|
||||||
testID='room-item-last-message'
|
testID='room-item-last-message'
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}, arePropsEqual);
|
};
|
||||||
|
|
||||||
export default LastMessage;
|
export default LastMessage;
|
||||||
|
|
|
@ -20,7 +20,6 @@ const RoomItem = ({
|
||||||
prid,
|
prid,
|
||||||
name,
|
name,
|
||||||
avatar,
|
avatar,
|
||||||
width,
|
|
||||||
username,
|
username,
|
||||||
showLastMessage,
|
showLastMessage,
|
||||||
status = 'offline',
|
status = 'offline',
|
||||||
|
@ -52,12 +51,13 @@ const RoomItem = ({
|
||||||
showAvatar,
|
showAvatar,
|
||||||
displayMode,
|
displayMode,
|
||||||
sourceType,
|
sourceType,
|
||||||
hideMentionStatus
|
hideMentionStatus,
|
||||||
|
touchableRef
|
||||||
}: IRoomItemProps) => (
|
}: IRoomItemProps) => (
|
||||||
<Touchable
|
<Touchable
|
||||||
|
ref={touchableRef}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
onLongPress={onLongPress}
|
onLongPress={onLongPress}
|
||||||
width={width}
|
|
||||||
favorite={favorite}
|
favorite={favorite}
|
||||||
toggleFav={toggleFav}
|
toggleFav={toggleFav}
|
||||||
isRead={isRead}
|
isRead={isRead}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { forwardRef, useImperativeHandle } from 'react';
|
||||||
import Animated, {
|
import Animated, {
|
||||||
useAnimatedGestureHandler,
|
useAnimatedGestureHandler,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
|
@ -13,227 +13,242 @@ import {
|
||||||
HandlerStateChangeEventPayload,
|
HandlerStateChangeEventPayload,
|
||||||
PanGestureHandlerEventPayload
|
PanGestureHandlerEventPayload
|
||||||
} from 'react-native-gesture-handler';
|
} from 'react-native-gesture-handler';
|
||||||
|
import { useWindowDimensions } from 'react-native';
|
||||||
|
|
||||||
import Touch from '../Touch';
|
import Touch from '../Touch';
|
||||||
import { ACTION_WIDTH, LONG_SWIPE, SMALL_SWIPE } from './styles';
|
import { ACTION_WIDTH, LONG_SWIPE, SMALL_SWIPE } from './styles';
|
||||||
import { LeftActions, RightActions } from './Actions';
|
import { LeftActions, RightActions } from './Actions';
|
||||||
import { ITouchableProps } from './interfaces';
|
import { ITouchableProps, ITouchableRef } from './interfaces';
|
||||||
import { useTheme } from '../../theme';
|
import { useTheme } from '../../theme';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
|
import { MAX_SIDEBAR_WIDTH } from '../../lib/constants';
|
||||||
|
import { useAppSelector } from '../../lib/hooks';
|
||||||
|
|
||||||
const Touchable = ({
|
const Touchable = forwardRef<ITouchableRef, ITouchableProps>(
|
||||||
children,
|
(
|
||||||
type,
|
{
|
||||||
onPress,
|
children,
|
||||||
onLongPress,
|
type,
|
||||||
testID,
|
onPress,
|
||||||
width,
|
onLongPress,
|
||||||
favorite,
|
testID,
|
||||||
isRead,
|
favorite,
|
||||||
rid,
|
isRead,
|
||||||
toggleFav,
|
rid,
|
||||||
toggleRead,
|
toggleFav,
|
||||||
hideChannel,
|
toggleRead,
|
||||||
isFocused,
|
hideChannel,
|
||||||
swipeEnabled,
|
isFocused,
|
||||||
displayMode
|
swipeEnabled,
|
||||||
}: ITouchableProps): React.ReactElement => {
|
displayMode
|
||||||
const { colors } = useTheme();
|
},
|
||||||
|
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 rowOffSet = useSharedValue(0);
|
||||||
const transX = useSharedValue(0);
|
const transX = useSharedValue(0);
|
||||||
const rowState = useSharedValue(0); // 0: closed, 1: right opened, -1: left opened
|
const rowState = useSharedValue(0); // 0: closed, 1: right opened, -1: left opened
|
||||||
let _value = 0;
|
let _value = 0;
|
||||||
|
|
||||||
const close = () => {
|
const close = () => {
|
||||||
rowState.value = 0;
|
console.log(`${rid} close`);
|
||||||
transX.value = withSpring(0, { overshootClamping: true });
|
rowState.value = 0;
|
||||||
rowOffSet.value = 0;
|
transX.value = withSpring(0, { overshootClamping: true });
|
||||||
};
|
rowOffSet.value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
const handleToggleFav = () => {
|
useImperativeHandle(ref, () => ({
|
||||||
if (toggleFav) {
|
close
|
||||||
toggleFav(rid, favorite);
|
}));
|
||||||
}
|
|
||||||
close();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleToggleRead = () => {
|
const handleToggleFav = () => {
|
||||||
if (toggleRead) {
|
if (toggleFav) {
|
||||||
toggleRead(rid, isRead);
|
toggleFav(rid, favorite);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const handleHideChannel = () => {
|
|
||||||
if (hideChannel) {
|
|
||||||
hideChannel(rid, type);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onToggleReadPress = () => {
|
|
||||||
handleToggleRead();
|
|
||||||
close();
|
|
||||||
};
|
|
||||||
|
|
||||||
const onHidePress = () => {
|
|
||||||
handleHideChannel();
|
|
||||||
close();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePress = () => {
|
|
||||||
if (rowState.value !== 0) {
|
|
||||||
close();
|
close();
|
||||||
return;
|
};
|
||||||
}
|
|
||||||
if (onPress) {
|
|
||||||
onPress();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleLongPress = () => {
|
const handleToggleRead = () => {
|
||||||
if (rowState.value !== 0) {
|
if (toggleRead) {
|
||||||
|
toggleRead(rid, isRead);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHideChannel = () => {
|
||||||
|
if (hideChannel) {
|
||||||
|
hideChannel(rid, type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onToggleReadPress = () => {
|
||||||
|
handleToggleRead();
|
||||||
close();
|
close();
|
||||||
return;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
if (onLongPress) {
|
const onHidePress = () => {
|
||||||
onLongPress();
|
handleHideChannel();
|
||||||
}
|
close();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onLongPressHandlerStateChange = ({ nativeEvent }: { nativeEvent: HandlerStateChangeEventPayload }) => {
|
const handlePress = () => {
|
||||||
if (nativeEvent.state === State.ACTIVE) {
|
if (rowState.value !== 0) {
|
||||||
handleLongPress();
|
close();
|
||||||
}
|
return;
|
||||||
};
|
}
|
||||||
|
if (onPress) {
|
||||||
|
onPress();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleRelease = (event: PanGestureHandlerEventPayload) => {
|
const handleLongPress = () => {
|
||||||
const { translationX } = event;
|
if (rowState.value !== 0) {
|
||||||
_value += translationX;
|
close();
|
||||||
let toValue = 0;
|
return;
|
||||||
if (rowState.value === 0) {
|
}
|
||||||
// if no option is opened
|
|
||||||
if (translationX > 0 && translationX < LONG_SWIPE) {
|
if (onLongPress) {
|
||||||
if (I18n.isRTL) {
|
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;
|
toValue = 2 * ACTION_WIDTH;
|
||||||
} else {
|
} else {
|
||||||
toValue = ACTION_WIDTH;
|
toValue = ACTION_WIDTH;
|
||||||
}
|
}
|
||||||
rowState.value = -1;
|
} else if (rowState.value === 1) {
|
||||||
} else if (translationX >= LONG_SWIPE) {
|
// if right option is opened
|
||||||
toValue = 0;
|
if (_value > -2 * SMALL_SWIPE) {
|
||||||
if (I18n.isRTL) {
|
toValue = 0;
|
||||||
handleHideChannel();
|
rowState.value = 0;
|
||||||
} else {
|
} else if (_value < -LONG_SWIPE) {
|
||||||
handleToggleRead();
|
if (I18n.isRTL) {
|
||||||
}
|
handleToggleRead();
|
||||||
} else if (translationX < 0 && translationX > -LONG_SWIPE) {
|
} else {
|
||||||
// open trailing option if he swipe left
|
handleHideChannel();
|
||||||
if (I18n.isRTL) {
|
}
|
||||||
|
} else if (I18n.isRTL) {
|
||||||
toValue = -ACTION_WIDTH;
|
toValue = -ACTION_WIDTH;
|
||||||
} else {
|
} else {
|
||||||
toValue = -2 * ACTION_WIDTH;
|
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) {
|
transX.value = withSpring(toValue, { overshootClamping: true });
|
||||||
// if left option is opened
|
rowOffSet.value = toValue;
|
||||||
if (_value < SMALL_SWIPE) {
|
_value = toValue;
|
||||||
toValue = 0;
|
};
|
||||||
rowState.value = 0;
|
|
||||||
} else if (_value > LONG_SWIPE) {
|
const onGestureEvent = useAnimatedGestureHandler({
|
||||||
toValue = 0;
|
onActive: event => {
|
||||||
rowState.value = 0;
|
transX.value = event.translationX + rowOffSet.value;
|
||||||
if (I18n.isRTL) {
|
if (transX.value > 2 * width) transX.value = 2 * width;
|
||||||
handleHideChannel();
|
},
|
||||||
} else {
|
onEnd: event => {
|
||||||
handleToggleRead();
|
runOnJS(handleRelease)(event);
|
||||||
}
|
|
||||||
} else if (I18n.isRTL) {
|
|
||||||
toValue = 2 * ACTION_WIDTH;
|
|
||||||
} else {
|
|
||||||
toValue = ACTION_WIDTH;
|
|
||||||
}
|
}
|
||||||
} 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({
|
const animatedStyles = useAnimatedStyle(() => ({ transform: [{ translateX: transX.value }] }));
|
||||||
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 }] }));
|
return (
|
||||||
|
<LongPressGestureHandler onHandlerStateChange={onLongPressHandlerStateChange}>
|
||||||
return (
|
<Animated.View>
|
||||||
<LongPressGestureHandler onHandlerStateChange={onLongPressHandlerStateChange}>
|
<PanGestureHandler activeOffsetX={[-20, 20]} onGestureEvent={onGestureEvent} enabled={swipeEnabled}>
|
||||||
<Animated.View>
|
<Animated.View>
|
||||||
<PanGestureHandler activeOffsetX={[-20, 20]} onGestureEvent={onGestureEvent} enabled={swipeEnabled}>
|
<LeftActions
|
||||||
<Animated.View>
|
transX={transX}
|
||||||
<LeftActions
|
isRead={isRead}
|
||||||
transX={transX}
|
width={width}
|
||||||
isRead={isRead}
|
onToggleReadPress={onToggleReadPress}
|
||||||
width={width}
|
displayMode={displayMode}
|
||||||
onToggleReadPress={onToggleReadPress}
|
/>
|
||||||
displayMode={displayMode}
|
<RightActions
|
||||||
/>
|
transX={transX}
|
||||||
<RightActions
|
favorite={favorite}
|
||||||
transX={transX}
|
width={width}
|
||||||
favorite={favorite}
|
toggleFav={handleToggleFav}
|
||||||
width={width}
|
onHidePress={onHidePress}
|
||||||
toggleFav={handleToggleFav}
|
displayMode={displayMode}
|
||||||
onHidePress={onHidePress}
|
/>
|
||||||
displayMode={displayMode}
|
<Animated.View style={animatedStyles}>
|
||||||
/>
|
<Touch
|
||||||
<Animated.View style={animatedStyles}>
|
onPress={handlePress}
|
||||||
<Touch
|
testID={testID}
|
||||||
onPress={handlePress}
|
style={{
|
||||||
testID={testID}
|
backgroundColor: isFocused ? colors.chatComponentBackground : colors.backgroundColor
|
||||||
style={{
|
}}
|
||||||
backgroundColor: isFocused ? colors.chatComponentBackground : colors.backgroundColor
|
>
|
||||||
}}
|
{children}
|
||||||
>
|
</Touch>
|
||||||
{children}
|
</Animated.View>
|
||||||
</Touch>
|
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</Animated.View>
|
</PanGestureHandler>
|
||||||
</PanGestureHandler>
|
</Animated.View>
|
||||||
</Animated.View>
|
</LongPressGestureHandler>
|
||||||
</LongPressGestureHandler>
|
);
|
||||||
);
|
}
|
||||||
};
|
);
|
||||||
|
|
||||||
export default Touchable;
|
export default Touchable;
|
||||||
|
|
|
@ -1,136 +1,127 @@
|
||||||
import React, { useEffect, useReducer, useRef } from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import { Subscription } from 'rxjs';
|
|
||||||
|
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import { useAppSelector } from '../../lib/hooks';
|
import { useAppSelector } from '../../lib/hooks';
|
||||||
import { getUserPresence } from '../../lib/methods';
|
import { getUserPresence } from '../../lib/methods';
|
||||||
import { isGroupChat } from '../../lib/methods/helpers';
|
import { isGroupChat } from '../../lib/methods/helpers';
|
||||||
import { formatDate } from '../../lib/methods/helpers/room';
|
import { formatDate } from '../../lib/methods/helpers/room';
|
||||||
import { IRoomItemContainerProps } from './interfaces';
|
import { IRoomItemContainerProps, ITouchableRef } from './interfaces';
|
||||||
import RoomItem from './RoomItem';
|
import RoomItem from './RoomItem';
|
||||||
import { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from './styles';
|
import { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from './styles';
|
||||||
|
|
||||||
export { ROW_HEIGHT, ROW_HEIGHT_CONDENSED };
|
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(
|
// When app reconnects, we need to fetch the rendered user's presence
|
||||||
({
|
useEffect(() => {
|
||||||
item,
|
if (connected && isDirect) {
|
||||||
id,
|
getUserPresence(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')}`;
|
|
||||||
}
|
}
|
||||||
if (item.userMentions > 0) {
|
}, [connected]);
|
||||||
accessibilityLabel = `, ${I18n.t('you_were_mentioned')}`;
|
|
||||||
}
|
/**
|
||||||
if (date) {
|
* The component can be recycled by FlashList.
|
||||||
accessibilityLabel = `, ${I18n.t('last_message')} ${date}`;
|
* 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 (
|
const handleOnPress = () => onPress(item);
|
||||||
<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 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;
|
export default RoomItemContainer;
|
||||||
|
|
|
@ -78,7 +78,6 @@ interface IBaseRoomItem extends IRoomItemTouchables {
|
||||||
showAvatar: boolean;
|
showAvatar: boolean;
|
||||||
swipeEnabled: boolean;
|
swipeEnabled: boolean;
|
||||||
autoJoin?: boolean;
|
autoJoin?: boolean;
|
||||||
width: number;
|
|
||||||
username?: string;
|
username?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +115,7 @@ export interface IRoomItemProps extends IBaseRoomItem {
|
||||||
size?: number;
|
size?: number;
|
||||||
sourceType: IOmnichannelSource;
|
sourceType: IOmnichannelSource;
|
||||||
hideMentionStatus?: boolean;
|
hideMentionStatus?: boolean;
|
||||||
|
touchableRef: React.RefObject<ITouchableRef>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ILastMessageProps {
|
export interface ILastMessageProps {
|
||||||
|
@ -127,11 +127,14 @@ export interface ILastMessageProps {
|
||||||
alert: boolean;
|
alert: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ITouchableRef {
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ITouchableProps extends IRoomItemTouchables {
|
export interface ITouchableProps extends IRoomItemTouchables {
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
type: SubscriptionType;
|
type: SubscriptionType;
|
||||||
testID: string;
|
testID: string;
|
||||||
width: number;
|
|
||||||
favorite: boolean;
|
favorite: boolean;
|
||||||
isRead: boolean;
|
isRead: boolean;
|
||||||
rid: string;
|
rid: string;
|
||||||
|
|
|
@ -68,7 +68,7 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
|
||||||
if (file && file.image_url) {
|
if (file && file.image_url) {
|
||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
key={file.image_url}
|
key={index}
|
||||||
file={file}
|
file={file}
|
||||||
showAttachment={showAttachment}
|
showAttachment={showAttachment}
|
||||||
getCustomEmoji={getCustomEmoji}
|
getCustomEmoji={getCustomEmoji}
|
||||||
|
@ -81,7 +81,7 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
|
||||||
if (file && file.audio_url) {
|
if (file && file.audio_url) {
|
||||||
return (
|
return (
|
||||||
<Audio
|
<Audio
|
||||||
key={file.audio_url}
|
key={index}
|
||||||
file={file}
|
file={file}
|
||||||
getCustomEmoji={getCustomEmoji}
|
getCustomEmoji={getCustomEmoji}
|
||||||
isReply={isReply}
|
isReply={isReply}
|
||||||
|
@ -95,7 +95,7 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
|
||||||
if (file.video_url) {
|
if (file.video_url) {
|
||||||
return (
|
return (
|
||||||
<Video
|
<Video
|
||||||
key={file.video_url}
|
key={index}
|
||||||
file={file}
|
file={file}
|
||||||
showAttachment={showAttachment}
|
showAttachment={showAttachment}
|
||||||
getCustomEmoji={getCustomEmoji}
|
getCustomEmoji={getCustomEmoji}
|
||||||
|
|
|
@ -90,8 +90,8 @@ const Fields = React.memo(
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{attachment.fields.map(field => (
|
{attachment.fields.map((field, index) => (
|
||||||
<View key={field.title} style={[styles.fieldContainer, { width: field.short ? '50%' : '100%' }]}>
|
<View key={index} style={[styles.fieldContainer, { width: field.short ? '50%' : '100%' }]}>
|
||||||
<Text testID='collapsibleQuoteTouchableFieldTitle' style={[styles.fieldTitle, { color: themes[theme].bodyText }]}>
|
<Text testID='collapsibleQuoteTouchableFieldTitle' style={[styles.fieldTitle, { color: themes[theme].bodyText }]}>
|
||||||
{field.title}
|
{field.title}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -10,7 +10,7 @@ const Emoji = React.memo(
|
||||||
const parsedContent = content.replace(/^:|:$/g, '');
|
const parsedContent = content.replace(/^:|:$/g, '');
|
||||||
const emoji = getCustomEmoji(parsedContent);
|
const emoji = getCustomEmoji(parsedContent);
|
||||||
if (emoji) {
|
if (emoji) {
|
||||||
return <CustomEmoji key={content} style={customEmojiStyle} emoji={emoji} />;
|
return <CustomEmoji style={customEmojiStyle} emoji={emoji} />;
|
||||||
}
|
}
|
||||||
return <Text style={standardEmojiStyle}>{shortnameToUnicode(content)}</Text>;
|
return <Text style={standardEmojiStyle}>{shortnameToUnicode(content)}</Text>;
|
||||||
},
|
},
|
||||||
|
|
|
@ -53,7 +53,6 @@ const Reaction = React.memo(({ reaction, getCustomEmoji, theme }: IMessageReacti
|
||||||
<Touchable
|
<Touchable
|
||||||
onPress={() => onReactionPress(reaction.emoji)}
|
onPress={() => onReactionPress(reaction.emoji)}
|
||||||
onLongPress={onReactionLongPress}
|
onLongPress={onReactionLongPress}
|
||||||
key={reaction.emoji}
|
|
||||||
testID={`message-reaction-${reaction.emoji}`}
|
testID={`message-reaction-${reaction.emoji}`}
|
||||||
style={[
|
style={[
|
||||||
styles.reactionButton,
|
styles.reactionButton,
|
||||||
|
@ -83,8 +82,8 @@ const Reactions = React.memo(({ reactions, getCustomEmoji }: IMessageReactions)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<View style={styles.reactionsContainer}>
|
<View style={styles.reactionsContainer}>
|
||||||
{reactions.map(reaction => (
|
{reactions.map((reaction, index) => (
|
||||||
<Reaction key={reaction.emoji} reaction={reaction} getCustomEmoji={getCustomEmoji} theme={theme} />
|
<Reaction key={index} reaction={reaction} getCustomEmoji={getCustomEmoji} theme={theme} />
|
||||||
))}
|
))}
|
||||||
<AddReaction theme={theme} />
|
<AddReaction theme={theme} />
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -184,8 +184,8 @@ const Fields = React.memo(
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.fieldsContainer}>
|
<View style={styles.fieldsContainer}>
|
||||||
{attachment.fields.map(field => (
|
{attachment.fields.map((field, index) => (
|
||||||
<View key={field.title} style={[styles.fieldContainer, { width: field.short ? '50%' : '100%' }]}>
|
<View key={index} style={[styles.fieldContainer, { width: field.short ? '50%' : '100%' }]}>
|
||||||
<Text style={[styles.fieldTitle, { color: themes[theme].bodyText }]}>{field.title}</Text>
|
<Text style={[styles.fieldTitle, { color: themes[theme].bodyText }]}>{field.title}</Text>
|
||||||
<Markdown msg={field?.value || ''} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
|
<Markdown msg={field?.value || ''} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -141,7 +141,7 @@ const Urls = React.memo(
|
||||||
return null;
|
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)
|
(oldProps, newProps) => dequal(oldProps.urls, newProps.urls)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Keyboard, ViewStyle } from 'react-native';
|
import { Keyboard } from 'react-native';
|
||||||
import { Subscription } from 'rxjs';
|
|
||||||
|
|
||||||
import Message from './Message';
|
import Message from './Message';
|
||||||
import MessageContext from './Context';
|
import MessageContext from './Context';
|
||||||
|
@ -8,64 +7,11 @@ import { debounce } from '../../lib/methods/helpers';
|
||||||
import { getMessageTranslation } from './utils';
|
import { getMessageTranslation } from './utils';
|
||||||
import { TSupportedThemes, withTheme } from '../../theme';
|
import { TSupportedThemes, withTheme } from '../../theme';
|
||||||
import openLink from '../../lib/methods/helpers/openLink';
|
import openLink from '../../lib/methods/helpers/openLink';
|
||||||
import { IAttachment, TAnyMessageModel, TGetCustomEmoji } from '../../definitions';
|
import { IAttachment } from '../../definitions';
|
||||||
import { IRoomInfoParam } from '../../views/SearchMessagesView';
|
|
||||||
import { E2E_MESSAGE_TYPE, E2E_STATUS, messagesStatus } from '../../lib/constants';
|
import { E2E_MESSAGE_TYPE, E2E_STATUS, messagesStatus } from '../../lib/constants';
|
||||||
|
import { IMessageContainerProps, TAnyMessageContainerState } from './interfaces';
|
||||||
|
|
||||||
interface IMessageContainerProps {
|
class MessageContainer extends React.Component<IMessageContainerProps, TAnyMessageContainerState> {
|
||||||
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> {
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
getCustomEmoji: () => null,
|
getCustomEmoji: () => null,
|
||||||
onLongPress: () => {},
|
onLongPress: () => {},
|
||||||
|
@ -79,45 +25,6 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
|
||||||
|
|
||||||
state = { isManualUnignored: false };
|
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 = () => {
|
onPressAction = () => {
|
||||||
const { closeEmojiAndAction } = this.props;
|
const { closeEmojiAndAction } = this.props;
|
||||||
|
|
||||||
|
@ -227,11 +134,11 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
previousItem &&
|
previousItem &&
|
||||||
// @ts-ignore TODO: IMessage vs IMessageFromServer non-sense
|
// @ts-ignore TODO: TAnyMessage vs TAnyMessageFromServer non-sense
|
||||||
previousItem.ts.toDateString() === item.ts.toDateString() &&
|
previousItem.ts.toDateString() === item.ts.toDateString() &&
|
||||||
previousItem.u.username === item.u.username &&
|
previousItem.u.username === item.u.username &&
|
||||||
!(previousItem.groupable === false || item.groupable === false || broadcast === true) &&
|
!(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 &&
|
item.ts - previousItem.ts < Message_GroupingPeriod * 1000 &&
|
||||||
previousItem.tmid === item.tmid &&
|
previousItem.tmid === item.tmid &&
|
||||||
item.t !== 'rm' &&
|
item.t !== 'rm' &&
|
||||||
|
@ -407,8 +314,8 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
|
||||||
threadBadgeColor,
|
threadBadgeColor,
|
||||||
toggleFollowThread,
|
toggleFollowThread,
|
||||||
replies
|
replies
|
||||||
}}>
|
}}
|
||||||
{/* @ts-ignore*/}
|
>
|
||||||
<Message
|
<Message
|
||||||
id={id}
|
id={id}
|
||||||
msg={message}
|
msg={message}
|
||||||
|
|
|
@ -1,11 +1,65 @@
|
||||||
import { MarkdownAST } from '@rocket.chat/message-parser';
|
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 { ImageStyle } from 'react-native-fast-image';
|
||||||
|
|
||||||
import { IUserChannel } from '../markdown/interfaces';
|
import { IUserChannel } from '../markdown/interfaces';
|
||||||
import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
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 { 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 {
|
export interface IMessageAttachments {
|
||||||
attachments?: IAttachment[];
|
attachments?: IAttachment[];
|
||||||
|
@ -44,7 +98,6 @@ export interface IMessageCallButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IMessageContent {
|
export interface IMessageContent {
|
||||||
_id: string;
|
|
||||||
isTemp: boolean;
|
isTemp: boolean;
|
||||||
isInfo: string | boolean;
|
isInfo: string | boolean;
|
||||||
tmid?: string;
|
tmid?: string;
|
||||||
|
@ -119,7 +172,6 @@ export interface IMessage extends IMessageRepliedThread, IMessageInner, IMessage
|
||||||
hasError: boolean;
|
hasError: boolean;
|
||||||
style: any;
|
style: any;
|
||||||
// style: ViewStyle;
|
// style: ViewStyle;
|
||||||
onLongPress?: (item: TAnyMessageModel) => void;
|
|
||||||
isReadReceiptEnabled?: boolean;
|
isReadReceiptEnabled?: boolean;
|
||||||
unread?: boolean;
|
unread?: boolean;
|
||||||
isIgnored: boolean;
|
isIgnored: boolean;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* eslint-disable complexity */
|
/* eslint-disable complexity */
|
||||||
import { MessageTypesValues, TMessageModel } from '../../definitions/IMessage';
|
import { MessageTypesValues, TAnyMessage } from '../../definitions/IMessage';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import { DISCUSSION } from './constants';
|
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) {
|
if (!autoTranslateLanguage) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,18 @@ import { MarkdownAST } from '@rocket.chat/message-parser';
|
||||||
import { MessageTypeLoad } from '../lib/constants';
|
import { MessageTypeLoad } from '../lib/constants';
|
||||||
import { IAttachment } from './IAttachment';
|
import { IAttachment } from './IAttachment';
|
||||||
import { IReaction } from './IReaction';
|
import { IReaction } from './IReaction';
|
||||||
import { TThreadMessageModel } from './IThreadMessage';
|
import { IThreadMessage } from './IThreadMessage';
|
||||||
import { TThreadModel } from './IThread';
|
import { IThread } from './IThread';
|
||||||
import { IUrl, IUrlFromServer } from './IUrl';
|
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 {
|
export interface IUserMessage {
|
||||||
_id: string;
|
_id: string;
|
||||||
|
@ -139,9 +146,12 @@ export interface IMessage extends IMessageFromServer {
|
||||||
editedAt?: string | Date;
|
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;
|
export type TTypeMessages = IMessageFromServer | ILoadMoreMessage | IMessage;
|
||||||
|
|
||||||
// Read receipts to ReadReceiptView and chat.getMessageReadReceipts
|
// Read receipts to ReadReceiptView and chat.getMessageReadReceipts
|
||||||
|
|
|
@ -96,7 +96,6 @@ export interface ISubscription {
|
||||||
avatarETag?: string;
|
avatarETag?: string;
|
||||||
teamId?: string;
|
teamId?: string;
|
||||||
teamMain?: boolean;
|
teamMain?: boolean;
|
||||||
unsubscribe: () => Promise<any>;
|
|
||||||
separator?: boolean;
|
separator?: boolean;
|
||||||
onHold?: boolean;
|
onHold?: boolean;
|
||||||
source?: IOmnichannelSource;
|
source?: IOmnichannelSource;
|
||||||
|
@ -108,7 +107,10 @@ export interface ISubscription {
|
||||||
uploads: RelationModified<TUploadModel>;
|
uploads: RelationModified<TUploadModel>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TSubscriptionModel = ISubscription & Model;
|
export type TSubscriptionModel = ISubscription &
|
||||||
|
Model & {
|
||||||
|
asPlain: () => ISubscription;
|
||||||
|
};
|
||||||
export type TSubscription = TSubscriptionModel | ISubscription;
|
export type TSubscription = TSubscriptionModel | ISubscription;
|
||||||
|
|
||||||
// https://github.com/RocketChat/Rocket.Chat/blob/a88a96fcadd925b678ff27ada37075e029f78b5e/definition/ISubscription.ts#L8
|
// https://github.com/RocketChat/Rocket.Chat/blob/a88a96fcadd925b678ff27ada37075e029f78b5e/definition/ISubscription.ts#L8
|
||||||
|
|
|
@ -38,4 +38,7 @@ export interface IThread extends IMessage {
|
||||||
draftMessage?: string;
|
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;
|
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;
|
@json('md', sanitizer) md;
|
||||||
|
|
||||||
@field('comment') comment;
|
@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;
|
@field('on_hold') onHold;
|
||||||
|
|
||||||
@json('source', sanitizer) source;
|
@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('e2e') e2e;
|
||||||
|
|
||||||
@field('draft_message') draftMessage;
|
@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('draft_message') draftMessage;
|
||||||
|
|
||||||
@field('e2e') e2e;
|
@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 log from './helpers/log';
|
||||||
import { TMessageModel, TSubscriptionModel } from '../../definitions';
|
import { IMessage, TSubscriptionModel } from '../../definitions';
|
||||||
import { store } from '../store/auxStore';
|
import { store } from '../store/auxStore';
|
||||||
import { isGroupChat } from './helpers';
|
import { isGroupChat } from './helpers';
|
||||||
import { getRoom } from './getRoom';
|
import { getRoom } from './getRoom';
|
||||||
|
|
||||||
type TRoomType = 'p' | 'c' | 'd';
|
type TRoomType = 'p' | 'c' | 'd';
|
||||||
|
|
||||||
export async function getPermalinkMessage(message: TMessageModel): Promise<string | null> {
|
export async function getPermalinkMessage(message: IMessage): Promise<string | null> {
|
||||||
if (!message.subscription) return null;
|
|
||||||
let room: TSubscriptionModel;
|
let room: TSubscriptionModel;
|
||||||
try {
|
try {
|
||||||
room = await getRoom(message.subscription.id);
|
room = await getRoom(message.rid);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||||
import { Model } from '@nozbe/watermelondb';
|
import { Model } from '@nozbe/watermelondb';
|
||||||
|
|
||||||
|
import { getMessageById } from '../database/services/Message';
|
||||||
import database from '../database';
|
import database from '../database';
|
||||||
import log from './helpers/log';
|
import log from './helpers/log';
|
||||||
import { random } from './helpers';
|
import { random } from './helpers';
|
||||||
|
@ -66,14 +67,17 @@ async function sendMessageCall(message: any) {
|
||||||
export async function resendMessage(message: TMessageModel, tmid?: string) {
|
export async function resendMessage(message: TMessageModel, tmid?: string) {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
try {
|
try {
|
||||||
await db.write(async () => {
|
const messageRecord = await getMessageById(message.id);
|
||||||
await message.update(m => {
|
if (messageRecord) {
|
||||||
m.status = messagesStatus.TEMP;
|
await db.write(async () => {
|
||||||
|
await messageRecord.update(m => {
|
||||||
|
m.status = messagesStatus.TEMP;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
const m = await Encryption.encryptMessage({
|
const m = await Encryption.encryptMessage({
|
||||||
_id: message.id,
|
_id: message.id,
|
||||||
rid: message.subscription ? message.subscription.id : '',
|
rid: message.rid,
|
||||||
msg: message.msg,
|
msg: message.msg,
|
||||||
...(tmid && { tmid })
|
...(tmid && { tmid })
|
||||||
} as IMessage);
|
} as IMessage);
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { addUserTyping, clearUserTyping, removeUserTyping } from '../../../actio
|
||||||
import { debounce } from '../helpers';
|
import { debounce } from '../helpers';
|
||||||
import { subscribeRoom, unsubscribeRoom } from '../../../actions/room';
|
import { subscribeRoom, unsubscribeRoom } from '../../../actions/room';
|
||||||
import { Encryption } from '../../encryption';
|
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 { IDDPMessage } from '../../../definitions/IDDPMessage';
|
||||||
import sdk from '../../services/sdk';
|
import sdk from '../../services/sdk';
|
||||||
import { readMessages } from '../readMessages';
|
import { readMessages } from '../readMessages';
|
||||||
|
@ -33,7 +33,7 @@ export default class RoomSubscription {
|
||||||
private _threadsBatch: { [key: string]: TThreadModel };
|
private _threadsBatch: { [key: string]: TThreadModel };
|
||||||
private threadMessagesBatch: {};
|
private threadMessagesBatch: {};
|
||||||
private _threadMessagesBatch: { [key: string]: TThreadMessageModel };
|
private _threadMessagesBatch: { [key: string]: TThreadMessageModel };
|
||||||
private promises?: Promise<TSubscriptionModel[]>;
|
private promises?: Promise<any>;
|
||||||
private connectedListener?: Promise<any>;
|
private connectedListener?: Promise<any>;
|
||||||
private disconnectedListener?: Promise<any>;
|
private disconnectedListener?: Promise<any>;
|
||||||
private notifyRoomListener?: Promise<any>;
|
private notifyRoomListener?: Promise<any>;
|
||||||
|
@ -79,7 +79,7 @@ export default class RoomSubscription {
|
||||||
if (this.promises) {
|
if (this.promises) {
|
||||||
try {
|
try {
|
||||||
const subscriptions = (await this.promises) || [];
|
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) {
|
} catch (e) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,7 @@ const Drawer = createDrawerNavigator<MasterDetailDrawerParamList>();
|
||||||
const DrawerNavigator = React.memo(() => (
|
const DrawerNavigator = React.memo(() => (
|
||||||
<Drawer.Navigator
|
<Drawer.Navigator
|
||||||
screenOptions={{ drawerType: 'permanent', headerShown: false, drawerStyle: { ...drawerStyle } }}
|
screenOptions={{ drawerType: 'permanent', headerShown: false, drawerStyle: { ...drawerStyle } }}
|
||||||
|
// @ts-ignore
|
||||||
drawerContent={({ navigation, state }) => <RoomsListView navigation={navigation} state={state} />}
|
drawerContent={({ navigation, state }) => <RoomsListView navigation={navigation} state={state} />}
|
||||||
>
|
>
|
||||||
<Drawer.Screen name='ChatsStackNavigator' component={ChatsStackNavigator} />
|
<Drawer.Screen name='ChatsStackNavigator' component={ChatsStackNavigator} />
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { IItem } from '../views/TeamChannelsView';
|
||||||
import { IOptionsField } from '../views/NotificationPreferencesView/options';
|
import { IOptionsField } from '../views/NotificationPreferencesView/options';
|
||||||
import { IServer } from '../definitions/IServer';
|
import { IServer } from '../definitions/IServer';
|
||||||
import { IAttachment } from '../definitions/IAttachment';
|
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 { ISubscription, SubscriptionType, TSubscriptionModel } from '../definitions/ISubscription';
|
||||||
import { ICannedResponse } from '../definitions/ICannedResponse';
|
import { ICannedResponse } from '../definitions/ICannedResponse';
|
||||||
import { TDataSelect } from '../definitions/IDataSelect';
|
import { TDataSelect } from '../definitions/IDataSelect';
|
||||||
|
@ -37,7 +37,7 @@ export type ChatsStackParamList = {
|
||||||
roomUserId?: string | null;
|
roomUserId?: string | null;
|
||||||
usedCannedResponse?: string;
|
usedCannedResponse?: string;
|
||||||
status?: string;
|
status?: string;
|
||||||
replyInDM?: TAnyMessageModel;
|
replyInDM?: TAnyMessage;
|
||||||
}
|
}
|
||||||
| undefined; // Navigates back to RoomView already on stack
|
| undefined; // Navigates back to RoomView already on stack
|
||||||
RoomActionsView: {
|
RoomActionsView: {
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {
|
||||||
SubscriptionType,
|
SubscriptionType,
|
||||||
IAttachment,
|
IAttachment,
|
||||||
IMessage,
|
IMessage,
|
||||||
TAnyMessageModel,
|
TAnyMessage,
|
||||||
IUrl,
|
IUrl,
|
||||||
TGetCustomEmoji,
|
TGetCustomEmoji,
|
||||||
ICustomEmoji
|
ICustomEmoji
|
||||||
|
@ -160,7 +160,7 @@ class MessagesView extends React.Component<IMessagesViewProps, IMessagesViewStat
|
||||||
|
|
||||||
defineMessagesViewContent = (name: string) => {
|
defineMessagesViewContent = (name: string) => {
|
||||||
const { user, baseUrl, theme, useRealName } = this.props;
|
const { user, baseUrl, theme, useRealName } = this.props;
|
||||||
const renderItemCommonProps = (item: TAnyMessageModel) => ({
|
const renderItemCommonProps = (item: TAnyMessage) => ({
|
||||||
item,
|
item,
|
||||||
baseUrl,
|
baseUrl,
|
||||||
user,
|
user,
|
||||||
|
@ -219,7 +219,7 @@ class MessagesView extends React.Component<IMessagesViewProps, IMessagesViewStat
|
||||||
},
|
},
|
||||||
noDataMsg: I18n.t('No_mentioned_messages'),
|
noDataMsg: I18n.t('No_mentioned_messages'),
|
||||||
testID: 'mentioned-messages-view',
|
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 Messages Screen
|
||||||
Starred: {
|
Starred: {
|
||||||
|
@ -230,7 +230,7 @@ class MessagesView extends React.Component<IMessagesViewProps, IMessagesViewStat
|
||||||
},
|
},
|
||||||
noDataMsg: I18n.t('No_starred_messages'),
|
noDataMsg: I18n.t('No_starred_messages'),
|
||||||
testID: 'starred-messages-view',
|
testID: 'starred-messages-view',
|
||||||
renderItem: (item: TAnyMessageModel) => (
|
renderItem: (item: TAnyMessage) => (
|
||||||
<Message {...renderItemCommonProps(item)} msg={item.msg} onLongPress={() => this.onLongPress(item)} theme={theme} />
|
<Message {...renderItemCommonProps(item)} msg={item.msg} onLongPress={() => this.onLongPress(item)} theme={theme} />
|
||||||
),
|
),
|
||||||
action: (message: IMessage) => ({
|
action: (message: IMessage) => ({
|
||||||
|
@ -249,7 +249,7 @@ class MessagesView extends React.Component<IMessagesViewProps, IMessagesViewStat
|
||||||
},
|
},
|
||||||
noDataMsg: I18n.t('No_pinned_messages'),
|
noDataMsg: I18n.t('No_pinned_messages'),
|
||||||
testID: 'pinned-messages-view',
|
testID: 'pinned-messages-view',
|
||||||
renderItem: (item: TAnyMessageModel) => (
|
renderItem: (item: TAnyMessage) => (
|
||||||
<Message {...renderItemCommonProps(item)} msg={item.msg} onLongPress={() => this.onLongPress(item)} theme={theme} />
|
<Message {...renderItemCommonProps(item)} msg={item.msg} onLongPress={() => this.onLongPress(item)} theme={theme} />
|
||||||
),
|
),
|
||||||
action: () => ({ title: I18n.t('Unpin'), icon: 'pin', onPress: this.handleActionPress }),
|
action: () => ({ title: I18n.t('Unpin'), icon: 'pin', onPress: this.handleActionPress }),
|
||||||
|
|
|
@ -1,42 +1,32 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FlatListProps, StyleSheet } from 'react-native';
|
import { StyleSheet } from 'react-native';
|
||||||
import { FlatList } from 'react-native-gesture-handler';
|
import { FlashList, FlashListProps } from '@shopify/flash-list';
|
||||||
import Animated from 'react-native-reanimated';
|
import Animated from 'react-native-reanimated';
|
||||||
|
|
||||||
import { isIOS } from '../../../lib/methods/helpers';
|
|
||||||
import scrollPersistTaps from '../../../lib/methods/helpers/scrollPersistTaps';
|
import scrollPersistTaps from '../../../lib/methods/helpers/scrollPersistTaps';
|
||||||
|
|
||||||
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
|
const AnimatedFlashList = Animated.createAnimatedComponent(FlashList);
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
list: {
|
|
||||||
flex: 1
|
|
||||||
},
|
|
||||||
contentContainer: {
|
contentContainer: {
|
||||||
paddingTop: 10
|
paddingTop: 8
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TListRef = React.RefObject<FlatList & { getNode: () => FlatList }>;
|
export type IListProps = FlashListProps<any>;
|
||||||
|
|
||||||
export interface IListProps extends FlatListProps<any> {
|
|
||||||
listRef: TListRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
const List = ({ listRef, ...props }: IListProps) => (
|
const List = ({ listRef, ...props }: IListProps) => (
|
||||||
<AnimatedFlatList
|
<AnimatedFlashList
|
||||||
testID='room-view-messages'
|
testID='room-view-messages'
|
||||||
ref={listRef}
|
ref={listRef}
|
||||||
keyExtractor={(item: any) => item.id}
|
keyExtractor={(item: any) => item.id}
|
||||||
|
// @ts-ignore
|
||||||
contentContainerStyle={styles.contentContainer}
|
contentContainerStyle={styles.contentContainer}
|
||||||
style={styles.list}
|
inverted
|
||||||
inverted={isIOS}
|
estimatedItemSize={48}
|
||||||
removeClippedSubviews={isIOS}
|
|
||||||
initialNumToRender={7}
|
|
||||||
onEndReachedThreshold={0.5}
|
onEndReachedThreshold={0.5}
|
||||||
maxToRenderPerBatch={5}
|
|
||||||
windowSize={10}
|
|
||||||
{...props}
|
{...props}
|
||||||
{...scrollPersistTaps}
|
{...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 { dequal } from 'dequal';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import React from 'react';
|
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 { event, Value } from 'react-native-reanimated';
|
||||||
import { Observable, Subscription } from 'rxjs';
|
import { Observable, Subscription } from 'rxjs';
|
||||||
|
|
||||||
import ActivityIndicator from '../../../containers/ActivityIndicator';
|
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 database from '../../../lib/database';
|
||||||
import { compareServerVersion, debounce } from '../../../lib/methods/helpers';
|
import { animateNextTransition, compareServerVersion, debounce } from '../../../lib/methods/helpers';
|
||||||
import { animateNextTransition } from '../../../lib/methods/helpers/layoutAnimation';
|
// import { animateNextTransition } from '../../../lib/methods/helpers/layoutAnimation';
|
||||||
import log from '../../../lib/methods/helpers/log';
|
import log from '../../../lib/methods/helpers/log';
|
||||||
import EmptyRoom from '../EmptyRoom';
|
import EmptyRoom from '../EmptyRoom';
|
||||||
|
// @ts-ignore
|
||||||
import List, { IListProps, TListRef } from './List';
|
import List, { IListProps, TListRef } from './List';
|
||||||
import NavBottomFAB from './NavBottomFAB';
|
import NavBottomFAB from './NavBottomFAB';
|
||||||
import { loadMissedMessages, loadThreadMessages } from '../../../lib/methods';
|
import { loadMissedMessages, loadThreadMessages } from '../../../lib/methods';
|
||||||
import { Services } from '../../../lib/services';
|
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 QUERY_SIZE = 50;
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
inverted: {
|
|
||||||
...Platform.select({
|
|
||||||
android: {
|
|
||||||
scaleY: -1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const onScroll = ({ y }: { y: Value<number> }) =>
|
const onScroll = ({ y }: { y: Value<number> }) =>
|
||||||
event(
|
event(
|
||||||
[
|
[
|
||||||
|
@ -60,7 +53,7 @@ export interface IListContainerProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IListContainerState {
|
interface IListContainerState {
|
||||||
messages: TAnyMessageModel[];
|
messages: TMessage[];
|
||||||
refreshing: boolean;
|
refreshing: boolean;
|
||||||
highlightedMessage: string | null;
|
highlightedMessage: string | null;
|
||||||
}
|
}
|
||||||
|
@ -104,30 +97,6 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
||||||
console.timeEnd(`${this.constructor.name} mount`);
|
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) {
|
componentDidUpdate(prevProps: IListContainerProps) {
|
||||||
const { hideSystemMessages } = this.props;
|
const { hideSystemMessages } = this.props;
|
||||||
if (!dequal(hideSystemMessages, prevProps.hideSystemMessages)) {
|
if (!dequal(hideSystemMessages, prevProps.hideSystemMessages)) {
|
||||||
|
@ -141,7 +110,7 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
||||||
this.unsubscribeFocus();
|
this.unsubscribeFocus();
|
||||||
}
|
}
|
||||||
this.clearHighlightedMessageTimeout();
|
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
|
// clears previous highlighted message timeout, if exists
|
||||||
|
@ -154,7 +123,7 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
||||||
|
|
||||||
query = async () => {
|
query = async () => {
|
||||||
this.count += QUERY_SIZE;
|
this.count += QUERY_SIZE;
|
||||||
const { rid, tmid, showMessageInMainThread, serverVersion } = this.props;
|
const { rid, tmid, showMessageInMainThread, serverVersion, listRef } = this.props;
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
|
|
||||||
// handle servers with version < 3.0.0
|
// handle servers with version < 3.0.0
|
||||||
|
@ -163,6 +132,8 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
||||||
hideSystemMessages = [];
|
hideSystemMessages = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const columnsToObserve = ['_updated_at', 'status'];
|
||||||
|
|
||||||
if (tmid) {
|
if (tmid) {
|
||||||
try {
|
try {
|
||||||
this.thread = await db.get('threads').find(tmid);
|
this.thread = await db.get('threads').find(tmid);
|
||||||
|
@ -172,7 +143,7 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
||||||
this.messagesObservable = db
|
this.messagesObservable = db
|
||||||
.get('thread_messages')
|
.get('thread_messages')
|
||||||
.query(Q.where('rid', tmid), Q.experimentalSortBy('ts', Q.desc), Q.experimentalSkip(0), Q.experimentalTake(this.count))
|
.query(Q.where('rid', tmid), Q.experimentalSortBy('ts', Q.desc), Q.experimentalSkip(0), Q.experimentalTake(this.count))
|
||||||
.observe();
|
.observeWithColumns(columnsToObserve);
|
||||||
} else if (rid) {
|
} else if (rid) {
|
||||||
const whereClause = [
|
const whereClause = [
|
||||||
Q.where('rid', rid),
|
Q.where('rid', rid),
|
||||||
|
@ -186,14 +157,22 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
||||||
this.messagesObservable = db
|
this.messagesObservable = db
|
||||||
.get('messages')
|
.get('messages')
|
||||||
.query(...whereClause)
|
.query(...whereClause)
|
||||||
.observe();
|
.observeWithColumns(columnsToObserve);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rid) {
|
if (rid) {
|
||||||
this.unsubscribeMessages();
|
this.unsubscribeMessages();
|
||||||
this.messagesSubscription = this.messagesObservable?.subscribe(messages => {
|
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) {
|
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
|
* hide system message is enabled
|
||||||
*/
|
*/
|
||||||
if (compareServerVersion(serverVersion, 'lowerThan', '3.16.0') || hideSystemMessages.length) {
|
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) {
|
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 {
|
} else {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.state.messages = messages;
|
this.state.messages = data;
|
||||||
}
|
}
|
||||||
// TODO: move it away from here
|
// TODO: move it away from here
|
||||||
this.readThreads();
|
this.readThreads();
|
||||||
|
@ -233,7 +219,13 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
||||||
}
|
}
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
onEndReached = () => this.query();
|
onEndReached = () => {
|
||||||
|
const { messages } = this.state;
|
||||||
|
if (messages.length < this.count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.query();
|
||||||
|
};
|
||||||
|
|
||||||
onRefresh = () =>
|
onRefresh = () =>
|
||||||
this.setState({ refreshing: true }, async () => {
|
this.setState({ refreshing: true }, async () => {
|
||||||
|
@ -255,20 +247,13 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
||||||
this.setState({ refreshing: false });
|
this.setState({ refreshing: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
update = () => {
|
|
||||||
if (this.animated) {
|
|
||||||
animateNextTransition();
|
|
||||||
}
|
|
||||||
this.forceUpdate();
|
|
||||||
};
|
|
||||||
|
|
||||||
unsubscribeMessages = () => {
|
unsubscribeMessages = () => {
|
||||||
if (this.messagesSubscription && this.messagesSubscription.unsubscribe) {
|
if (this.messagesSubscription && this.messagesSubscription.unsubscribe) {
|
||||||
this.messagesSubscription.unsubscribe();
|
this.messagesSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getLastMessage = (): TMessageModel | TThreadMessageModel | null => {
|
getLastMessage = (): TAnyMessage | null => {
|
||||||
const { messages } = this.state;
|
const { messages } = this.state;
|
||||||
if (messages.length > 0) {
|
if (messages.length > 0) {
|
||||||
return messages[0];
|
return messages[0];
|
||||||
|
@ -353,7 +338,7 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
||||||
renderItem: FlatListProps<any>['renderItem'] = ({ item, index }) => {
|
renderItem: FlatListProps<any>['renderItem'] = ({ item, index }) => {
|
||||||
const { messages, highlightedMessage } = this.state;
|
const { messages, highlightedMessage } = this.state;
|
||||||
const { renderRow } = this.props;
|
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 }) => {
|
onViewableItemsChanged: FlatListProps<any>['onViewableItemsChanged'] = ({ viewableItems }) => {
|
||||||
|
@ -361,28 +346,37 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
console.count(`${this.constructor.name}.render calls`);
|
const { rid, tmid, listRef, loading } = this.props;
|
||||||
const { rid, tmid, listRef } = this.props;
|
const { messages, refreshing, highlightedMessage } = this.state;
|
||||||
const { messages, refreshing } = this.state;
|
console.count(`${this.constructor.name}.render: ${tmid || rid} calls`);
|
||||||
return (
|
return (
|
||||||
<>
|
// FIXME: added context directly so we don't have to touch on withTheme's ref
|
||||||
<EmptyRoom rid={rid} length={messages.length} mounted={this.mounted} />
|
<ThemeContext.Consumer>
|
||||||
<RefreshControl refreshing={refreshing} onRefresh={this.onRefresh}>
|
{({ theme }) => (
|
||||||
<List
|
<>
|
||||||
onScroll={this.onScroll}
|
<EmptyRoom rid={rid} length={messages.length} mounted={this.mounted} />
|
||||||
scrollEventThrottle={16}
|
<List
|
||||||
listRef={listRef}
|
onScroll={this.onScroll}
|
||||||
data={messages}
|
scrollEventThrottle={16}
|
||||||
renderItem={this.renderItem}
|
listRef={listRef}
|
||||||
onEndReached={this.onEndReached}
|
data={messages}
|
||||||
ListFooterComponent={this.renderFooter}
|
extraData={{ loading, highlightedMessage }}
|
||||||
onScrollToIndexFailed={this.handleScrollToIndexFailed}
|
// @ts-ignore
|
||||||
onViewableItemsChanged={this.onViewableItemsChanged}
|
renderItem={this.renderItem}
|
||||||
viewabilityConfig={this.viewabilityConfig}
|
onEndReached={this.onEndReached}
|
||||||
/>
|
ListFooterComponent={this.renderFooter}
|
||||||
</RefreshControl>
|
onScrollToIndexFailed={this.handleScrollToIndexFailed}
|
||||||
<NavBottomFAB y={this.y} onPress={this.jumpToBottom} isThread={!!tmid} />
|
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,
|
ISubscription,
|
||||||
IVisitor,
|
IVisitor,
|
||||||
SubscriptionType,
|
SubscriptionType,
|
||||||
TAnyMessageModel,
|
TAnyMessage,
|
||||||
TMessageModel,
|
TMessageModel,
|
||||||
TSubscriptionModel,
|
TSubscriptionModel,
|
||||||
TThreadModel,
|
TThreadModel,
|
||||||
|
@ -78,7 +78,7 @@ import {
|
||||||
TGetCustomEmoji
|
TGetCustomEmoji
|
||||||
} from '../../definitions';
|
} from '../../definitions';
|
||||||
import { E2E_MESSAGE_TYPE, E2E_STATUS, MESSAGE_TYPE_ANY_LOAD, MessageTypeLoad, themes } from '../../lib/constants';
|
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 { ModalStackParamList } from '../../stacks/MasterDetailStack/types';
|
||||||
import {
|
import {
|
||||||
callJitsi,
|
callJitsi,
|
||||||
|
@ -101,6 +101,7 @@ import {
|
||||||
import { Services } from '../../lib/services';
|
import { Services } from '../../lib/services';
|
||||||
import { withActionSheet, IActionSheetProvider } from '../../containers/ActionSheet';
|
import { withActionSheet, IActionSheetProvider } from '../../containers/ActionSheet';
|
||||||
import { goRoom, TGoRoomItem } from '../../lib/methods/helpers/goRoom';
|
import { goRoom, TGoRoomItem } from '../../lib/methods/helpers/goRoom';
|
||||||
|
import { TMessage } from './definitions';
|
||||||
|
|
||||||
type TStateAttrsUpdate = keyof IRoomViewState;
|
type TStateAttrsUpdate = keyof IRoomViewState;
|
||||||
|
|
||||||
|
@ -193,7 +194,7 @@ interface IRoomViewState {
|
||||||
member: any;
|
member: any;
|
||||||
lastOpen: Date | null;
|
lastOpen: Date | null;
|
||||||
reactionsModalVisible: boolean;
|
reactionsModalVisible: boolean;
|
||||||
selectedMessage?: TAnyMessageModel;
|
selectedMessage?: TAnyMessage;
|
||||||
canAutoTranslate: boolean;
|
canAutoTranslate: boolean;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
editing: boolean;
|
editing: boolean;
|
||||||
|
@ -204,6 +205,12 @@ interface IRoomViewState {
|
||||||
roomUserId?: string | null;
|
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> {
|
class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
private rid?: string;
|
private rid?: string;
|
||||||
private t?: string;
|
private t?: string;
|
||||||
|
@ -213,7 +220,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
private messagebox: React.RefObject<MessageBoxType>;
|
private messagebox: React.RefObject<MessageBoxType>;
|
||||||
private list: React.RefObject<ListContainerType>;
|
private list: React.RefObject<ListContainerType>;
|
||||||
private joinCode: React.RefObject<IJoinCode>;
|
private joinCode: React.RefObject<IJoinCode>;
|
||||||
private flatList: TListRef;
|
private flatList: any;
|
||||||
private mounted: boolean;
|
private mounted: boolean;
|
||||||
private offset = 0;
|
private offset = 0;
|
||||||
private subObserveQuery?: Subscription;
|
private subObserveQuery?: Subscription;
|
||||||
|
@ -225,7 +232,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
private retryFindTimeout?: ReturnType<typeof setTimeout>;
|
private retryFindTimeout?: ReturnType<typeof setTimeout>;
|
||||||
private messageErrorActions?: IMessageErrorActions | null;
|
private messageErrorActions?: IMessageErrorActions | null;
|
||||||
private messageActions?: IMessageActions | null;
|
private messageActions?: IMessageActions | null;
|
||||||
private replyInDM?: TAnyMessageModel;
|
private replyInDM?: TAnyMessage;
|
||||||
// Type of InteractionManager.runAfterInteractions
|
// Type of InteractionManager.runAfterInteractions
|
||||||
private didMountInteraction?: {
|
private didMountInteraction?: {
|
||||||
then: (onfulfilled?: (() => any) | undefined, onrejected?: (() => any) | undefined) => Promise<any>;
|
then: (onfulfilled?: (() => any) | undefined, onrejected?: (() => any) | undefined) => Promise<any>;
|
||||||
|
@ -264,7 +271,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
this.state = {
|
this.state = {
|
||||||
joined: true,
|
joined: true,
|
||||||
room,
|
room,
|
||||||
roomUpdate: {},
|
roomUpdate: fetchRoomUpdate(room),
|
||||||
member: {},
|
member: {},
|
||||||
lastOpen: null,
|
lastOpen: null,
|
||||||
reactionsModalVisible: false,
|
reactionsModalVisible: false,
|
||||||
|
@ -286,7 +293,8 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
|
|
||||||
this.setHeader();
|
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 :(
|
// @ts-ignore TODO: type guard isn't helping here :(
|
||||||
this.observeRoom(room);
|
this.observeRoom(room);
|
||||||
} else if (this.rid) {
|
} 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) {
|
if (insets.left !== prevProps.insets.left || insets.right !== prevProps.insets.right) {
|
||||||
this.setHeader();
|
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 () => {
|
updateOmnichannel = async () => {
|
||||||
|
@ -473,7 +487,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
EventEmitter.removeListener(KEY_COMMAND, this.handleCommands);
|
EventEmitter.removeListener(KEY_COMMAND, this.handleCommands);
|
||||||
}
|
}
|
||||||
EventEmitter.removeListener('ROOM_REMOVED', this.handleRoomRemoved);
|
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 () => {
|
canForwardGuest = async () => {
|
||||||
|
@ -765,10 +779,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
observeRoom = (room: TSubscriptionModel) => {
|
observeRoom = (room: TSubscriptionModel) => {
|
||||||
const observable = room.observe();
|
const observable = room.observe();
|
||||||
this.subSubscription = observable.subscribe(changes => {
|
this.subSubscription = observable.subscribe(changes => {
|
||||||
const roomUpdate = roomAttrsUpdate.reduce((ret: any, attr) => {
|
const roomUpdate = fetchRoomUpdate(changes);
|
||||||
ret[attr] = changes[attr];
|
|
||||||
return ret;
|
|
||||||
}, {});
|
|
||||||
if (this.mounted) {
|
if (this.mounted) {
|
||||||
this.internalSetState({ room: changes, roomUpdate, isOnHold: !!changes?.onHold });
|
this.internalSetState({ room: changes, roomUpdate, isOnHold: !!changes?.onHold });
|
||||||
} else {
|
} 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);
|
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);
|
this.messagebox?.current?.closeEmojiAndAction(showActionSheet, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
onEditInit = (message: TAnyMessageModel) => {
|
onEditInit = (message: TAnyMessage) => {
|
||||||
const newMessage = {
|
const newMessage = {
|
||||||
id: message.id,
|
id: message.id,
|
||||||
subscription: {
|
subscription: {
|
||||||
// @ts-ignore TODO: we can remove this after we merge a PR separating IMessage vs IMessageFromServer
|
id: message.rid
|
||||||
id: message.subscription.id
|
|
||||||
},
|
},
|
||||||
msg: message?.attachments?.[0]?.description || message.msg
|
msg: message?.attachments?.[0]?.description || message.msg
|
||||||
} as TMessageModel;
|
} as TMessageModel;
|
||||||
|
@ -805,7 +815,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
this.setState({ selectedMessage: undefined, editing: false });
|
this.setState({ selectedMessage: undefined, editing: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
onEditRequest = async (message: TAnyMessageModel) => {
|
onEditRequest = async (message: TAnyMessage) => {
|
||||||
this.setState({ selectedMessage: undefined, editing: false });
|
this.setState({ selectedMessage: undefined, editing: false });
|
||||||
try {
|
try {
|
||||||
await Services.editMessage(message);
|
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 there's a thread already, we redirect to it
|
||||||
if (mention && !!message.tlm) {
|
if (mention && !!message.tlm) {
|
||||||
return this.onThreadPress(message);
|
return this.onThreadPress(message);
|
||||||
|
@ -844,7 +854,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
onReactionInit = (message: TAnyMessageModel) => {
|
onReactionInit = (message: TAnyMessage) => {
|
||||||
this.messagebox?.current?.closeEmojiAndAction(() => {
|
this.messagebox?.current?.closeEmojiAndAction(() => {
|
||||||
this.setState({ selectedMessage: message }, this.showReactionPicker);
|
this.setState({ selectedMessage: message }, this.showReactionPicker);
|
||||||
});
|
});
|
||||||
|
@ -855,7 +865,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
this.setState({ selectedMessage: undefined }, hideActionSheet);
|
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 it's a thread message on main room, we disable the long press
|
||||||
if (message.tmid && !this.tmid) {
|
if (message.tmid && !this.tmid) {
|
||||||
return;
|
return;
|
||||||
|
@ -885,7 +895,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onReactionLongPress = (message: TAnyMessageModel) => {
|
onReactionLongPress = (message: TAnyMessage) => {
|
||||||
this.setState({ selectedMessage: message });
|
this.setState({ selectedMessage: message });
|
||||||
const { showActionSheet } = this.props;
|
const { showActionSheet } = this.props;
|
||||||
const { selectedMessage } = this.state;
|
const { selectedMessage } = this.state;
|
||||||
|
@ -911,7 +921,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
onDiscussionPress = debounce(
|
onDiscussionPress = debounce(
|
||||||
async (item: TAnyMessageModel) => {
|
async (item: TAnyMessage) => {
|
||||||
const { isMasterDetail } = this.props;
|
const { isMasterDetail } = this.props;
|
||||||
if (!item.drid) return;
|
if (!item.drid) return;
|
||||||
const sub = await getRoomInfo(item.drid);
|
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) => {
|
shouldNavigateToRoom = (message: IMessage) => {
|
||||||
if (message.tmid && message.tmid === this.tmid) {
|
if (message.tmid && message.tmid === this.tmid) {
|
||||||
|
@ -1048,9 +1058,9 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
const { rid } = this.state.room;
|
const { rid } = this.state.room;
|
||||||
const { user } = this.props;
|
const { user } = this.props;
|
||||||
sendMessage(rid, message, this.tmid || tmid, user, tshow).then(() => {
|
sendMessage(rid, message, this.tmid || tmid, user, tshow).then(() => {
|
||||||
if (this.list && this.list.current) {
|
// if (this.list && this.list.current) {
|
||||||
this.list.current?.update();
|
// this.list.current?.update();
|
||||||
}
|
// }
|
||||||
this.setLastOpen(null);
|
this.setLastOpen(null);
|
||||||
Review.pushPositiveEvent();
|
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 { roomUserId } = this.state;
|
||||||
const { navigation } = this.props;
|
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 { isMasterDetail } = this.props;
|
||||||
const roomInfo = await getRoomInfo(message.rid);
|
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;
|
const { room } = this.state;
|
||||||
if ('id' in room) {
|
if ('id' in room) {
|
||||||
return room?.ignored?.includes?.(message?.u?._id) ?? false;
|
return room?.ignored?.includes?.(message?.u?._id) ?? false;
|
||||||
|
@ -1301,7 +1311,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
onLoadMoreMessages = (loaderItem: TAnyMessageModel) => {
|
onLoadMoreMessages = (loaderItem: TMessageModel) => {
|
||||||
const { room } = this.state;
|
const { room } = this.state;
|
||||||
return RoomServices.getMoreMessages({
|
return RoomServices.getMoreMessages({
|
||||||
rid: room.rid,
|
rid: room.rid,
|
||||||
|
@ -1316,7 +1326,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
Navigation.navigate('CannedResponsesListView', { rid: room.rid });
|
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 { room, lastOpen, canAutoTranslate } = this.state;
|
||||||
const { user, Message_GroupingPeriod, Message_TimeFormat, useRealName, baseUrl, Message_Read_Receipt_Enabled, theme } =
|
const { user, Message_GroupingPeriod, Message_TimeFormat, useRealName, baseUrl, Message_Read_Receipt_Enabled, theme } =
|
||||||
this.props;
|
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)) {
|
if (item.t && MESSAGE_TYPE_ANY_LOAD.includes(item.t as MessageTypeLoad)) {
|
||||||
content = (
|
content = (
|
||||||
<LoadMore
|
<LoadMore
|
||||||
load={() => this.onLoadMoreMessages(item)}
|
load={() => this.onLoadMoreMessages(item as TMessageModel)}
|
||||||
type={item.t}
|
type={item.t}
|
||||||
runOnRender={item.t === MessageTypeLoad.MORE && !previousItem}
|
runOnRender={item.t === MessageTypeLoad.MORE && !previousItem}
|
||||||
/>
|
/>
|
||||||
|
@ -1518,10 +1528,10 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
console.count(`${this.constructor.name}.render calls`);
|
|
||||||
const { room, loading } = this.state;
|
const { room, loading } = this.state;
|
||||||
const { user, baseUrl, theme, navigation, Hide_System_Messages, width, serverVersion } = this.props;
|
const { user, baseUrl, theme, navigation, Hide_System_Messages, width, serverVersion } = this.props;
|
||||||
const { rid, t } = room;
|
const { rid, t } = room;
|
||||||
|
console.count(`${this.constructor.name}.render: ${this.tmid || rid} calls`);
|
||||||
let sysMes;
|
let sysMes;
|
||||||
let bannerClosed;
|
let bannerClosed;
|
||||||
let announcement;
|
let announcement;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { SubscriptionType, TAnyMessageModel } from '../../../definitions';
|
import { SubscriptionType, TMessageModel } from '../../../definitions';
|
||||||
import { loadNextMessages, loadMessagesForRoom } from '../../../lib/methods';
|
import { loadNextMessages, loadMessagesForRoom } from '../../../lib/methods';
|
||||||
import { MessageTypeLoad } from '../../../lib/constants';
|
import { MessageTypeLoad } from '../../../lib/constants';
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ const getMoreMessages = ({
|
||||||
rid: string;
|
rid: string;
|
||||||
t: SubscriptionType;
|
t: SubscriptionType;
|
||||||
tmid?: string;
|
tmid?: string;
|
||||||
loaderItem: TAnyMessageModel;
|
loaderItem: TMessageModel;
|
||||||
}): Promise<void> => {
|
}): Promise<void> => {
|
||||||
if ([MessageTypeLoad.MORE, MessageTypeLoad.PREVIOUS_CHUNK].includes(loaderItem.t as MessageTypeLoad)) {
|
if ([MessageTypeLoad.MORE, MessageTypeLoad.PREVIOUS_CHUNK].includes(loaderItem.t as MessageTypeLoad)) {
|
||||||
return loadMessagesForRoom({
|
return loadMessagesForRoom({
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import React from 'react';
|
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 { batch, connect } from 'react-redux';
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
import Orientation from 'react-native-orientation-locker';
|
import Orientation from 'react-native-orientation-locker';
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q } from '@nozbe/watermelondb';
|
||||||
import { withSafeAreaInsets } from 'react-native-safe-area-context';
|
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { Header } from '@react-navigation/elements';
|
import { Header } from '@react-navigation/elements';
|
||||||
|
import { FlashList } from '@shopify/flash-list';
|
||||||
import { CompositeNavigationProp, RouteProp } from '@react-navigation/native';
|
import { CompositeNavigationProp, RouteProp } from '@react-navigation/native';
|
||||||
import { Dispatch } from 'redux';
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
|
@ -39,7 +39,6 @@ import {
|
||||||
import { getUserSelector } from '../../selectors/login';
|
import { getUserSelector } from '../../selectors/login';
|
||||||
import { goRoom } from '../../lib/methods/helpers/goRoom';
|
import { goRoom } from '../../lib/methods/helpers/goRoom';
|
||||||
import SafeAreaView from '../../containers/SafeAreaView';
|
import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
import { withDimensions } from '../../dimensions';
|
|
||||||
import { getInquiryQueueSelector } from '../../ee/omnichannel/selectors/inquiry';
|
import { getInquiryQueueSelector } from '../../ee/omnichannel/selectors/inquiry';
|
||||||
import { IApplicationState, ISubscription, IUser, RootEnum, SubscriptionType, TSubscriptionModel } from '../../definitions';
|
import { IApplicationState, ISubscription, IUser, RootEnum, SubscriptionType, TSubscriptionModel } from '../../definitions';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
@ -55,10 +54,9 @@ import {
|
||||||
hasPermission,
|
hasPermission,
|
||||||
isRead,
|
isRead,
|
||||||
debounce,
|
debounce,
|
||||||
isIOS,
|
|
||||||
isTablet
|
isTablet
|
||||||
} from '../../lib/methods/helpers';
|
} 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';
|
import { Services } from '../../lib/services';
|
||||||
|
|
||||||
type TNavigation = CompositeNavigationProp<
|
type TNavigation = CompositeNavigationProp<
|
||||||
|
@ -71,7 +69,6 @@ interface IRoomsListViewProps {
|
||||||
route: RouteProp<ChatsStackParamList, 'RoomsListView'>;
|
route: RouteProp<ChatsStackParamList, 'RoomsListView'>;
|
||||||
theme: TSupportedThemes;
|
theme: TSupportedThemes;
|
||||||
dispatch: Dispatch;
|
dispatch: Dispatch;
|
||||||
[key: string]: IUser | string | boolean | ISubscription[] | number | object | TEncryptionBanner;
|
|
||||||
user: IUser;
|
user: IUser;
|
||||||
server: string;
|
server: string;
|
||||||
searchText: string;
|
searchText: string;
|
||||||
|
@ -87,29 +84,22 @@ interface IRoomsListViewProps {
|
||||||
useRealName: boolean;
|
useRealName: boolean;
|
||||||
isMasterDetail: boolean;
|
isMasterDetail: boolean;
|
||||||
subscribedRoom: string;
|
subscribedRoom: string;
|
||||||
width: number;
|
|
||||||
insets: {
|
|
||||||
left: number;
|
|
||||||
right: number;
|
|
||||||
};
|
|
||||||
queueSize: number;
|
queueSize: number;
|
||||||
inquiryEnabled: boolean;
|
inquiryEnabled: boolean;
|
||||||
encryptionBanner: TEncryptionBanner;
|
encryptionBanner: string;
|
||||||
showAvatar: boolean;
|
showAvatar: boolean;
|
||||||
displayMode: string;
|
displayMode: string;
|
||||||
createTeamPermission: [];
|
createTeamPermission?: string[];
|
||||||
createDirectMessagePermission: [];
|
createDirectMessagePermission?: string[];
|
||||||
createPublicChannelPermission: [];
|
createPublicChannelPermission?: string[];
|
||||||
createPrivateChannelPermission: [];
|
createPrivateChannelPermission?: string[];
|
||||||
createDiscussionPermission: [];
|
createDiscussionPermission?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IRoomsListViewState {
|
interface IRoomsListViewState {
|
||||||
searching?: boolean;
|
searching?: boolean;
|
||||||
search?: IRoomItem[];
|
search?: IRoomItem[];
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
chatsUpdate?: string[] | { rid: string; alert?: boolean }[];
|
|
||||||
omnichannelsUpdate?: string[];
|
|
||||||
chats?: IRoomItem[];
|
chats?: IRoomItem[];
|
||||||
item?: ISubscription;
|
item?: ISubscription;
|
||||||
canCreateRoom?: boolean;
|
canCreateRoom?: boolean;
|
||||||
|
@ -120,7 +110,6 @@ interface IRoomItem extends ISubscription {
|
||||||
outside?: boolean;
|
outside?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12;
|
|
||||||
const CHATS_HEADER = 'Chats';
|
const CHATS_HEADER = 'Chats';
|
||||||
const UNREAD_HEADER = 'Unread';
|
const UNREAD_HEADER = 'Unread';
|
||||||
const FAVORITES_HEADER = 'Favorites';
|
const FAVORITES_HEADER = 'Favorites';
|
||||||
|
@ -132,53 +121,22 @@ const OMNICHANNEL_HEADER_IN_PROGRESS = 'Open_Livechats';
|
||||||
const OMNICHANNEL_HEADER_ON_HOLD = 'On_hold_Livechats';
|
const OMNICHANNEL_HEADER_ON_HOLD = 'On_hold_Livechats';
|
||||||
const QUERY_SIZE = 20;
|
const QUERY_SIZE = 20;
|
||||||
|
|
||||||
const filterIsUnread = (s: TSubscriptionModel) => (s.unread > 0 || s.tunread?.length > 0 || s.alert) && !s.hideUnreadStatus;
|
const filterIsUnread = (s: any) => (s.unread > 0 || s.tunread?.length > 0 || s.alert) && !s.hideUnreadStatus;
|
||||||
const filterIsFavorite = (s: TSubscriptionModel) => s.f;
|
const filterIsFavorite = (s: any) => s.f;
|
||||||
const filterIsOmnichannel = (s: TSubscriptionModel) => s.t === 'l';
|
const filterIsOmnichannel = (s: any) => s.t === 'l';
|
||||||
const filterIsTeam = (s: TSubscriptionModel) => s.teamMain;
|
const filterIsTeam = (s: any) => s.teamMain;
|
||||||
const filterIsDiscussion = (s: TSubscriptionModel) => s.prid;
|
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;
|
const keyExtractor = (item: ISubscription) => item.rid;
|
||||||
|
|
||||||
class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewState> {
|
class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewState> {
|
||||||
private animated: boolean;
|
private animated: boolean;
|
||||||
private mounted: boolean;
|
|
||||||
private count: number;
|
private count: number;
|
||||||
private unsubscribeFocus?: () => void;
|
private unsubscribeFocus?: () => void;
|
||||||
private unsubscribeBlur?: () => void;
|
private unsubscribeBlur?: () => void;
|
||||||
private sortPreferencesChanged?: boolean;
|
|
||||||
private shouldUpdate?: boolean;
|
|
||||||
private backHandler?: NativeEventSubscription;
|
private backHandler?: NativeEventSubscription;
|
||||||
private querySubscription?: Subscription;
|
private querySubscription?: Subscription;
|
||||||
private scroll?: FlatList;
|
private scroll?: any;
|
||||||
private useRealName?: boolean;
|
private useRealName?: boolean;
|
||||||
|
|
||||||
constructor(props: IRoomsListViewProps) {
|
constructor(props: IRoomsListViewProps) {
|
||||||
|
@ -187,14 +145,11 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
console.time(`${this.constructor.name} mount`);
|
console.time(`${this.constructor.name} mount`);
|
||||||
|
|
||||||
this.animated = false;
|
this.animated = false;
|
||||||
this.mounted = false;
|
|
||||||
this.count = 0;
|
this.count = 0;
|
||||||
this.state = {
|
this.state = {
|
||||||
searching: false,
|
searching: false,
|
||||||
search: [],
|
search: [],
|
||||||
loading: true,
|
loading: true,
|
||||||
chatsUpdate: [] as TSubscriptionModel[],
|
|
||||||
omnichannelsUpdate: [],
|
|
||||||
chats: [],
|
chats: [],
|
||||||
item: {} as ISubscription,
|
item: {} as ISubscription,
|
||||||
canCreateRoom: false
|
canCreateRoom: false
|
||||||
|
@ -206,7 +161,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { navigation, dispatch } = this.props;
|
const { navigation, dispatch } = this.props;
|
||||||
this.handleHasPermission();
|
this.handleHasPermission();
|
||||||
this.mounted = true;
|
|
||||||
|
|
||||||
if (isTablet) {
|
if (isTablet) {
|
||||||
EventEmitter.addEventListener(KEY_COMMAND, this.handleCommands);
|
EventEmitter.addEventListener(KEY_COMMAND, this.handleCommands);
|
||||||
|
@ -214,16 +168,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
this.unsubscribeFocus = navigation.addListener('focus', () => {
|
this.unsubscribeFocus = navigation.addListener('focus', () => {
|
||||||
Orientation.unlockAllOrientations();
|
Orientation.unlockAllOrientations();
|
||||||
this.animated = true;
|
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.backHandler = BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
|
||||||
});
|
});
|
||||||
this.unsubscribeBlur = navigation.addListener('blur', () => {
|
this.unsubscribeBlur = navigation.addListener('blur', () => {
|
||||||
|
@ -253,81 +197,61 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: IRoomsListViewProps, nextState: IRoomsListViewState) {
|
shouldComponentUpdate(nextProps: Readonly<IRoomsListViewProps>, nextState: Readonly<IRoomsListViewState>): boolean {
|
||||||
const { chatsUpdate, searching, item, canCreateRoom, omnichannelsUpdate } = this.state;
|
const {
|
||||||
// eslint-disable-next-line react/destructuring-assignment
|
createTeamPermission,
|
||||||
const propsUpdated = shouldUpdateProps.some(key => nextProps[key] !== this.props[key]);
|
createPublicChannelPermission,
|
||||||
if (propsUpdated) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if some display props are changed to force update when focus this view again
|
const { chats, search } = this.state;
|
||||||
// eslint-disable-next-line react/destructuring-assignment
|
if (!dequal(chats, nextState.chats) || !dequal(search, nextState.search)) {
|
||||||
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) {
|
|
||||||
return true;
|
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;
|
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;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,7 +263,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
showUnread,
|
showUnread,
|
||||||
subscribedRoom,
|
subscribedRoom,
|
||||||
isMasterDetail,
|
isMasterDetail,
|
||||||
insets,
|
|
||||||
createTeamPermission,
|
createTeamPermission,
|
||||||
createPublicChannelPermission,
|
createPublicChannelPermission,
|
||||||
createPrivateChannelPermission,
|
createPrivateChannelPermission,
|
||||||
|
@ -366,9 +289,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
if (isMasterDetail && item?.rid !== subscribedRoom && subscribedRoom !== prevProps.subscribedRoom) {
|
if (isMasterDetail && item?.rid !== subscribedRoom && subscribedRoom !== prevProps.subscribedRoom) {
|
||||||
this.setState({ item: { rid: subscribedRoom } as ISubscription });
|
this.setState({ item: { rid: subscribedRoom } as ISubscription });
|
||||||
}
|
}
|
||||||
if (insets.left !== prevProps.insets.left || insets.right !== prevProps.insets.right) {
|
|
||||||
this.setHeader();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!dequal(createTeamPermission, prevProps.createTeamPermission) ||
|
!dequal(createTeamPermission, prevProps.createTeamPermission) ||
|
||||||
|
@ -481,13 +401,14 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
| (Pick<IRoomsListViewState, keyof IRoomsListViewState> | IRoomsListViewState | null),
|
| (Pick<IRoomsListViewState, keyof IRoomsListViewState> | IRoomsListViewState | null),
|
||||||
callback?: () => void
|
callback?: () => void
|
||||||
) => {
|
) => {
|
||||||
|
this.setState(state, callback);
|
||||||
if (this.animated) {
|
if (this.animated) {
|
||||||
|
this.scroll?.prepareForLayoutAnimationRender();
|
||||||
animateNextTransition();
|
animateNextTransition();
|
||||||
}
|
}
|
||||||
this.setState(state, callback);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
addRoomsGroup = (data: TSubscriptionModel[], header: string, allData: TSubscriptionModel[]) => {
|
addRoomsGroup = (data: ISubscription[], header: string, allData: ISubscription[]) => {
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
if (header) {
|
if (header) {
|
||||||
allData.push({ rid: header, separator: true } as TSubscriptionModel);
|
allData.push({ rid: header, separator: true } as TSubscriptionModel);
|
||||||
|
@ -498,6 +419,7 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
};
|
};
|
||||||
|
|
||||||
getSubscriptions = async () => {
|
getSubscriptions = async () => {
|
||||||
|
console.log('🚀 ~ file: index.tsx ~ line 408 ~ RoomsListView ~ getSubscriptions');
|
||||||
this.unsubscribeQuery();
|
this.unsubscribeQuery();
|
||||||
|
|
||||||
const { sortBy, showUnread, showFavorites, groupByType, user } = this.props;
|
const { sortBy, showUnread, showFavorites, groupByType, user } = this.props;
|
||||||
|
@ -506,6 +428,7 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
let observable;
|
let observable;
|
||||||
|
|
||||||
const defaultWhereClause = [Q.where('archived', false), Q.where('open', true)] as (Q.WhereDescription | Q.SortBy)[];
|
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) {
|
if (sortBy === SortBy.Alphabetical) {
|
||||||
defaultWhereClause.push(Q.experimentalSortBy(`${this.useRealName ? 'fname' : 'name'}`, Q.asc));
|
defaultWhereClause.push(Q.experimentalSortBy(`${this.useRealName ? 'fname' : 'name'}`, Q.asc));
|
||||||
|
@ -518,28 +441,26 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
observable = await db
|
observable = await db
|
||||||
.get('subscriptions')
|
.get('subscriptions')
|
||||||
.query(...defaultWhereClause)
|
.query(...defaultWhereClause)
|
||||||
.observeWithColumns(['alert', 'on_hold']);
|
.observeWithColumns(columnsToObserve);
|
||||||
// When we're NOT grouping
|
// When we're NOT grouping
|
||||||
} else {
|
} else {
|
||||||
this.count += QUERY_SIZE;
|
this.count += QUERY_SIZE;
|
||||||
observable = await db
|
observable = await db
|
||||||
.get('subscriptions')
|
.get('subscriptions')
|
||||||
.query(...defaultWhereClause, Q.experimentalSkip(0), Q.experimentalTake(this.count))
|
.query(...defaultWhereClause, Q.experimentalSkip(0), Q.experimentalTake(this.count))
|
||||||
.observeWithColumns(['on_hold']);
|
.observeWithColumns(columnsToObserve);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.querySubscription = observable.subscribe(data => {
|
this.querySubscription = observable.subscribe(data => {
|
||||||
let tempChats = [] as TSubscriptionModel[];
|
let tempChats: ISubscription[] = [];
|
||||||
let chats = data;
|
let chats = data.map(item => item.asPlain());
|
||||||
|
|
||||||
let omnichannelsUpdate: string[] = [];
|
|
||||||
const isOmnichannelAgent = user?.roles?.includes('livechat-agent');
|
const isOmnichannelAgent = user?.roles?.includes('livechat-agent');
|
||||||
if (isOmnichannelAgent) {
|
if (isOmnichannelAgent) {
|
||||||
const omnichannel = chats.filter(s => filterIsOmnichannel(s));
|
const omnichannel = chats.filter(s => filterIsOmnichannel(s));
|
||||||
const omnichannelInProgress = omnichannel.filter(s => !s.onHold);
|
const omnichannelInProgress = omnichannel.filter(s => !s.onHold);
|
||||||
const omnichannelOnHold = omnichannel.filter(s => s.onHold);
|
const omnichannelOnHold = omnichannel.filter(s => s.onHold);
|
||||||
chats = chats.filter(s => !filterIsOmnichannel(s));
|
chats = chats.filter(s => !filterIsOmnichannel(s));
|
||||||
omnichannelsUpdate = omnichannelInProgress.map(s => s.rid);
|
|
||||||
tempChats = this.addRoomsGroup(omnichannelInProgress, OMNICHANNEL_HEADER_IN_PROGRESS, tempChats);
|
tempChats = this.addRoomsGroup(omnichannelInProgress, OMNICHANNEL_HEADER_IN_PROGRESS, tempChats);
|
||||||
tempChats = this.addRoomsGroup(omnichannelOnHold, OMNICHANNEL_HEADER_ON_HOLD, tempChats);
|
tempChats = this.addRoomsGroup(omnichannelOnHold, OMNICHANNEL_HEADER_ON_HOLD, tempChats);
|
||||||
}
|
}
|
||||||
|
@ -574,12 +495,8 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
tempChats = chats;
|
tempChats = chats;
|
||||||
}
|
}
|
||||||
|
|
||||||
const chatsUpdate = tempChats.map(item => item.rid);
|
|
||||||
|
|
||||||
this.internalSetState({
|
this.internalSetState({
|
||||||
chats: tempChats,
|
chats: tempChats,
|
||||||
chatsUpdate,
|
|
||||||
omnichannelsUpdate,
|
|
||||||
loading: false
|
loading: false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -893,13 +810,14 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
};
|
};
|
||||||
|
|
||||||
onEndReached = () => {
|
onEndReached = () => {
|
||||||
// Run only when we're not grouping by anything
|
const { searching } = this.state;
|
||||||
if (!this.isGrouping) {
|
if (searching) {
|
||||||
this.getSubscriptions();
|
return;
|
||||||
}
|
}
|
||||||
|
this.getSubscriptions();
|
||||||
};
|
};
|
||||||
|
|
||||||
getScrollRef = (ref: FlatList) => (this.scroll = ref);
|
getScrollRef = (ref: any) => (this.scroll = ref);
|
||||||
|
|
||||||
renderListHeader = () => {
|
renderListHeader = () => {
|
||||||
const { searching } = this.state;
|
const { searching } = this.state;
|
||||||
|
@ -911,7 +829,7 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
goQueue={this.goQueue}
|
goQueue={this.goQueue}
|
||||||
queueSize={queueSize}
|
queueSize={queueSize}
|
||||||
inquiryEnabled={inquiryEnabled}
|
inquiryEnabled={inquiryEnabled}
|
||||||
encryptionBanner={encryptionBanner}
|
encryptionBanner={encryptionBanner as TEncryptionBanner}
|
||||||
user={user}
|
user={user}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -938,8 +856,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
user: { username },
|
user: { username },
|
||||||
StoreLastMessage,
|
StoreLastMessage,
|
||||||
useRealName,
|
useRealName,
|
||||||
isMasterDetail,
|
|
||||||
width,
|
|
||||||
showAvatar,
|
showAvatar,
|
||||||
displayMode
|
displayMode
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
@ -953,7 +869,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
username={username}
|
username={username}
|
||||||
showLastMessage={StoreLastMessage}
|
showLastMessage={StoreLastMessage}
|
||||||
onPress={this.onPressItem}
|
onPress={this.onPressItem}
|
||||||
width={isMasterDetail ? MAX_SIDEBAR_WIDTH : width}
|
|
||||||
toggleFav={this.toggleFav}
|
toggleFav={this.toggleFav}
|
||||||
toggleRead={this.toggleRead}
|
toggleRead={this.toggleRead}
|
||||||
hideChannel={this.hideChannel}
|
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 = () => {
|
render = () => {
|
||||||
console.count(`${this.constructor.name}.render calls`);
|
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 (
|
return (
|
||||||
<SafeAreaView testID='rooms-list-view' style={{ backgroundColor: themes[theme].backgroundColor }}>
|
<SafeAreaView testID='rooms-list-view' style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||||
<StatusBar />
|
<StatusBar />
|
||||||
{this.renderHeader()}
|
{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*/}
|
{/* TODO - this ts-ignore is here because the route props, on IBaseScreen*/}
|
||||||
{/* @ts-ignore*/}
|
{/* @ts-ignore*/}
|
||||||
{showServerDropdown ? <ServerDropdown navigation={navigation} theme={theme} /> : null}
|
{showServerDropdown ? <ServerDropdown navigation={navigation} theme={theme} /> : null}
|
||||||
|
@ -1041,8 +950,8 @@ const mapStateToProps = (state: IApplicationState) => ({
|
||||||
groupByType: state.sortPreferences.groupByType,
|
groupByType: state.sortPreferences.groupByType,
|
||||||
showFavorites: state.sortPreferences.showFavorites,
|
showFavorites: state.sortPreferences.showFavorites,
|
||||||
showUnread: state.sortPreferences.showUnread,
|
showUnread: state.sortPreferences.showUnread,
|
||||||
useRealName: state.settings.UI_Use_Real_Name,
|
useRealName: state.settings.UI_Use_Real_Name as boolean,
|
||||||
StoreLastMessage: state.settings.Store_Last_Message,
|
StoreLastMessage: state.settings.Store_Last_Message as boolean,
|
||||||
subscribedRoom: state.room.subscribedRoom,
|
subscribedRoom: state.room.subscribedRoom,
|
||||||
queueSize: getInquiryQueueSelector(state).length,
|
queueSize: getInquiryQueueSelector(state).length,
|
||||||
inquiryEnabled: state.inquiry.enabled,
|
inquiryEnabled: state.inquiry.enabled,
|
||||||
|
@ -1056,4 +965,4 @@ const mapStateToProps = (state: IApplicationState) => ({
|
||||||
createDiscussionPermission: state.permissions['start-discussion']
|
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: {
|
container: {
|
||||||
flex: 1
|
flex: 1
|
||||||
},
|
},
|
||||||
list: {
|
|
||||||
width: '100%'
|
|
||||||
},
|
|
||||||
dropdownContainerHeader: {
|
dropdownContainerHeader: {
|
||||||
height: 41,
|
height: 41,
|
||||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||||
|
|
|
@ -340,7 +340,9 @@ describe('E2E Encryption', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add server and create new user', async () => {
|
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 element(by.id('rooms-list-header-server-dropdown-button')).tap();
|
||||||
await waitFor(element(by.id('rooms-list-header-server-dropdown')))
|
await waitFor(element(by.id('rooms-list-header-server-dropdown')))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
import { expect } from 'detox';
|
import { expect } from 'detox';
|
||||||
|
|
||||||
import { navigateToRegister, platformTypes, TTextMatcher } from '../../helpers/app';
|
import { navigateToRegister } from '../../helpers/app';
|
||||||
import data from '../../data';
|
import data from '../../data';
|
||||||
|
|
||||||
describe('Create user screen', () => {
|
describe('Create user screen', () => {
|
||||||
let alertButtonType: string;
|
|
||||||
let textMatcher: TTextMatcher;
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
({ alertButtonType, textMatcher } = platformTypes[device.getPlatform()]);
|
|
||||||
await navigateToRegister();
|
await navigateToRegister();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -65,17 +62,17 @@ describe('Create user screen', () => {
|
||||||
// await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
// await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
// });
|
// });
|
||||||
|
|
||||||
it('should submit username already taken and raise error', async () => {
|
// 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-name')).replaceText(data.registeringUser.username);
|
||||||
await element(by.id('register-view-username')).replaceText(data.users.existing.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-email')).replaceText(data.registeringUser.email);
|
||||||
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
|
// await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
|
||||||
await element(by.id('register-view-submit')).tap();
|
// await element(by.id('register-view-submit')).tap();
|
||||||
await waitFor(element(by[textMatcher]('Username is already in use')).atIndex(0))
|
// await waitFor(element(by[textMatcher]('Username is already in use')).atIndex(0))
|
||||||
.toExist()
|
// .toExist()
|
||||||
.withTimeout(10000);
|
// .withTimeout(10000);
|
||||||
await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
// await element(by[textMatcher]('OK').and(by.type(alertButtonType))).tap();
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('should register', async () => {
|
it('should register', async () => {
|
||||||
await element(by.id('register-view-name')).replaceText(data.registeringUser.username);
|
await element(by.id('register-view-name')).replaceText(data.registeringUser.username);
|
||||||
|
|
|
@ -187,12 +187,19 @@ describe('Room', () => {
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await element(by[textMatcher]('Load Newer')).atIndex(0).tap();
|
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')))
|
await waitFor(element(by[textMatcher]('Load Newer')))
|
||||||
.toNotExist()
|
.toNotExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
await expect(element(by[textMatcher]('Load More'))).toNotExist();
|
await expect(element(by[textMatcher]('Load More'))).toNotExist();
|
||||||
await expect(element(by[textMatcher]('201'))).toExist();
|
await expect(element(by[textMatcher]('253'))).toExist();
|
||||||
await expect(element(by[textMatcher]('202'))).toExist();
|
await expect(element(by[textMatcher]('252'))).toExist();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
5
index.js
5
index.js
|
@ -1,11 +1,16 @@
|
||||||
import 'react-native-gesture-handler';
|
import 'react-native-gesture-handler';
|
||||||
import 'react-native-console-time-polyfill';
|
import 'react-native-console-time-polyfill';
|
||||||
import { AppRegistry } from 'react-native';
|
import { AppRegistry } from 'react-native';
|
||||||
|
import { connectToDevTools } from 'react-devtools-core';
|
||||||
|
|
||||||
import { name as appName, share as shareName } from './app.json';
|
import { name as appName, share as shareName } from './app.json';
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
require('./app/ReactotronConfig');
|
require('./app/ReactotronConfig');
|
||||||
|
connectToDevTools({
|
||||||
|
host: 'localhost',
|
||||||
|
port: 8097
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log = () => {};
|
console.log = () => {};
|
||||||
console.time = () => {};
|
console.time = () => {};
|
||||||
|
|
|
@ -364,6 +364,11 @@ PODS:
|
||||||
- React-Core
|
- React-Core
|
||||||
- react-native-document-picker (8.1.2):
|
- react-native-document-picker (8.1.2):
|
||||||
- React-Core
|
- 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):
|
- react-native-jitsi-meet (3.6.0):
|
||||||
- JitsiMeetSDK (= 3.6.0)
|
- JitsiMeetSDK (= 3.6.0)
|
||||||
- React
|
- React
|
||||||
|
@ -522,6 +527,8 @@ PODS:
|
||||||
- RNFBApp
|
- RNFBApp
|
||||||
- RNFileViewer (2.1.5):
|
- RNFileViewer (2.1.5):
|
||||||
- React-Core
|
- React-Core
|
||||||
|
- RNFlashList (1.2.2):
|
||||||
|
- React-Core
|
||||||
- RNGestureHandler (2.4.2):
|
- RNGestureHandler (2.4.2):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNImageCropPicker (0.36.3):
|
- RNImageCropPicker (0.36.3):
|
||||||
|
@ -629,6 +636,7 @@ DEPENDENCIES:
|
||||||
- "react-native-cameraroll (from `../node_modules/@react-native-community/cameraroll`)"
|
- "react-native-cameraroll (from `../node_modules/@react-native-community/cameraroll`)"
|
||||||
- "react-native-cookies (from `../node_modules/@react-native-cookies/cookies`)"
|
- "react-native-cookies (from `../node_modules/@react-native-cookies/cookies`)"
|
||||||
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
|
- 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-jitsi-meet (from `../node_modules/react-native-jitsi-meet`)
|
||||||
- react-native-mmkv-storage (from `../node_modules/react-native-mmkv-storage`)
|
- react-native-mmkv-storage (from `../node_modules/react-native-mmkv-storage`)
|
||||||
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
|
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
|
||||||
|
@ -668,6 +676,7 @@ DEPENDENCIES:
|
||||||
- "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
|
- "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
|
||||||
- "RNFBCrashlytics (from `../node_modules/@react-native-firebase/crashlytics`)"
|
- "RNFBCrashlytics (from `../node_modules/@react-native-firebase/crashlytics`)"
|
||||||
- RNFileViewer (from `../node_modules/react-native-file-viewer`)
|
- RNFileViewer (from `../node_modules/react-native-file-viewer`)
|
||||||
|
- "RNFlashList (from `../node_modules/@shopify/flash-list`)"
|
||||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||||
- RNLocalize (from `../node_modules/react-native-localize`)
|
- RNLocalize (from `../node_modules/react-native-localize`)
|
||||||
|
@ -783,6 +792,8 @@ EXTERNAL SOURCES:
|
||||||
:path: "../node_modules/@react-native-cookies/cookies"
|
:path: "../node_modules/@react-native-cookies/cookies"
|
||||||
react-native-document-picker:
|
react-native-document-picker:
|
||||||
:path: "../node_modules/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:
|
react-native-jitsi-meet:
|
||||||
:path: "../node_modules/react-native-jitsi-meet"
|
:path: "../node_modules/react-native-jitsi-meet"
|
||||||
react-native-mmkv-storage:
|
react-native-mmkv-storage:
|
||||||
|
@ -861,6 +872,8 @@ EXTERNAL SOURCES:
|
||||||
:path: "../node_modules/@react-native-firebase/crashlytics"
|
:path: "../node_modules/@react-native-firebase/crashlytics"
|
||||||
RNFileViewer:
|
RNFileViewer:
|
||||||
:path: "../node_modules/react-native-file-viewer"
|
:path: "../node_modules/react-native-file-viewer"
|
||||||
|
RNFlashList:
|
||||||
|
:path: "../node_modules/@shopify/flash-list"
|
||||||
RNGestureHandler:
|
RNGestureHandler:
|
||||||
:path: "../node_modules/react-native-gesture-handler"
|
:path: "../node_modules/react-native-gesture-handler"
|
||||||
RNImageCropPicker:
|
RNImageCropPicker:
|
||||||
|
@ -949,6 +962,7 @@ SPEC CHECKSUMS:
|
||||||
react-native-cameraroll: 2957f2bce63ae896a848fbe0d5352c1bd4d20866
|
react-native-cameraroll: 2957f2bce63ae896a848fbe0d5352c1bd4d20866
|
||||||
react-native-cookies: f54fcded06bb0cda05c11d86788020b43528a26c
|
react-native-cookies: f54fcded06bb0cda05c11d86788020b43528a26c
|
||||||
react-native-document-picker: f5ec1a712ca2a975c233117f044817bb8393cad4
|
react-native-document-picker: f5ec1a712ca2a975c233117f044817bb8393cad4
|
||||||
|
react-native-flipper-performance-plugin: 2b873b68da3e368afeaf29c9c7a8c2b0ff908c4f
|
||||||
react-native-jitsi-meet: 3e3ac5d0445091154119f94342efd55c8b1124ce
|
react-native-jitsi-meet: 3e3ac5d0445091154119f94342efd55c8b1124ce
|
||||||
react-native-mmkv-storage: 8ba3c0216a6df283ece11205b442a3e435aec4e5
|
react-native-mmkv-storage: 8ba3c0216a6df283ece11205b442a3e435aec4e5
|
||||||
react-native-netinfo: e849fc21ca2f4128a5726c801a82fc6f4a6db50d
|
react-native-netinfo: e849fc21ca2f4128a5726c801a82fc6f4a6db50d
|
||||||
|
@ -988,6 +1002,7 @@ SPEC CHECKSUMS:
|
||||||
RNFBApp: b1b5a80a676a07dea17e778bda7c1e8b69b2f5ec
|
RNFBApp: b1b5a80a676a07dea17e778bda7c1e8b69b2f5ec
|
||||||
RNFBCrashlytics: 357955a1564721ca9001960e57b395c6a319f9be
|
RNFBCrashlytics: 357955a1564721ca9001960e57b395c6a319f9be
|
||||||
RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592
|
RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592
|
||||||
|
RNFlashList: 13d14d9502661134ad3ba892f81d76bdcbd79755
|
||||||
RNGestureHandler: 61628a2c859172551aa2100d3e73d1e57878392f
|
RNGestureHandler: 61628a2c859172551aa2100d3e73d1e57878392f
|
||||||
RNImageCropPicker: 97289cd94fb01ab79db4e5c92938be4d0d63415d
|
RNImageCropPicker: 97289cd94fb01ab79db4e5c92938be4d0d63415d
|
||||||
RNLocalize: 82a569022724d35461e2dc5b5d015a13c3ca995b
|
RNLocalize: 82a569022724d35461e2dc5b5d015a13c3ca995b
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
0C6E2DE448364EA896869ADF /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B37C79D9BD0742CE936B6982 /* libc++.tbd */; };
|
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 */; };
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||||
1E01C81C2511208400FEF824 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E01C81B2511208400FEF824 /* URL+Extensions.swift */; };
|
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 */; };
|
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, ); }; };
|
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 */; };
|
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 */; };
|
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 */; };
|
7A006F14229C83B600803143 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7A006F13229C83B600803143 /* GoogleService-Info.plist */; };
|
||||||
7A0D62D2242AB187006D5C06 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A0D62D1242AB187006D5C06 /* LaunchScreen.storyboard */; };
|
7A0D62D2242AB187006D5C06 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A0D62D1242AB187006D5C06 /* LaunchScreen.storyboard */; };
|
||||||
7A14FCED257FEB3A005BDCD4 /* Experimental.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A14FCEC257FEB3A005BDCD4 /* Experimental.xcassets */; };
|
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 */; };
|
7AE10C0728A59530003593CB /* Inter.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7AE10C0528A59530003593CB /* Inter.ttf */; };
|
||||||
7AE10C0828A59530003593CB /* 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 */; };
|
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 */; };
|
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 */; };
|
D94D81FB9E10756FAA03F203 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016747EF3B9FED8DE2C9DA14 /* ExpoModulesProvider.swift */; };
|
||||||
DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BA7E862283664608B3894E34 /* libWatermelonDB.a */; };
|
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 */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
@ -210,8 +210,9 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
|
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>"; };
|
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; };
|
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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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; };
|
421FD6D28D6DECEEC09F100E /* 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>"; };
|
|
||||||
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>"; };
|
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>"; };
|
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>"; };
|
||||||
5F1EEB258E879574E6F9EADA /* libPods-defaults-Rocket.Chat.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-defaults-Rocket.Chat.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
60B2A6A31FC4588700BD58E5 /* RocketChatRN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = RocketChatRN.entitlements; path = RocketChatRN/RocketChatRN.entitlements; 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>"; };
|
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>"; };
|
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>"; };
|
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; };
|
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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
||||||
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>"; };
|
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>"; };
|
||||||
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>"; };
|
|
||||||
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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
||||||
DEC0A8A825375FCCDCDFEFE2 /* libPods-defaults-NotificationService.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-defaults-NotificationService.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
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 */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
@ -310,7 +310,7 @@
|
||||||
7ACD4897222860DE00442C55 /* JavaScriptCore.framework in Frameworks */,
|
7ACD4897222860DE00442C55 /* JavaScriptCore.framework in Frameworks */,
|
||||||
24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */,
|
24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */,
|
||||||
DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */,
|
DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */,
|
||||||
58B1112437C7F012923203ED /* libPods-defaults-RocketChatRN.a in Frameworks */,
|
A891D4519F3C3C0DF281382E /* libPods-defaults-RocketChatRN.a in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -319,7 +319,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
1E25743422CBA2CF005A877F /* JavaScriptCore.framework in Frameworks */,
|
1E25743422CBA2CF005A877F /* JavaScriptCore.framework in Frameworks */,
|
||||||
4BC950FF98C56CFA992BBAFE /* libPods-defaults-ShareRocketChatRN.a in Frameworks */,
|
E5BA08EDF1C874FF35785B16 /* libPods-defaults-ShareRocketChatRN.a in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -327,7 +327,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
A965681B9D9B1DB968676F54 /* libPods-defaults-NotificationService.a in Frameworks */,
|
77BB45FF3B406BBA2A3C36F9 /* libPods-defaults-NotificationService.a in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -348,7 +348,7 @@
|
||||||
7AAB3E3D257E6A6E00707CF6 /* JavaScriptCore.framework in Frameworks */,
|
7AAB3E3D257E6A6E00707CF6 /* JavaScriptCore.framework in Frameworks */,
|
||||||
7AAB3E3E257E6A6E00707CF6 /* libz.tbd in Frameworks */,
|
7AAB3E3E257E6A6E00707CF6 /* libz.tbd in Frameworks */,
|
||||||
7AAB3E3F257E6A6E00707CF6 /* libWatermelonDB.a 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;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -499,14 +499,14 @@
|
||||||
7AC2B09613AA7C3FEBAC9F57 /* Pods */ = {
|
7AC2B09613AA7C3FEBAC9F57 /* Pods */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
8009E8CCFAA4804CCED401D8 /* Pods-defaults-NotificationService.debug.xcconfig */,
|
9EF17496557D766CD7CC65C8 /* Pods-defaults-NotificationService.debug.xcconfig */,
|
||||||
7E01AFB7FFC99A24DE24A9E7 /* Pods-defaults-NotificationService.release.xcconfig */,
|
28F09CD56CC780BB681DA43A /* Pods-defaults-NotificationService.release.xcconfig */,
|
||||||
04CABACAE3DF5FF44121FC30 /* Pods-defaults-Rocket.Chat.debug.xcconfig */,
|
5CA29716AE736DD49CEC421A /* Pods-defaults-Rocket.Chat.debug.xcconfig */,
|
||||||
3AD43034372030994471D0E9 /* Pods-defaults-Rocket.Chat.release.xcconfig */,
|
D2549B70E3F3979B2FB2F170 /* Pods-defaults-Rocket.Chat.release.xcconfig */,
|
||||||
48A6FD916DB2F924F1360A4A /* Pods-defaults-RocketChatRN.debug.xcconfig */,
|
77A439FBC388926A1D8F1B98 /* Pods-defaults-RocketChatRN.debug.xcconfig */,
|
||||||
AC87BFDE8CC75468C2E87328 /* Pods-defaults-RocketChatRN.release.xcconfig */,
|
8CF5ED249C29001A33922AC8 /* Pods-defaults-RocketChatRN.release.xcconfig */,
|
||||||
C84BF59D4FEA8C08AD41906D /* Pods-defaults-ShareRocketChatRN.debug.xcconfig */,
|
E956695E229DFCCB2DB61EE2 /* Pods-defaults-ShareRocketChatRN.debug.xcconfig */,
|
||||||
94EB1DBE281212E61157DDEE /* Pods-defaults-ShareRocketChatRN.release.xcconfig */,
|
FA35FD80EDA9584432506DDA /* Pods-defaults-ShareRocketChatRN.release.xcconfig */,
|
||||||
);
|
);
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -597,10 +597,10 @@
|
||||||
7ACD4853222860DE00442C55 /* JavaScriptCore.framework */,
|
7ACD4853222860DE00442C55 /* JavaScriptCore.framework */,
|
||||||
B37C79D9BD0742CE936B6982 /* libc++.tbd */,
|
B37C79D9BD0742CE936B6982 /* libc++.tbd */,
|
||||||
06BB44DD4855498082A744AD /* libz.tbd */,
|
06BB44DD4855498082A744AD /* libz.tbd */,
|
||||||
DEC0A8A825375FCCDCDFEFE2 /* libPods-defaults-NotificationService.a */,
|
10533AE1624775EF2CE700C5 /* libPods-defaults-NotificationService.a */,
|
||||||
5F1EEB258E879574E6F9EADA /* libPods-defaults-Rocket.Chat.a */,
|
09A9622AB95BAF321135704F /* libPods-defaults-Rocket.Chat.a */,
|
||||||
674E4FB148AE2FB17415683F /* libPods-defaults-RocketChatRN.a */,
|
FA66A470302CC036893877E3 /* libPods-defaults-RocketChatRN.a */,
|
||||||
3982B430BE28C2D93FD9AF5C /* libPods-defaults-ShareRocketChatRN.a */,
|
421FD6D28D6DECEEC09F100E /* libPods-defaults-ShareRocketChatRN.a */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -620,7 +620,7 @@
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "RocketChatRN" */;
|
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "RocketChatRN" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
E368867D90711EA1666BFF6A /* [CP] Check Pods Manifest.lock */,
|
D9ECCB381CCB547C6D9734F3 /* [CP] Check Pods Manifest.lock */,
|
||||||
7AA5C63E23E30D110005C4A7 /* Start Packager */,
|
7AA5C63E23E30D110005C4A7 /* Start Packager */,
|
||||||
13B07F871A680F5B00A75B9A /* Sources */,
|
13B07F871A680F5B00A75B9A /* Sources */,
|
||||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||||
|
@ -629,8 +629,8 @@
|
||||||
1EC6ACF422CB9FC300A41C61 /* Embed App Extensions */,
|
1EC6ACF422CB9FC300A41C61 /* Embed App Extensions */,
|
||||||
1E1EA8082326CCE300E22452 /* ShellScript */,
|
1E1EA8082326CCE300E22452 /* ShellScript */,
|
||||||
7AAE9EB32891A0D20024F559 /* Upload source maps to Bugsnag */,
|
7AAE9EB32891A0D20024F559 /* Upload source maps to Bugsnag */,
|
||||||
DE93C39DFDB4F3759B84670D /* [CP] Embed Pods Frameworks */,
|
A4C45440ECC8DF4C333E90AC /* [CP] Embed Pods Frameworks */,
|
||||||
52CE06391F137AA82A402A69 /* [CP] Copy Pods Resources */,
|
A820EB1B8BCA486D6F111B28 /* [CP] Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
@ -647,12 +647,12 @@
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 1EC6ACF322CB9FC300A41C61 /* Build configuration list for PBXNativeTarget "ShareRocketChatRN" */;
|
buildConfigurationList = 1EC6ACF322CB9FC300A41C61 /* Build configuration list for PBXNativeTarget "ShareRocketChatRN" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
943E61A9039C6FE02871CAD9 /* [CP] Check Pods Manifest.lock */,
|
1C5A0A2393598AD05D7E91C9 /* [CP] Check Pods Manifest.lock */,
|
||||||
1EC6ACAC22CB9FC300A41C61 /* Sources */,
|
1EC6ACAC22CB9FC300A41C61 /* Sources */,
|
||||||
1EC6ACAD22CB9FC300A41C61 /* Frameworks */,
|
1EC6ACAD22CB9FC300A41C61 /* Frameworks */,
|
||||||
1EC6ACAE22CB9FC300A41C61 /* Resources */,
|
1EC6ACAE22CB9FC300A41C61 /* Resources */,
|
||||||
1EFE4DC322CBF36300B766B7 /* ShellScript */,
|
1EFE4DC322CBF36300B766B7 /* ShellScript */,
|
||||||
1FB8D9B08356E6AC6201714D /* [CP] Copy Pods Resources */,
|
826C4D7E61DA0A8A695A5BF0 /* [CP] Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
@ -667,11 +667,11 @@
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 1EFEB5A02493B6640072EDC0 /* Build configuration list for PBXNativeTarget "NotificationService" */;
|
buildConfigurationList = 1EFEB5A02493B6640072EDC0 /* Build configuration list for PBXNativeTarget "NotificationService" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
AAFC671179263417C34C729A /* [CP] Check Pods Manifest.lock */,
|
443ECB36C026E4E5891D0289 /* [CP] Check Pods Manifest.lock */,
|
||||||
1EFEB5912493B6640072EDC0 /* Sources */,
|
1EFEB5912493B6640072EDC0 /* Sources */,
|
||||||
1EFEB5922493B6640072EDC0 /* Frameworks */,
|
1EFEB5922493B6640072EDC0 /* Frameworks */,
|
||||||
1EFEB5932493B6640072EDC0 /* Resources */,
|
1EFEB5932493B6640072EDC0 /* Resources */,
|
||||||
996816F401E32166714ABD9E /* [CP] Copy Pods Resources */,
|
A02AEE64373B898BFED7C77A /* [CP] Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
@ -686,7 +686,7 @@
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 7AAB3E4F257E6A6E00707CF6 /* Build configuration list for PBXNativeTarget "Rocket.Chat" */;
|
buildConfigurationList = 7AAB3E4F257E6A6E00707CF6 /* Build configuration list for PBXNativeTarget "Rocket.Chat" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
CDFA7A6FA541A8BED7CE9EE7 /* [CP] Check Pods Manifest.lock */,
|
439D1EFA5403CEE68343332F /* [CP] Check Pods Manifest.lock */,
|
||||||
7AAB3E13257E6A6E00707CF6 /* Start Packager */,
|
7AAB3E13257E6A6E00707CF6 /* Start Packager */,
|
||||||
7AAB3E14257E6A6E00707CF6 /* Sources */,
|
7AAB3E14257E6A6E00707CF6 /* Sources */,
|
||||||
7AAB3E32257E6A6E00707CF6 /* Frameworks */,
|
7AAB3E32257E6A6E00707CF6 /* Frameworks */,
|
||||||
|
@ -695,8 +695,8 @@
|
||||||
7AAB3E48257E6A6E00707CF6 /* Embed App Extensions */,
|
7AAB3E48257E6A6E00707CF6 /* Embed App Extensions */,
|
||||||
7AAB3E4B257E6A6E00707CF6 /* ShellScript */,
|
7AAB3E4B257E6A6E00707CF6 /* ShellScript */,
|
||||||
7A10288726B1D15200E47EF8 /* Upload source maps to Bugsnag */,
|
7A10288726B1D15200E47EF8 /* Upload source maps to Bugsnag */,
|
||||||
CCA2F3534731DC8EE1FAB416 /* [CP] Embed Pods Frameworks */,
|
6B58CF06B9125764FD3EEB12 /* [CP] Embed Pods Frameworks */,
|
||||||
DEE9CFB76371CE33773CB435 /* [CP] Copy Pods Resources */,
|
5E4E13E42C9F5F48755B0D71 /* [CP] Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
@ -846,6 +846,28 @@
|
||||||
shellPath = /bin/sh;
|
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";
|
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 */ = {
|
1E1EA8082326CCE300E22452 /* ShellScript */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -880,69 +902,57 @@
|
||||||
shellPath = /bin/sh;
|
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";
|
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;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-defaults-ShareRocketChatRN/Pods-defaults-ShareRocketChatRN-resources.sh",
|
);
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
|
inputPaths = (
|
||||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf",
|
);
|
||||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf",
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf",
|
outputFileListPaths = (
|
||||||
"${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 = (
|
outputPaths = (
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
|
"$(DERIVED_FILE_DIR)/Pods-defaults-Rocket.Chat-checkManifestLockResult.txt",
|
||||||
"${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;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
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;
|
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;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
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_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/AntDesign.ttf",
|
||||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
|
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
|
||||||
|
@ -989,7 +999,31 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
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;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
7A10288726B1D15200E47EF8 /* Upload source maps to Bugsnag */ = {
|
7A10288726B1D15200E47EF8 /* Upload source maps to Bugsnag */ = {
|
||||||
|
@ -1095,29 +1129,63 @@
|
||||||
shellPath = /bin/sh;
|
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";
|
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;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputFileListPaths = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
"${PODS_ROOT}/Target Support Files/Pods-defaults-ShareRocketChatRN/Pods-defaults-ShareRocketChatRN-resources.sh",
|
||||||
"${PODS_ROOT}/Manifest.lock",
|
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
|
||||||
);
|
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
|
||||||
outputFileListPaths = (
|
"${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 = (
|
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;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
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;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
996816F401E32166714ABD9E /* [CP] Copy Pods Resources */ = {
|
A02AEE64373B898BFED7C77A /* [CP] Copy Pods Resources */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
@ -1173,75 +1241,7 @@
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
AAFC671179263417C34C729A /* [CP] Check Pods Manifest.lock */ = {
|
A4C45440ECC8DF4C333E90AC /* [CP] Embed Pods Frameworks */ = {
|
||||||
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 */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
@ -1265,13 +1265,13 @@
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
DEE9CFB76371CE33773CB435 /* [CP] Copy Pods Resources */ = {
|
A820EB1B8BCA486D6F111B28 /* [CP] Copy Pods Resources */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
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_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/AntDesign.ttf",
|
||||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
|
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
|
||||||
|
@ -1318,10 +1318,10 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
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;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
E368867D90711EA1666BFF6A /* [CP] Check Pods Manifest.lock */ = {
|
D9ECCB381CCB547C6D9734F3 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
@ -1500,7 +1500,7 @@
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 48A6FD916DB2F924F1360A4A /* Pods-defaults-RocketChatRN.debug.xcconfig */;
|
baseConfigurationReference = 77A439FBC388926A1D8F1B98 /* Pods-defaults-RocketChatRN.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||||
|
@ -1557,7 +1557,7 @@
|
||||||
};
|
};
|
||||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = AC87BFDE8CC75468C2E87328 /* Pods-defaults-RocketChatRN.release.xcconfig */;
|
baseConfigurationReference = 8CF5ED249C29001A33922AC8 /* Pods-defaults-RocketChatRN.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||||
|
@ -1613,7 +1613,7 @@
|
||||||
};
|
};
|
||||||
1EC6ACBC22CB9FC300A41C61 /* Debug */ = {
|
1EC6ACBC22CB9FC300A41C61 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = C84BF59D4FEA8C08AD41906D /* Pods-defaults-ShareRocketChatRN.debug.xcconfig */;
|
baseConfigurationReference = E956695E229DFCCB2DB61EE2 /* Pods-defaults-ShareRocketChatRN.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
@ -1681,7 +1681,7 @@
|
||||||
};
|
};
|
||||||
1EC6ACBD22CB9FC300A41C61 /* Release */ = {
|
1EC6ACBD22CB9FC300A41C61 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 94EB1DBE281212E61157DDEE /* Pods-defaults-ShareRocketChatRN.release.xcconfig */;
|
baseConfigurationReference = FA35FD80EDA9584432506DDA /* Pods-defaults-ShareRocketChatRN.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
@ -1748,7 +1748,7 @@
|
||||||
};
|
};
|
||||||
1EFEB59D2493B6640072EDC0 /* Debug */ = {
|
1EFEB59D2493B6640072EDC0 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 8009E8CCFAA4804CCED401D8 /* Pods-defaults-NotificationService.debug.xcconfig */;
|
baseConfigurationReference = 9EF17496557D766CD7CC65C8 /* Pods-defaults-NotificationService.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
@ -1785,7 +1785,7 @@
|
||||||
};
|
};
|
||||||
1EFEB59E2493B6640072EDC0 /* Release */ = {
|
1EFEB59E2493B6640072EDC0 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 7E01AFB7FFC99A24DE24A9E7 /* Pods-defaults-NotificationService.release.xcconfig */;
|
baseConfigurationReference = 28F09CD56CC780BB681DA43A /* Pods-defaults-NotificationService.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
@ -1822,7 +1822,7 @@
|
||||||
};
|
};
|
||||||
7AAB3E50257E6A6E00707CF6 /* Debug */ = {
|
7AAB3E50257E6A6E00707CF6 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 04CABACAE3DF5FF44121FC30 /* Pods-defaults-Rocket.Chat.debug.xcconfig */;
|
baseConfigurationReference = 5CA29716AE736DD49CEC421A /* Pods-defaults-Rocket.Chat.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||||
|
@ -1876,7 +1876,7 @@
|
||||||
};
|
};
|
||||||
7AAB3E51257E6A6E00707CF6 /* Release */ = {
|
7AAB3E51257E6A6E00707CF6 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 3AD43034372030994471D0E9 /* Pods-defaults-Rocket.Chat.release.xcconfig */;
|
baseConfigurationReference = D2549B70E3F3979B2FB2F170 /* Pods-defaults-Rocket.Chat.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
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",
|
"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",
|
"postinstall": "patch-package && jetify",
|
||||||
"prepare": "husky install",
|
"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": {
|
"lint-staged": {
|
||||||
"*.{js,ts,tsx}": [
|
"*.{js,ts,tsx}": [
|
||||||
|
@ -55,6 +56,7 @@
|
||||||
"@rocket.chat/message-parser": "^0.31.14",
|
"@rocket.chat/message-parser": "^0.31.14",
|
||||||
"@rocket.chat/sdk": "RocketChat/Rocket.Chat.js.SDK#mobile",
|
"@rocket.chat/sdk": "RocketChat/Rocket.Chat.js.SDK#mobile",
|
||||||
"@rocket.chat/ui-kit": "^0.31.19",
|
"@rocket.chat/ui-kit": "^0.31.19",
|
||||||
|
"@shopify/flash-list": "^1.2.2",
|
||||||
"bytebuffer": "^5.0.1",
|
"bytebuffer": "^5.0.1",
|
||||||
"color2k": "1.2.4",
|
"color2k": "1.2.4",
|
||||||
"commonmark": "git+https://github.com/RocketChat/commonmark.js.git",
|
"commonmark": "git+https://github.com/RocketChat/commonmark.js.git",
|
||||||
|
@ -126,8 +128,8 @@
|
||||||
"react-native-ui-lib": "RocketChat/react-native-ui-lib",
|
"react-native-ui-lib": "RocketChat/react-native-ui-lib",
|
||||||
"react-native-vector-icons": "9.1.0",
|
"react-native-vector-icons": "9.1.0",
|
||||||
"react-native-webview": "10.3.2",
|
"react-native-webview": "10.3.2",
|
||||||
"react-redux": "^8.0.5",
|
"react-redux": "8.0.5",
|
||||||
"reactotron-react-native": "^5.0.3",
|
"reactotron-react-native": "5.0.3",
|
||||||
"redux": "4.2.0",
|
"redux": "4.2.0",
|
||||||
"redux-immutable-state-invariant": "2.1.0",
|
"redux-immutable-state-invariant": "2.1.0",
|
||||||
"redux-saga": "1.1.3",
|
"redux-saga": "1.1.3",
|
||||||
|
@ -206,7 +208,10 @@
|
||||||
"otp.js": "1.2.0",
|
"otp.js": "1.2.0",
|
||||||
"patch-package": "6.4.7",
|
"patch-package": "6.4.7",
|
||||||
"prettier": "^2.3.2",
|
"prettier": "^2.3.2",
|
||||||
|
"react-devtools": "4.27.0",
|
||||||
|
"react-devtools-core": "4.27.0",
|
||||||
"react-dom": "17.0.1",
|
"react-dom": "17.0.1",
|
||||||
|
"react-native-flipper-performance-plugin": "^0.3.1",
|
||||||
"react-test-renderer": "17.0.2",
|
"react-test-renderer": "17.0.2",
|
||||||
"reactotron-redux": "3.1.3",
|
"reactotron-redux": "3.1.3",
|
||||||
"reactotron-redux-saga": "4.2.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