[FIX] Add Realm.safeAddListener (#785)
This commit is contained in:
parent
46a36d7764
commit
2019ec58ce
|
@ -10,7 +10,7 @@ import TabBar from './TabBar';
|
||||||
import EmojiCategory from './EmojiCategory';
|
import EmojiCategory from './EmojiCategory';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import categories from './categories';
|
import categories from './categories';
|
||||||
import database from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import { emojisByCategory } from '../../emojis';
|
import { emojisByCategory } from '../../emojis';
|
||||||
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
|
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ export default class EmojiPicker extends Component {
|
||||||
this.updateFrequentlyUsed();
|
this.updateFrequentlyUsed();
|
||||||
this.updateCustomEmojis();
|
this.updateCustomEmojis();
|
||||||
requestAnimationFrame(() => this.setState({ show: true }));
|
requestAnimationFrame(() => this.setState({ show: true }));
|
||||||
this.frequentlyUsed.addListener(this.updateFrequentlyUsed);
|
safeAddListener(this.frequentlyUsed, this.updateFrequentlyUsed);
|
||||||
this.customEmojis.addListener(this.updateCustomEmojis);
|
safeAddListener(this.customEmojis, this.updateCustomEmojis);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
|
|
@ -346,4 +346,22 @@ class DB {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default new DB();
|
const db = new DB();
|
||||||
|
export default db;
|
||||||
|
|
||||||
|
// Realm workaround for "Cannot create asynchronous query while in a write transaction"
|
||||||
|
// inpired from https://github.com/realm/realm-js/issues/1188#issuecomment-359223918
|
||||||
|
export function safeAddListener(results, callback, database = db) {
|
||||||
|
if (!results || !results.addListener) {
|
||||||
|
console.log('⚠️ safeAddListener called for non addListener-compliant object');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (database.isInTransaction) {
|
||||||
|
setTimeout(() => {
|
||||||
|
safeAddListener(results, callback);
|
||||||
|
}, 50);
|
||||||
|
} else {
|
||||||
|
results.addListener(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { Rocketchat as RocketchatClient } from '@rocket.chat/sdk';
|
||||||
import reduxStore from './createStore';
|
import reduxStore from './createStore';
|
||||||
import defaultSettings from '../constants/settings';
|
import defaultSettings from '../constants/settings';
|
||||||
import messagesStatus from '../constants/messagesStatus';
|
import messagesStatus from '../constants/messagesStatus';
|
||||||
import database from './realm';
|
import database, { safeAddListener } from './realm';
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
import { isIOS, getBundleId } from '../utils/deviceInfo';
|
import { isIOS, getBundleId } from '../utils/deviceInfo';
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ const RocketChat = {
|
||||||
if (data.length) {
|
if (data.length) {
|
||||||
return resolve(data[0]);
|
return resolve(data[0]);
|
||||||
}
|
}
|
||||||
data.addListener(() => {
|
safeAddListener(data, () => {
|
||||||
if (!data.length) { return; }
|
if (!data.length) { return; }
|
||||||
data.removeAllListeners();
|
data.removeAllListeners();
|
||||||
resolve(data[0]);
|
resolve(data[0]);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { connect } from 'react-redux';
|
||||||
import { SafeAreaView } from 'react-navigation';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import database from '../lib/realm';
|
import database, { safeAddListener } from '../lib/realm';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import UserItem from '../presentation/UserItem';
|
import UserItem from '../presentation/UserItem';
|
||||||
import debounce from '../utils/debounce';
|
import debounce from '../utils/debounce';
|
||||||
|
@ -79,7 +79,7 @@ export default class NewMessageView extends LoggedView {
|
||||||
this.state = {
|
this.state = {
|
||||||
search: []
|
search: []
|
||||||
};
|
};
|
||||||
this.data.addListener(this.updateState);
|
safeAddListener(this.data, this.updateState);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import sharedStyles from '../Styles';
|
||||||
import Avatar from '../../containers/Avatar';
|
import Avatar from '../../containers/Avatar';
|
||||||
import Status from '../../containers/Status';
|
import Status from '../../containers/Status';
|
||||||
import Touch from '../../utils/touch';
|
import Touch from '../../utils/touch';
|
||||||
import database from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
||||||
|
@ -81,7 +81,7 @@ export default class RoomActionsView extends LoggedView {
|
||||||
} else if (room.t === 'd') {
|
} else if (room.t === 'd') {
|
||||||
this.updateRoomMember();
|
this.updateRoomMember();
|
||||||
}
|
}
|
||||||
this.rooms.addListener(this.updateRoom);
|
safeAddListener(this.rooms, this.updateRoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import sharedStyles from '../Styles';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
import { showErrorAlert, showToast } from '../../utils/info';
|
import { showErrorAlert, showToast } from '../../utils/info';
|
||||||
import database from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import RCTextInput from '../../containers/TextInput';
|
import RCTextInput from '../../containers/TextInput';
|
||||||
import Loading from '../../containers/Loading';
|
import Loading from '../../containers/Loading';
|
||||||
|
@ -77,7 +77,7 @@ export default class RoomInfoEditView extends LoggedView {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.updateRoom();
|
this.updateRoom();
|
||||||
this.init();
|
this.init();
|
||||||
this.rooms.addListener(this.updateRoom);
|
safeAddListener(this.rooms, this.updateRoom);
|
||||||
const { room } = this.state;
|
const { room } = this.state;
|
||||||
this.permissions = RocketChat.hasPermission(PERMISSIONS_ARRAY, room.rid);
|
this.permissions = RocketChat.hasPermission(PERMISSIONS_ARRAY, room.rid);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import Status from '../../containers/Status';
|
||||||
import Avatar from '../../containers/Avatar';
|
import Avatar from '../../containers/Avatar';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import sharedStyles from '../Styles';
|
import sharedStyles from '../Styles';
|
||||||
import database from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
||||||
|
@ -87,7 +87,7 @@ export default class RoomInfoView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
this.rooms.addListener(this.updateRoom);
|
safeAddListener(this.rooms, this.updateRoom);
|
||||||
const { room } = this.state;
|
const { room } = this.state;
|
||||||
const permissions = RocketChat.hasPermission([PERMISSION_EDIT_ROOM], room.rid);
|
const permissions = RocketChat.hasPermission([PERMISSION_EDIT_ROOM], room.rid);
|
||||||
if (permissions[PERMISSION_EDIT_ROOM]) {
|
if (permissions[PERMISSION_EDIT_ROOM]) {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import styles from './styles';
|
||||||
import UserItem from '../../presentation/UserItem';
|
import UserItem from '../../presentation/UserItem';
|
||||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import database from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import { showToast } from '../../utils/info';
|
import { showToast } from '../../utils/info';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import { vibrate } from '../../utils/vibration';
|
import { vibrate } from '../../utils/vibration';
|
||||||
|
@ -81,7 +81,7 @@ export default class RoomMembersView extends LoggedView {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.fetchMembers();
|
this.fetchMembers();
|
||||||
this.rooms.addListener(this.updateRoom);
|
safeAddListener(this.rooms, this.updateRoom);
|
||||||
|
|
||||||
const { navigation } = this.props;
|
const { navigation } = this.props;
|
||||||
navigation.setParams({ toggleStatus: this.toggleStatus });
|
navigation.setParams({ toggleStatus: this.toggleStatus });
|
||||||
|
|
|
@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
||||||
import { responsive } from 'react-native-responsive-ui';
|
import { responsive } from 'react-native-responsive-ui';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import database from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
import debounce from '../../utils/debounce';
|
import debounce from '../../utils/debounce';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
@ -36,7 +36,7 @@ export class List extends React.Component {
|
||||||
messages: this.data.slice(),
|
messages: this.data.slice(),
|
||||||
showScollToBottomButton: false
|
showScollToBottomButton: false
|
||||||
};
|
};
|
||||||
this.data.addListener(this.updateState);
|
safeAddListener(this.data, this.updateState);
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldComponentUpdate(nextProps, nextState) {
|
// shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import PropTypes from 'prop-types';
|
||||||
import { responsive } from 'react-native-responsive-ui';
|
import { responsive } from 'react-native-responsive-ui';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import database from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
|
@ -74,7 +74,7 @@ export default class UploadProgress extends Component {
|
||||||
};
|
};
|
||||||
const { rid } = this.props;
|
const { rid } = this.props;
|
||||||
this.uploads = database.objects('uploads').filtered('rid = $0', rid);
|
this.uploads = database.objects('uploads').filtered('rid = $0', rid);
|
||||||
this.uploads.addListener(this.updateUploads);
|
safeAddListener(this.uploads, this.updateUploads);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { openRoom as openRoomAction, closeRoom as closeRoomAction } from '../../
|
||||||
import { toggleReactionPicker as toggleReactionPickerAction, actionsShow as actionsShowAction } from '../../actions/messages';
|
import { toggleReactionPicker as toggleReactionPickerAction, actionsShow as actionsShowAction } from '../../actions/messages';
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
import { List } from './List';
|
import { List } from './List';
|
||||||
import database from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import Message from '../../containers/message';
|
import Message from '../../containers/message';
|
||||||
import MessageActions from '../../containers/MessageActions';
|
import MessageActions from '../../containers/MessageActions';
|
||||||
|
@ -114,7 +114,7 @@ export default class RoomView extends LoggedView {
|
||||||
() => this.updateRoom()
|
() => this.updateRoom()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.rooms.addListener(this.updateRoom);
|
safeAddListener(this.rooms, this.updateRoom);
|
||||||
this.internalSetState({ loaded: true });
|
this.internalSetState({ loaded: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { toggleServerDropdown as toggleServerDropdownAction } from '../../action
|
||||||
import { selectServerRequest as selectServerRequestAction } from '../../actions/server';
|
import { selectServerRequest as selectServerRequestAction } from '../../actions/server';
|
||||||
import { appStart as appStartAction } from '../../actions';
|
import { appStart as appStartAction } from '../../actions';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import database from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import Touch from '../../utils/touch';
|
import Touch from '../../utils/touch';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
|
@ -46,7 +46,7 @@ class ServerDropdown extends Component {
|
||||||
servers: this.servers
|
servers: this.servers
|
||||||
};
|
};
|
||||||
this.animatedValue = new Animated.Value(0);
|
this.animatedValue = new Animated.Value(0);
|
||||||
this.servers.addListener(this.updateState);
|
safeAddListener(this.servers, this.updateState);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import Orientation from 'react-native-orientation-locker';
|
||||||
|
|
||||||
import SearchBox from '../../containers/SearchBox';
|
import SearchBox from '../../containers/SearchBox';
|
||||||
import ConnectionBadge from '../../containers/ConnectionBadge';
|
import ConnectionBadge from '../../containers/ConnectionBadge';
|
||||||
import database from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import RoomItem, { ROW_HEIGHT } from '../../presentation/RoomItem';
|
import RoomItem, { ROW_HEIGHT } from '../../presentation/RoomItem';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
@ -277,7 +277,7 @@ export default class RoomsListView extends LoggedView {
|
||||||
if (showUnread) {
|
if (showUnread) {
|
||||||
this.unread = this.data.filtered('archived != true && open == true').filtered('(unread > 0 || alert == true)');
|
this.unread = this.data.filtered('archived != true && open == true').filtered('(unread > 0 || alert == true)');
|
||||||
unread = this.removeRealmInstance(this.unread);
|
unread = this.removeRealmInstance(this.unread);
|
||||||
this.unread.addListener(debounce(() => this.internalSetState({ unread: this.removeRealmInstance(this.unread) }), 300));
|
safeAddListener(this.unread, debounce(() => this.internalSetState({ unread: this.removeRealmInstance(this.unread) }), 300));
|
||||||
} else {
|
} else {
|
||||||
this.removeListener(unread);
|
this.removeListener(unread);
|
||||||
}
|
}
|
||||||
|
@ -285,7 +285,7 @@ export default class RoomsListView extends LoggedView {
|
||||||
if (showFavorites) {
|
if (showFavorites) {
|
||||||
this.favorites = this.data.filtered('f == true');
|
this.favorites = this.data.filtered('f == true');
|
||||||
favorites = this.removeRealmInstance(this.favorites);
|
favorites = this.removeRealmInstance(this.favorites);
|
||||||
this.favorites.addListener(debounce(() => this.internalSetState({ favorites: this.removeRealmInstance(this.favorites) }), 300));
|
safeAddListener(this.favorites, debounce(() => this.internalSetState({ favorites: this.removeRealmInstance(this.favorites) }), 300));
|
||||||
} else {
|
} else {
|
||||||
this.removeListener(favorites);
|
this.removeListener(favorites);
|
||||||
}
|
}
|
||||||
|
@ -307,10 +307,10 @@ export default class RoomsListView extends LoggedView {
|
||||||
this.livechat = this.data.filtered('t == $0', 'l');
|
this.livechat = this.data.filtered('t == $0', 'l');
|
||||||
livechat = this.removeRealmInstance(this.livechat);
|
livechat = this.removeRealmInstance(this.livechat);
|
||||||
|
|
||||||
this.channels.addListener(debounce(() => this.internalSetState({ channels: this.removeRealmInstance(this.channels) }), 300));
|
safeAddListener(this.channels, debounce(() => this.internalSetState({ channels: this.removeRealmInstance(this.channels) }), 300));
|
||||||
this.privateGroup.addListener(debounce(() => this.internalSetState({ privateGroup: this.removeRealmInstance(this.privateGroup) }), 300));
|
safeAddListener(this.privateGroup, debounce(() => this.internalSetState({ privateGroup: this.removeRealmInstance(this.privateGroup) }), 300));
|
||||||
this.direct.addListener(debounce(() => this.internalSetState({ direct: this.removeRealmInstance(this.direct) }), 300));
|
safeAddListener(this.direct, debounce(() => this.internalSetState({ direct: this.removeRealmInstance(this.direct) }), 300));
|
||||||
this.livechat.addListener(debounce(() => this.internalSetState({ livechat: this.removeRealmInstance(this.livechat) }), 300));
|
safeAddListener(this.livechat, debounce(() => this.internalSetState({ livechat: this.removeRealmInstance(this.livechat) }), 300));
|
||||||
this.removeListener(this.chats);
|
this.removeListener(this.chats);
|
||||||
} else {
|
} else {
|
||||||
// chats
|
// chats
|
||||||
|
@ -321,7 +321,7 @@ export default class RoomsListView extends LoggedView {
|
||||||
}
|
}
|
||||||
chats = this.removeRealmInstance(this.chats);
|
chats = this.removeRealmInstance(this.chats);
|
||||||
|
|
||||||
this.chats.addListener(debounce(() => this.internalSetState({ chats: this.removeRealmInstance(this.chats) }), 300));
|
safeAddListener(this.chats, debounce(() => this.internalSetState({ chats: this.removeRealmInstance(this.chats) }), 300));
|
||||||
this.removeListener(this.channels);
|
this.removeListener(this.channels);
|
||||||
this.removeListener(this.privateGroup);
|
this.removeListener(this.privateGroup);
|
||||||
this.removeListener(this.direct);
|
this.removeListener(this.direct);
|
||||||
|
|
|
@ -10,7 +10,7 @@ import equal from 'deep-equal';
|
||||||
import {
|
import {
|
||||||
addUser as addUserAction, removeUser as removeUserAction, reset as resetAction, setLoading as setLoadingAction
|
addUser as addUserAction, removeUser as removeUserAction, reset as resetAction, setLoading as setLoadingAction
|
||||||
} from '../actions/selectedUsers';
|
} from '../actions/selectedUsers';
|
||||||
import database from '../lib/realm';
|
import database, { safeAddListener } from '../lib/realm';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import UserItem from '../presentation/UserItem';
|
import UserItem from '../presentation/UserItem';
|
||||||
import Loading from '../containers/Loading';
|
import Loading from '../containers/Loading';
|
||||||
|
@ -88,7 +88,7 @@ export default class SelectedUsersView extends LoggedView {
|
||||||
this.state = {
|
this.state = {
|
||||||
search: []
|
search: []
|
||||||
};
|
};
|
||||||
this.data.addListener(this.updateState);
|
safeAddListener(this.data, this.updateState);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
|
Loading…
Reference in New Issue