Commit 3006c527 authored by Renato Becker's avatar Renato Becker Committed by Guilherme Gazzo

Improvements when storing messages (#176)

Closes #174 
Closes #144
When the `Show Read Receipts` setting is enabled or when a message is edited, the SDK `onMessage` method will be emitted, but we're always inserting the incoming message, instead of updating messages already stored.
parent 47998b51
No preview for this file type
......@@ -65,16 +65,17 @@ export const throttle = (func, limit) => {
};
};
export function sort(array, value) {
export function getInsertIndex(array, item, ranking) {
const order = ranking(item);
let min = 0;
let max = array.length - 1;
while (min <= max) {
const guess = Math.floor((min + max) / 2);
const { ts } = array[guess];
if (ts < value) {
const guessedOrder = ranking(array[guess]);
if (guessedOrder < order) {
min = guess + 1;
} else if (ts > array[guess + 1]) {
} else if (guessedOrder > array[guess + 1]) {
return guess;
} else {
max = guess - 1;
......@@ -84,7 +85,17 @@ export function sort(array, value) {
return array.length > 0 ? array.length : 0;
}
export const insert = (array, el) => (array.splice(sort(array, el.ts), 0, el), array);
export function upsert(array, item, predicate, ranking) {
const index = array.findIndex(predicate);
if (index > -1) {
array[index] = item;
return array;
}
array.splice(getInsertIndex(array, item, ranking), 0, item);
return array;
}
export const setCookies = (rid, token) => {
document.cookie = `rc_rid=${ rid }; path=/`;
......
import format from 'date-fns/format';
import { Livechat } from '../api';
import store from '../store';
import { insert } from '../components/helpers';
import constants from '../lib/constants';
......@@ -53,7 +52,7 @@ export const processUnread = async() => {
});
const alert = { id: constants.unreadMessagesAlertId, children: alertMessage, success: true, timeout: 0 };
const newAlerts = alerts.filter((item) => item.id !== constants.unreadMessagesAlertId);
await store.setState({ alerts: insert(newAlerts, alert) });
await store.setState({ alerts: (newAlerts.push(alert), newAlerts) });
}
await store.setState({ unread: unreadMessages.length });
......
import { route } from 'preact-router';
import { Livechat } from '../api';
import store from '../store';
import { insert, createToken, asyncForEach } from '../components/helpers';
import { upsert, createToken, asyncForEach } from '../components/helpers';
import { parentCall } from './parentCall';
import { processUnread } from './main';
......@@ -112,7 +112,10 @@ class Triggers {
_id: createToken(),
};
await store.setState({ triggered: true, messages: insert(store.state.messages, message).filter(({ msg }) => ({ msg })) });
await store.setState({
triggered: true,
messages: upsert(store.state.messages, message, ({ _id }) => _id === message._id, ({ ts }) => ts),
});
await processUnread();
if (agent && agent._id) {
......
......@@ -4,7 +4,7 @@ import { Livechat } from '../../api';
import { Consumer } from '../../store';
import { loadConfig } from '../../lib/main';
import constants from '../../lib/constants';
import { createToken, debounce, getAvatarUrl, insert, renderMessage, throttle } from '../../components/helpers';
import { createToken, debounce, getAvatarUrl, renderMessage, throttle } from '../../components/helpers';
import Chat from './component';
import { ModalManager } from '../../components/Modal';
import { initRoom, closeChat } from './room';
......@@ -73,7 +73,7 @@ export class ChatContainer extends Component {
} catch (error) {
const { data: { error: reason } } = error;
const alert = { id: createToken(), children: I18n.t('Error starting a new conversation: %{reason}', { reason }), error: true, timeout: 10000 };
await dispatch({ loading: false, alerts: insert(alerts, alert) });
await dispatch({ loading: false, alerts: (alerts.push(alert), alerts) });
throw error;
} finally {
await dispatch({ loading: false });
......@@ -120,7 +120,7 @@ export class ChatContainer extends Component {
await loadConfig();
const { data: { error: reason } } = error;
const alert = { id: createToken(), children: reason, error: true, timeout: 5000 };
await dispatch({ alerts: insert(alerts, alert) });
await dispatch({ alerts: (alerts.push(alert), alerts) });
}
await Livechat.notifyVisitorTyping(rid, user.username, false);
......@@ -144,7 +144,7 @@ export class ChatContainer extends Component {
}
const alert = { id: createToken(), children: message, error: true, timeout: 5000 };
await dispatch({ alerts: insert(alerts, alert) });
await dispatch({ alerts: (alerts.push(alert), alerts) });
}
};
......@@ -185,7 +185,7 @@ export class ChatContainer extends Component {
} catch (error) {
console.error(error);
const alert = { id: createToken(), children: 'Error closing chat.', error: true, timeout: 0 };
await dispatch({ alerts: insert(alerts, alert) });
await dispatch({ alerts: (alerts.push(alert), alerts) });
} finally {
await dispatch({ loading: false });
await closeChat();
......@@ -209,7 +209,7 @@ export class ChatContainer extends Component {
} catch (error) {
console.error(error);
const alert = { id: createToken(), children: 'Error removing user data.', error: true, timeout: 0 };
await dispatch({ alerts: insert(alerts, alert) });
await dispatch({ alerts: (alerts.push(alert), alerts) });
} finally {
await loadConfig();
await dispatch({ loading: false });
......
import { Livechat } from '../../api';
import { store } from '../../store';
import { route } from 'preact-router';
import { insert, setCookies } from '../../components/helpers';
import { setCookies, upsert } from '../../components/helpers';
import Commands from '../../lib/commands';
import { loadConfig, processUnread } from '../../lib/main';
import { parentCall } from '../../lib/parentCall';
......@@ -89,8 +89,12 @@ Livechat.onTyping((username, isTyping) => {
});
Livechat.onMessage(async(message) => {
if (message.ts instanceof Date) {
message.ts = message.ts.toISOString();
}
await store.setState({
messages: insert(store.state.messages, message).filter(({ msg, attachments }) => ({ msg, attachments })),
messages: upsert(store.state.messages, message, ({ _id }) => _id === message._id, ({ ts }) => ts),
});
await processMessage(message);
await processUnread();
......
......@@ -3,7 +3,7 @@ import { Livechat } from '../../api';
import { parentCall } from '../../lib/parentCall';
import { Consumer } from '../../store';
import LeaveMessage from './component';
import { insert, createToken } from '../../components/helpers';
import { createToken } from '../../components/helpers';
export class LeaveMessageContainer extends Component {
......@@ -14,13 +14,13 @@ export class LeaveMessageContainer extends Component {
try {
const message = await Livechat.sendOfflineMessage(fields);
const success = { id: createToken(), children: successMessage || message, success: true, timeout: 5000 };
await dispatch({ alerts: insert(alerts, success) });
await dispatch({ alerts: (alerts.push(success), alerts) });
parentCall('callback', ['offline-form-submit', fields]);
} catch (error) {
const { data: { message } } = error;
console.error(message);
const alert = { id: createToken(), children: message, error: true, timeout: 0 };
await dispatch({ alerts: insert(alerts, alert) });
await dispatch({ alerts: (alerts.push(alert), alerts) });
} finally {
await dispatch({ loading: false });
}
......
......@@ -4,7 +4,7 @@ import { loadConfig } from '../../lib/main';
import { Consumer } from '../../store';
import SwitchDepartment from './component';
import { ModalManager } from '../../components/Modal';
import { createToken, insert } from '../../components/helpers';
import { createToken } from '../../components/helpers';
import history from '../../history';
export class SwitchDepartmentContainer extends Component {
......@@ -44,7 +44,7 @@ export class SwitchDepartmentContainer extends Component {
history.go(-1);
} catch (error) {
console.error(error);
await dispatch({ alerts: insert(alerts, { id: createToken(), children: I18n.t('No available agents to transfer'), warning: true, timeout: 5000 }) });
await dispatch({ alerts: (alerts.push({ id: createToken(), children: I18n.t('No available agents to transfer'), warning: true, timeout: 5000 }), alerts) });
} finally {
await dispatch({ loading: false });
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment