// Copyright 2014-2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only /* global _ */ /* eslint-disable more/no-then */ // eslint-disable-next-line func-names (function () { window.Whisper = window.Whisper || {}; let ready = false; let items; let callbacks = []; reset(); async function put(key, value) { if (value === undefined) { window.log.warn(`storage/put: undefined provided for key ${key}`); } if (!ready) { window.log.warn('Called storage.put before storage is ready. key:', key); } const data = { id: key, value }; items[key] = data; await window.Signal.Data.createOrUpdateItem(data); if (_.has(window, ['reduxActions', 'items', 'putItemExternal'])) { window.reduxActions.items.putItemExternal(key, value); } } function get(key, defaultValue) { if (!ready) { window.log.warn('Called storage.get before storage is ready. key:', key); } const item = items[key]; if (!item) { return defaultValue; } return item.value; } async function remove(key) { if (!ready) { window.log.warn( 'Called storage.remove before storage is ready. key:', key ); } delete items[key]; await window.Signal.Data.removeItemById(key); if (_.has(window, ['reduxActions', 'items', 'removeItemExternal'])) { window.reduxActions.items.removeItemExternal(key); } } function onready(callback) { if (ready) { callback(); } else { callbacks.push(callback); } } function callListeners() { if (ready) { callbacks.forEach(callback => callback()); callbacks = []; } } async function fetch() { this.reset(); const array = await window.Signal.Data.getAllItems(); for (let i = 0, max = array.length; i < max; i += 1) { const item = array[i]; const { id } = item; items[id] = item; } ready = true; callListeners(); } function getItemsState() { const data = _.clone(items); const ids = Object.keys(data); ids.forEach(id => { data[id] = data[id].value; }); return data; } function reset() { ready = false; items = Object.create(null); } const storage = { fetch, put, get, getItemsState, remove, onready, reset, }; // Keep a reference to this storage system, since there are scenarios where // we need to replace it with the legacy storage system for a while. window.newStorage = storage; window.textsecure = window.textsecure || {}; window.textsecure.storage = window.textsecure.storage || {}; window.installStorage = newStorage => { window.storage = newStorage; window.textsecure.storage.impl = newStorage; }; window.installStorage(storage); })();