Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] Add Realm.safeAddListener #785

Merged
merged 1 commit into from
Apr 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions app/containers/EmojiPicker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import TabBar from './TabBar';
import EmojiCategory from './EmojiCategory';
import styles from './styles';
import categories from './categories';
import database from '../../lib/realm';
import database, { safeAddListener } from '../../lib/realm';
import { emojisByCategory } from '../../emojis';
import protectedFunction from '../../lib/methods/helpers/protectedFunction';

Expand Down Expand Up @@ -45,8 +45,8 @@ export default class EmojiPicker extends Component {
this.updateFrequentlyUsed();
this.updateCustomEmojis();
requestAnimationFrame(() => this.setState({ show: true }));
this.frequentlyUsed.addListener(this.updateFrequentlyUsed);
this.customEmojis.addListener(this.updateCustomEmojis);
safeAddListener(this.frequentlyUsed, this.updateFrequentlyUsed);
safeAddListener(this.customEmojis, this.updateCustomEmojis);
}

shouldComponentUpdate(nextProps, nextState) {
Expand Down
20 changes: 19 additions & 1 deletion app/lib/realm.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
4 changes: 2 additions & 2 deletions app/lib/rocketchat.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Rocketchat as RocketchatClient } from '@rocket.chat/sdk';
import reduxStore from './createStore';
import defaultSettings from '../constants/settings';
import messagesStatus from '../constants/messagesStatus';
import database from './realm';
import database, { safeAddListener } from './realm';
import log from '../utils/log';
import { isIOS, getBundleId } from '../utils/deviceInfo';

