Implement and use pymStorage

This commit is contained in:
Chi Vinh Le
2017-09-09 00:11:15 +07:00
parent 244a4b108d
commit 9f33a77745
6 changed files with 102 additions and 11 deletions
@@ -92,12 +92,6 @@ const singleCommentFragment = gql`
const withCommentFragments = withFragments({
root: gql`
fragment CoralEmbedStream_Comment_root on RootQuery {
me {
ignoredUsers {
id
}
}
__typename
me {
ignoredUsers {
id
+4
View File
@@ -3,6 +3,7 @@ import pym from 'pym.js';
import EventEmitter from 'eventemitter2';
import {buildUrl} from 'coral-framework/utils/url';
import Snackbar from './Snackbar';
import {createStorage, connectStorageToPym} from 'coral-framework/services/storage';
const NOTIFICATION_OFFSET = 200;
@@ -134,6 +135,9 @@ export default class Stream {
// If the user clicks outside the embed, then tell the embed.
document.addEventListener('click', this.handleClick.bind(this), true);
// Listens to storage requests on pym and relay it to local storage.
connectStorageToPym(createStorage(), this.pym);
}
login(token) {
+1 -1
View File
@@ -83,7 +83,7 @@ Talk.render = (el, opts) => {
console.warn(
'This page does not include a canonical link tag. Talk has inferred this asset_url from the window object. Query params have been stripped, which may cause a single thread to be present across multiple pages.'
);
if (!window.location.origin) {
window.location.origin = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}`;
}
+3 -1
View File
@@ -12,7 +12,7 @@ import {createPluginsService} from './plugins';
import {createNotificationService} from './notification';
import {createGraphQLRegistry} from './graphqlRegistry';
import globalFragments from 'coral-framework/graphql/fragments';
import {createStorage} from 'coral-framework/services/storage';
import {createStorage, createPymStorage} from 'coral-framework/services/storage';
import {createHistory} from 'coral-framework/services/history';
import {createIntrospection} from 'coral-framework/services/introspection';
import introspectionData from 'coral-framework/graphql/introspection.json';
@@ -81,6 +81,7 @@ export async function createContext({
} = {}) {
const eventEmitter = new EventEmitter({wildcard: true});
const storage = createStorage();
const pymStorage = createPymStorage(pym);
const history = createHistory(BASE_PATH);
const introspection = createIntrospection(introspectionData);
let store = null;
@@ -137,6 +138,7 @@ export async function createContext({
storage,
history,
introspection,
pymStorage,
};
// Load framework fragments.
@@ -1,3 +1,4 @@
import uuid from 'uuid/v4';
function getStorage(type) {
let storage = window[type], x = '__storage_test__';
@@ -41,3 +42,90 @@ function getStorage(type) {
export function createStorage() {
return getStorage('localStorage');
}
/**
* Creates a storage that relay requests over to pym.
* This is the counterpart of `connectStorageToPym`.
* @param {string} pym pym
* @return {Object} storage
*/
export function createPymStorage(pym) {
// A Map of requestID => {resolve, reject}
const requests = {};
// Requests method with parameters over pym.
const call = (method, parameters) => {
const id = uuid();
return new Promise((resolve, reject) => {
requests[id] = {resolve, reject};
pym.sendMessage('pymStorage.request', JSON.stringify({id, method, parameters}));
});
};
// Receive successful responses.
pym.onMessage('pymStorage.response', (msg) => {
const {id, result} = JSON.parse(msg);
requests[id].resolve(result);
delete requests[id];
});
// Receive error responses.
pym.onMessage('pymStorage.error', (msg) => {
const {id, error} = JSON.parse(msg);
requests[id].reject(error);
delete requests[id];
});
return {
setItem: (key, value) => call('setItem', {key, value}),
getItem: (key, value) => call('getItem', {key, value}),
removeItem: (key) => call('removeItem', {key}),
};
}
/**
* Listens to `pym` and relay storage requests to `storage`.
* This is the counterpart of `createPymStorage`.
* @param {string} pym pym
* @return {Object} storage
*/
export function connectStorageToPym(storage, pym) {
pym.onMessage('pymStorage.request', (msg) => {
const {id, method, parameters} = JSON.parse(msg);
const {key, value} = parameters;
const prefixedKey = `talkPymStorage:${key}`;
// Variable for the method return value.
let result;
const sendError = (error) => {
console.error(error);
pym.sendMessage('pymStorage.error', JSON.stringify({id, error}));
};
try {
switch(method) {
case 'setItem':
result = storage.setItem(prefixedKey, value);
break;
case 'getItem':
result = storage.getItem(prefixedKey);
break;
case 'removeItem':
result = storage.removeItem(prefixedKey);
break;
default:
sendError(`Unknown method ${method}`);
return;
}
}
catch(err) {
sendError(err.toString());
return;
}
pym.sendMessage('pymStorage.response', JSON.stringify({id, result}));
});
}
@@ -4,7 +4,7 @@ import {sortOrderSelector, sortBySelector} from 'plugin-api/beta/client/selector
const STORAGE_PATH = 'talkPluginRememberSort';
export default {
init: ({store, storage, introspection}) => {
init: async ({store, pymStorage, introspection}) => {
// TODO: workaround as this plugin is included in any target and
// embeds (e.g. admin), but should only be included inside the stream.
@@ -14,7 +14,10 @@ export default {
return;
}
let sort = JSON.parse(storage.getItem(STORAGE_PATH));
// We use pymStorage instead to persist the data directly on the parent page,
// in order to mitigate strict cross domain security settings.
let sort = JSON.parse(await pymStorage.getItem(STORAGE_PATH));
if (
sort &&
introspection.isValidEnumValue('SORT_ORDER', sort.sortOrder) &&
@@ -30,7 +33,7 @@ export default {
// Save sorting choice to storage if it has changed.
if (!sort || sort.sortOrder !== sortOrder || sort.sortBy !== sortBy) {
sort = {sortOrder, sortBy};
storage.setItem(STORAGE_PATH, JSON.stringify(sort));
pymStorage.setItem(STORAGE_PATH, JSON.stringify(sort));
}
});
}