Expand Down Expand Up @@ -65,7 +65,7 @@ const RocketChat = {
if (data.length) {
return resolve(data[0]);
}
data.addListener(() => {
safeAddListener(data, () => {
if (!data.length) { return; }
data.removeAllListeners();
resolve(data[0]);
Expand Down
4 changes: 2 additions & 2 deletions app/views/NewMessageView.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { connect } from 'react-redux';
import { SafeAreaView } from 'react-navigation';
import equal from 'deep-equal';

import database from '../lib/realm';
import database, { safeAddListener } from '../lib/realm';
import RocketChat from '../lib/rocketchat';
import UserItem from '../presentation/UserItem';
import debounce from '../utils/debounce';
Expand Down Expand Up @@ -79,7 +79,7 @@ export default class NewMessageView extends LoggedView {
this.state = {
search: []
};
this.data.addListener(this.updateState);
safeAddListener(this.data, this.updateState);
}

shouldComponentUpdate(nextProps, nextState) {
Expand Down
4 changes: 2 additions & 2 deletions app/views/RoomActionsView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import sharedStyles from '../Styles';
import Avatar from '../../containers/Avatar';
import Status from '../../containers/Status';
import Touch from '../../utils/touch';
import database from '../../lib/realm';
import database, { safeAddListener } from '../../lib/realm';
import RocketChat from '../../lib/rocketchat';
import log from '../../utils/log';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
Expand Down Expand Up @@ -81,7 +81,7 @@ export default class RoomActionsView extends LoggedView {
} else if (room.t === 'd') {
this.updateRoomMember();
}
this.rooms.addListener(this.updateRoom);
safeAddListener(this.rooms, this.updateRoom);
}

shouldComponentUpdate(nextProps, nextState) {
Expand Down
4 changes: 2 additions & 2 deletions app/views/RoomInfoEditView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import sharedStyles from '../Styles';
import styles from './styles';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import { showErrorAlert, showToast } from '../../utils/info';
import database from '../../lib/realm';
import database, { safeAddListener } from '../../lib/realm';
import RocketChat from '../../lib/rocketchat';
import RCTextInput from '../../containers/TextInput';
import Loading from '../../containers/Loading';
Expand Down Expand Up @@ -77,7 +77,7 @@ export default class RoomInfoEditView extends LoggedView {
componentDidMount() {
this.updateRoom();
this.init();
this.rooms.addListener(this.updateRoom);
safeAddListener(this.rooms, this.updateRoom);
const { room } = this.state;
this.permissions = RocketChat.hasPermission(PERMISSIONS_ARRAY, room.rid);
}
Expand Down
4 changes: 2 additions & 2 deletions app/views/RoomInfoView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Status from '../../containers/Status';
import Avatar from '../../containers/Avatar';
import styles from './styles';
import sharedStyles from '../Styles';
import database from '../../lib/realm';
import database, { safeAddListener } from '../../lib/realm';
import RocketChat from '../../lib/rocketchat';
import log from '../../utils/log';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
Expand Down Expand Up @@ -87,7 +87,7 @@ export default class RoomInfoView extends LoggedView {
}

async componentDidMount() {
this.rooms.addListener(this.updateRoom);
safeAddListener(this.rooms, this.updateRoom);
const { room } = this.state;
const permissions = RocketChat.hasPermission([PERMISSION_EDIT_ROOM], room.rid);
if (permissions[PERMISSION_EDIT_ROOM]) {
Expand Down
4 changes: 2 additions & 2 deletions app/views/RoomMembersView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import styles from './styles';
import UserItem from '../../presentation/UserItem';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import RocketChat from '../../lib/rocketchat';
import database from '../../lib/realm';
import database, { safeAddListener } from '../../lib/realm';
import { showToast } from '../../utils/info';
import log from '../../utils/log';
import { vibrate } from '../../utils/vibration';
Expand Down Expand Up @@ -81,7 +81,7 @@ export default class RoomMembersView extends LoggedView {

componentDidMount() {
this.fetchMembers();
this.rooms.addListener(this.updateRoom);
safeAddListener(this.rooms, this.updateRoom);

const { navigation } = this.props;
navigation.setParams({ toggleStatus: this.toggleStatus });
Expand Down
4 changes: 2 additions & 2 deletions app/views/RoomView/List.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import { responsive } from 'react-native-responsive-ui';

import styles from './styles';
import database from '../../lib/realm';
import database, { safeAddListener } from '../../lib/realm';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import debounce from '../../utils/debounce';
import RocketChat from '../../lib/rocketchat';
Expand Down Expand Up @@ -36,7 +36,7 @@ export class List extends React.Component {
messages: this.data.slice(),
showScollToBottomButton: false
};
this.data.addListener(this.updateState);
safeAddListener(this.data, this.updateState);
}

// shouldComponentUpdate(nextProps, nextState) {
Expand Down
4 changes: 2 additions & 2 deletions app/views/RoomView/UploadProgress.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import PropTypes from 'prop-types';
import { responsive } from 'react-native-responsive-ui';
import equal from 'deep-equal';

import database from '../../lib/realm';
import database, { safeAddListener } from '../../lib/realm';
import RocketChat from '../../lib/rocketchat';
import log from '../../utils/log';
import I18n from '../../i18n';
Expand Down Expand Up @@ -74,7 +74,7 @@ export default class UploadProgress extends Component {
};
const { rid } = this.props;
this.uploads = database.objects('uploads').filtered('rid = $0', rid);
this.uploads.addListener(this.updateUploads);
safeAddListener(this.uploads, this.updateUploads);
}

componentDidMount() {
Expand Down
4 changes: 2 additions & 2 deletions app/views/RoomView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { openRoom as openRoomAction, closeRoom as closeRoomAction } from '../../
import { toggleReactionPicker as toggleReactionPickerAction, actionsShow as actionsShowAction } from '../../actions/messages';
import LoggedView from '../View';
import { List } from './List';
import database from '../../lib/realm';
import database, { safeAddListener } from '../../lib/realm';
import RocketChat from '../../lib/rocketchat';
import Message from '../../containers/message';
import MessageActions from '../../containers/MessageActions';
Expand Down Expand Up @@ -114,7 +114,7 @@ export default class RoomView extends LoggedView {
() => this.updateRoom()
);
}
this.rooms.addListener(this.updateRoom);
safeAddListener(this.rooms, this.updateRoom);
this.internalSetState({ loaded: true });
}

Expand Down
4 changes: 2 additions & 2 deletions app/views/RoomsListView/ServerDropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { toggleServerDropdown as toggleServerDropdownAction } from '../../action
import { selectServerRequest as selectServerRequestAction } from '../../actions/server';
import { appStart as appStartAction } from '../../actions';
import styles from './styles';
import database from '../../lib/realm';
import database, { safeAddListener } from '../../lib/realm';
import Touch from '../../utils/touch';
import RocketChat from '../../lib/rocketchat';
import I18n from '../../i18n';
Expand Down Expand Up @@ -46,7 +46,7 @@ class ServerDropdown extends Component {
servers: this.servers
};
this.animatedValue = new Animated.Value(0);
this.servers.addListener(this.updateState);
safeAddListener(this.servers, this.updateState);
}

componentDidMount() {
Expand Down
16 changes: 8 additions & 8 deletions app/views/RoomsListView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Orientation from 'react-native-orientation-locker';

import SearchBox from '../../containers/SearchBox';
import ConnectionBadge from '../../containers/ConnectionBadge';
import database from '../../lib/realm';
import database, { safeAddListener } from '../../lib/realm';
import RocketChat from '../../lib/rocketchat';
import RoomItem, { ROW_HEIGHT } from '../../presentation/RoomItem';
import styles from './styles';
Expand Down Expand Up @@ -277,15 +277,15 @@ export default class RoomsListView extends LoggedView {
if (showUnread) {
this.unread = this.data.filtered('archived != true && open == true').filtered('(unread > 0 || alert == true)');
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 {
this.removeListener(unread);
}
// favorites
if (showFavorites) {
this.favorites = this.data.filtered('f == true');
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 {
this.removeListener(favorites);
}
Expand All @@ -307,10 +307,10 @@ export default class RoomsListView extends LoggedView {
this.livechat = this.data.filtered('t == $0', 'l');
livechat = this.removeRealmInstance(this.livechat);

this.channels.addListener(debounce(() => this.internalSetState({ channels: this.removeRealmInstance(this.channels) }), 300));
this.privateGroup.addListener(debounce(() => this.internalSetState({ privateGroup: this.removeRealmInstance(this.privateGroup) }), 300));
this.direct.addListener(debounce(() => this.internalSetState({ direct: this.removeRealmInstance(this.direct) }), 300));
this.livechat.addListener(debounce(() => this.internalSetState({ livechat: this.removeRealmInstance(this.livechat) }), 300));
safeAddListener(this.channels, debounce(() => this.internalSetState({ channels: this.removeRealmInstance(this.channels) }), 300));
safeAddListener(this.privateGroup, debounce(() => this.internalSetState({ privateGroup: this.removeRealmInstance(this.privateGroup) }), 300));
safeAddListener(this.direct, debounce(() => this.internalSetState({ direct: this.removeRealmInstance(this.direct) }), 300));
safeAddListener(this.livechat, debounce(() => this.internalSetState({ livechat: this.removeRealmInstance(this.livechat) }), 300));
this.removeListener(this.chats);
} else {
// chats
Expand All @@ -321,7 +321,7 @@ export default class RoomsListView extends LoggedView {
}
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.privateGroup);
this.removeListener(this.direct);
Expand Down
4 changes: 2 additions & 2 deletions app/views/SelectedUsersView.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import equal from 'deep-equal';
import {
addUser as addUserAction, removeUser as removeUserAction, reset as resetAction, setLoading as setLoadingAction
} from '../actions/selectedUsers';
import database from '../lib/realm';
import database, { safeAddListener } from '../lib/realm';
import RocketChat from '../lib/rocketchat';
import UserItem from '../presentation/UserItem';
import Loading from '../containers/Loading';
Expand Down Expand Up @@ -88,7 +88,7 @@ export default class SelectedUsersView extends LoggedView {
this.state = {
search: []
};
this.data.addListener(this.updateState);
safeAddListener(this.data, this.updateState);
}

componentDidMount() {
Expand Down