forked from mystiq/hydrogen-web
convert tabs to spaces where needed
This commit is contained in:
parent
56ae6670be
commit
cd9f25ea80
10 changed files with 340 additions and 340 deletions
|
@ -1,36 +1,36 @@
|
|||
export default class EventEmitter {
|
||||
constructor() {
|
||||
this._handlersByName = {};
|
||||
}
|
||||
constructor() {
|
||||
this._handlersByName = {};
|
||||
}
|
||||
|
||||
emit(name, ...values) {
|
||||
const handlers = this._handlersByName[name];
|
||||
if (handlers) {
|
||||
for(const h of handlers) {
|
||||
h(...values);
|
||||
}
|
||||
}
|
||||
}
|
||||
emit(name, ...values) {
|
||||
const handlers = this._handlersByName[name];
|
||||
if (handlers) {
|
||||
for(const h of handlers) {
|
||||
h(...values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
on(name, callback) {
|
||||
let handlers = this._handlersByName[name];
|
||||
if (!handlers) {
|
||||
on(name, callback) {
|
||||
let handlers = this._handlersByName[name];
|
||||
if (!handlers) {
|
||||
this.onFirstSubscriptionAdded(name);
|
||||
this._handlersByName[name] = handlers = new Set();
|
||||
}
|
||||
handlers.add(callback);
|
||||
}
|
||||
this._handlersByName[name] = handlers = new Set();
|
||||
}
|
||||
handlers.add(callback);
|
||||
}
|
||||
|
||||
off(name, callback) {
|
||||
const handlers = this._handlersByName[name];
|
||||
if (handlers) {
|
||||
handlers.delete(callback);
|
||||
if (handlers.length === 0) {
|
||||
delete this._handlersByName[name];
|
||||
off(name, callback) {
|
||||
const handlers = this._handlersByName[name];
|
||||
if (handlers) {
|
||||
handlers.delete(callback);
|
||||
if (handlers.length === 0) {
|
||||
delete this._handlersByName[name];
|
||||
this.onLastSubscriptionRemoved(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onFirstSubscriptionAdded(name) {}
|
||||
|
||||
|
@ -38,38 +38,38 @@ export default class EventEmitter {
|
|||
}
|
||||
//#ifdef TESTS
|
||||
export function tests() {
|
||||
return {
|
||||
test_on_off(assert) {
|
||||
let counter = 0;
|
||||
const e = new EventEmitter();
|
||||
const callback = () => counter += 1;
|
||||
e.on("change", callback);
|
||||
e.emit("change");
|
||||
e.off("change", callback);
|
||||
e.emit("change");
|
||||
assert.equal(counter, 1);
|
||||
},
|
||||
return {
|
||||
test_on_off(assert) {
|
||||
let counter = 0;
|
||||
const e = new EventEmitter();
|
||||
const callback = () => counter += 1;
|
||||
e.on("change", callback);
|
||||
e.emit("change");
|
||||
e.off("change", callback);
|
||||
e.emit("change");
|
||||
assert.equal(counter, 1);
|
||||
},
|
||||
|
||||
test_emit_value(assert) {
|
||||
let value = 0;
|
||||
const e = new EventEmitter();
|
||||
const callback = (v) => value = v;
|
||||
e.on("change", callback);
|
||||
e.emit("change", 5);
|
||||
e.off("change", callback);
|
||||
assert.equal(value, 5);
|
||||
},
|
||||
test_emit_value(assert) {
|
||||
let value = 0;
|
||||
const e = new EventEmitter();
|
||||
const callback = (v) => value = v;
|
||||
e.on("change", callback);
|
||||
e.emit("change", 5);
|
||||
e.off("change", callback);
|
||||
assert.equal(value, 5);
|
||||
},
|
||||
|
||||
test_double_on(assert) {
|
||||
let counter = 0;
|
||||
const e = new EventEmitter();
|
||||
const callback = () => counter += 1;
|
||||
e.on("change", callback);
|
||||
e.on("change", callback);
|
||||
e.emit("change");
|
||||
e.off("change", callback);
|
||||
assert.equal(counter, 1);
|
||||
}
|
||||
};
|
||||
test_double_on(assert) {
|
||||
let counter = 0;
|
||||
const e = new EventEmitter();
|
||||
const callback = () => counter += 1;
|
||||
e.on("change", callback);
|
||||
e.on("change", callback);
|
||||
e.emit("change");
|
||||
e.off("change", callback);
|
||||
assert.equal(counter, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
//#endif
|
||||
|
|
40
src/main.js
40
src/main.js
|
@ -12,14 +12,14 @@ const USER_ID = `@${USERNAME}:localhost`;
|
|||
const PASSWORD = "testtest";
|
||||
|
||||
function getSessionInfo(userId) {
|
||||
const sessionsJson = localStorage.getItem("brawl_sessions_v1");
|
||||
if (sessionsJson) {
|
||||
const sessions = JSON.parse(sessionsJson);
|
||||
const session = sessions.find(session => session.userId === userId);
|
||||
if (session) {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
const sessionsJson = localStorage.getItem("brawl_sessions_v1");
|
||||
if (sessionsJson) {
|
||||
const sessions = JSON.parse(sessionsJson);
|
||||
const session = sessions.find(session => session.userId === userId);
|
||||
if (session) {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function storeSessionInfo(loginData) {
|
||||
|
@ -39,9 +39,9 @@ function storeSessionInfo(loginData) {
|
|||
}
|
||||
|
||||
async function login(username, password, homeserver) {
|
||||
const hsApi = new HomeServerApi(homeserver);
|
||||
const loginData = await hsApi.passwordLogin(username, password).response();
|
||||
return storeSessionInfo(loginData);
|
||||
const hsApi = new HomeServerApi(homeserver);
|
||||
const loginData = await hsApi.passwordLogin(username, password).response();
|
||||
return storeSessionInfo(loginData);
|
||||
}
|
||||
|
||||
function showSession(container, session, sync) {
|
||||
|
@ -51,11 +51,11 @@ function showSession(container, session, sync) {
|
|||
}
|
||||
|
||||
export default async function main(container) {
|
||||
try {
|
||||
let sessionInfo = getSessionInfo(USER_ID);
|
||||
if (!sessionInfo) {
|
||||
sessionInfo = await login(USERNAME, PASSWORD, HOMESERVER);
|
||||
}
|
||||
try {
|
||||
let sessionInfo = getSessionInfo(USER_ID);
|
||||
if (!sessionInfo) {
|
||||
sessionInfo = await login(USERNAME, PASSWORD, HOMESERVER);
|
||||
}
|
||||
const storage = await createIdbStorage(`brawl_session_${sessionInfo.id}`);
|
||||
const hsApi = new HomeServerApi(HOMESERVER, sessionInfo.accessToken);
|
||||
const session = new Session({storage, hsApi, sessionInfo: {
|
||||
|
@ -65,18 +65,18 @@ export default async function main(container) {
|
|||
}});
|
||||
await session.load();
|
||||
console.log("session loaded");
|
||||
const sync = new Sync(hsApi, session, storage);
|
||||
const sync = new Sync(hsApi, session, storage);
|
||||
const needsInitialSync = !session.syncToken;
|
||||
if (needsInitialSync) {
|
||||
console.log("session needs initial sync");
|
||||
} else {
|
||||
showSession(container, session, sync);
|
||||
}
|
||||
await sync.start();
|
||||
await sync.start();
|
||||
if (needsInitialSync) {
|
||||
showSession(container, session, sync);
|
||||
}
|
||||
} catch(err) {
|
||||
} catch(err) {
|
||||
console.error(`${err.message}:\n${err.stack}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
export class HomeServerError extends Error {
|
||||
constructor(method, url, body) {
|
||||
super(`${body.error} on ${method} ${url}`);
|
||||
this.errcode = body.errcode;
|
||||
}
|
||||
constructor(method, url, body) {
|
||||
super(`${body.error} on ${method} ${url}`);
|
||||
this.errcode = body.errcode;
|
||||
}
|
||||
}
|
||||
|
||||
export class RequestAbortError extends Error {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import {
|
||||
HomeServerError,
|
||||
RequestAbortError,
|
||||
HomeServerError,
|
||||
RequestAbortError,
|
||||
NetworkError
|
||||
} from "./error.js";
|
||||
|
||||
class RequestWrapper {
|
||||
constructor(promise, controller) {
|
||||
constructor(promise, controller) {
|
||||
if (!controller) {
|
||||
const abortPromise = new Promise((_, reject) => {
|
||||
this._controller = {
|
||||
|
@ -21,63 +21,63 @@ class RequestWrapper {
|
|||
this._promise = promise;
|
||||
this._controller = controller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abort() {
|
||||
this._controller.abort();
|
||||
}
|
||||
abort() {
|
||||
this._controller.abort();
|
||||
}
|
||||
|
||||
response() {
|
||||
return this._promise;
|
||||
}
|
||||
response() {
|
||||
return this._promise;
|
||||
}
|
||||
}
|
||||
|
||||
export default class HomeServerApi {
|
||||
constructor(homeserver, accessToken) {
|
||||
constructor(homeserver, accessToken) {
|
||||
// store these both in a closure somehow so it's harder to get at in case of XSS?
|
||||
// one could change the homeserver as well so the token gets sent there, so both must be protected from read/write
|
||||
this._homeserver = homeserver;
|
||||
this._accessToken = accessToken;
|
||||
}
|
||||
this._accessToken = accessToken;
|
||||
}
|
||||
|
||||
_url(csPath) {
|
||||
return `${this._homeserver}/_matrix/client/r0${csPath}`;
|
||||
}
|
||||
_url(csPath) {
|
||||
return `${this._homeserver}/_matrix/client/r0${csPath}`;
|
||||
}
|
||||
|
||||
_request(method, csPath, queryParams = {}, body) {
|
||||
const queryString = Object.entries(queryParams)
|
||||
.filter(([, value]) => value !== undefined)
|
||||
.map(([name, value]) => `${encodeURIComponent(name)}=${encodeURIComponent(value)}`)
|
||||
.join("&");
|
||||
const url = this._url(`${csPath}?${queryString}`);
|
||||
let bodyString;
|
||||
const headers = new Headers();
|
||||
if (this._accessToken) {
|
||||
headers.append("Authorization", `Bearer ${this._accessToken}`);
|
||||
}
|
||||
headers.append("Accept", "application/json");
|
||||
if (body) {
|
||||
headers.append("Content-Type", "application/json");
|
||||
bodyString = JSON.stringify(body);
|
||||
}
|
||||
const controller = typeof AbortController === "function" ? new AbortController() : null;
|
||||
// TODO: set authenticated headers with second arguments, cache them
|
||||
let promise = fetch(url, {
|
||||
method,
|
||||
headers,
|
||||
body: bodyString,
|
||||
signal: controller && controller.signal
|
||||
});
|
||||
promise = promise.then(async (response) => {
|
||||
if (response.ok) {
|
||||
return await response.json();
|
||||
} else {
|
||||
switch (response.status) {
|
||||
default:
|
||||
throw new HomeServerError(method, url, await response.json())
|
||||
}
|
||||
}
|
||||
}, err => {
|
||||
_request(method, csPath, queryParams = {}, body) {
|
||||
const queryString = Object.entries(queryParams)
|
||||
.filter(([, value]) => value !== undefined)
|
||||
.map(([name, value]) => `${encodeURIComponent(name)}=${encodeURIComponent(value)}`)
|
||||
.join("&");
|
||||
const url = this._url(`${csPath}?${queryString}`);
|
||||
let bodyString;
|
||||
const headers = new Headers();
|
||||
if (this._accessToken) {
|
||||
headers.append("Authorization", `Bearer ${this._accessToken}`);
|
||||
}
|
||||
headers.append("Accept", "application/json");
|
||||
if (body) {
|
||||
headers.append("Content-Type", "application/json");
|
||||
bodyString = JSON.stringify(body);
|
||||
}
|
||||
const controller = typeof AbortController === "function" ? new AbortController() : null;
|
||||
// TODO: set authenticated headers with second arguments, cache them
|
||||
let promise = fetch(url, {
|
||||
method,
|
||||
headers,
|
||||
body: bodyString,
|
||||
signal: controller && controller.signal
|
||||
});
|
||||
promise = promise.then(async (response) => {
|
||||
if (response.ok) {
|
||||
return await response.json();
|
||||
} else {
|
||||
switch (response.status) {
|
||||
default:
|
||||
throw new HomeServerError(method, url, await response.json())
|
||||
}
|
||||
}
|
||||
}, err => {
|
||||
if (err.name === "AbortError") {
|
||||
throw new RequestAbortError();
|
||||
} else if (err instanceof TypeError) {
|
||||
|
@ -89,29 +89,29 @@ export default class HomeServerApi {
|
|||
// but the 2 later ones are indistinguishable from javascript.
|
||||
throw new NetworkError(err.message);
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
return new RequestWrapper(promise, controller);
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
return new RequestWrapper(promise, controller);
|
||||
}
|
||||
|
||||
_post(csPath, queryParams, body) {
|
||||
return this._request("POST", csPath, queryParams, body);
|
||||
}
|
||||
_post(csPath, queryParams, body) {
|
||||
return this._request("POST", csPath, queryParams, body);
|
||||
}
|
||||
|
||||
_get(csPath, queryParams, body) {
|
||||
return this._request("GET", csPath, queryParams, body);
|
||||
}
|
||||
_get(csPath, queryParams, body) {
|
||||
return this._request("GET", csPath, queryParams, body);
|
||||
}
|
||||
|
||||
sync(since, filter, timeout) {
|
||||
return this._get("/sync", {since, timeout, filter});
|
||||
}
|
||||
sync(since, filter, timeout) {
|
||||
return this._get("/sync", {since, timeout, filter});
|
||||
}
|
||||
|
||||
// params is from, dir and optionally to, limit, filter.
|
||||
messages(roomId, params) {
|
||||
return this._get(`/rooms/${roomId}/messages`, params);
|
||||
}
|
||||
|
||||
passwordLogin(username, password) {
|
||||
passwordLogin(username, password) {
|
||||
return this._post("/login", undefined, {
|
||||
"type": "m.login.password",
|
||||
"identifier": {
|
||||
|
@ -120,5 +120,5 @@ export default class HomeServerApi {
|
|||
},
|
||||
"password": password
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import {iterateCursor, reqAsPromise} from "./utils.js";
|
||||
|
||||
export default class QueryTarget {
|
||||
constructor(target) {
|
||||
this._target = target;
|
||||
}
|
||||
constructor(target) {
|
||||
this._target = target;
|
||||
}
|
||||
|
||||
_openCursor(range, direction) {
|
||||
if (range && direction) {
|
||||
|
@ -21,55 +21,55 @@ export default class QueryTarget {
|
|||
return reqAsPromise(this._target.get(key));
|
||||
}
|
||||
|
||||
reduce(range, reducer, initialValue) {
|
||||
return this._reduce(range, reducer, initialValue, "next");
|
||||
}
|
||||
reduce(range, reducer, initialValue) {
|
||||
return this._reduce(range, reducer, initialValue, "next");
|
||||
}
|
||||
|
||||
reduceReverse(range, reducer, initialValue) {
|
||||
return this._reduce(range, reducer, initialValue, "prev");
|
||||
}
|
||||
|
||||
selectLimit(range, amount) {
|
||||
return this._selectLimit(range, amount, "next");
|
||||
}
|
||||
reduceReverse(range, reducer, initialValue) {
|
||||
return this._reduce(range, reducer, initialValue, "prev");
|
||||
}
|
||||
|
||||
selectLimit(range, amount) {
|
||||
return this._selectLimit(range, amount, "next");
|
||||
}
|
||||
|
||||
selectLimitReverse(range, amount) {
|
||||
return this._selectLimit(range, amount, "prev");
|
||||
}
|
||||
selectLimitReverse(range, amount) {
|
||||
return this._selectLimit(range, amount, "prev");
|
||||
}
|
||||
|
||||
selectWhile(range, predicate) {
|
||||
return this._selectWhile(range, predicate, "next");
|
||||
}
|
||||
selectWhile(range, predicate) {
|
||||
return this._selectWhile(range, predicate, "next");
|
||||
}
|
||||
|
||||
selectWhileReverse(range, predicate) {
|
||||
return this._selectWhile(range, predicate, "prev");
|
||||
}
|
||||
selectWhileReverse(range, predicate) {
|
||||
return this._selectWhile(range, predicate, "prev");
|
||||
}
|
||||
|
||||
async selectAll(range, direction) {
|
||||
const cursor = this._openCursor(range, direction);
|
||||
const results = [];
|
||||
await iterateCursor(cursor, (value) => {
|
||||
results.push(value);
|
||||
return {done: false};
|
||||
});
|
||||
return results;
|
||||
}
|
||||
async selectAll(range, direction) {
|
||||
const cursor = this._openCursor(range, direction);
|
||||
const results = [];
|
||||
await iterateCursor(cursor, (value) => {
|
||||
results.push(value);
|
||||
return {done: false};
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
selectFirst(range) {
|
||||
return this._find(range, () => true, "next");
|
||||
}
|
||||
selectFirst(range) {
|
||||
return this._find(range, () => true, "next");
|
||||
}
|
||||
|
||||
selectLast(range) {
|
||||
return this._find(range, () => true, "prev");
|
||||
}
|
||||
selectLast(range) {
|
||||
return this._find(range, () => true, "prev");
|
||||
}
|
||||
|
||||
find(range, predicate) {
|
||||
return this._find(range, predicate, "next");
|
||||
}
|
||||
find(range, predicate) {
|
||||
return this._find(range, predicate, "next");
|
||||
}
|
||||
|
||||
findReverse(range, predicate) {
|
||||
return this._find(range, predicate, "prev");
|
||||
}
|
||||
findReverse(range, predicate) {
|
||||
return this._find(range, predicate, "prev");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given set of keys exist.
|
||||
|
@ -107,43 +107,43 @@ export default class QueryTarget {
|
|||
}
|
||||
}
|
||||
|
||||
_reduce(range, reducer, initialValue, direction) {
|
||||
let reducedValue = initialValue;
|
||||
const cursor = this._openCursor(range, direction);
|
||||
return iterateCursor(cursor, (value) => {
|
||||
reducedValue = reducer(reducedValue, value);
|
||||
return {done: false};
|
||||
});
|
||||
}
|
||||
_reduce(range, reducer, initialValue, direction) {
|
||||
let reducedValue = initialValue;
|
||||
const cursor = this._openCursor(range, direction);
|
||||
return iterateCursor(cursor, (value) => {
|
||||
reducedValue = reducer(reducedValue, value);
|
||||
return {done: false};
|
||||
});
|
||||
}
|
||||
|
||||
_selectLimit(range, amount, direction) {
|
||||
return this._selectWhile(range, (results) => {
|
||||
return results.length === amount;
|
||||
}, direction);
|
||||
}
|
||||
_selectLimit(range, amount, direction) {
|
||||
return this._selectWhile(range, (results) => {
|
||||
return results.length === amount;
|
||||
}, direction);
|
||||
}
|
||||
|
||||
async _selectWhile(range, predicate, direction) {
|
||||
const cursor = this._openCursor(range, direction);
|
||||
const results = [];
|
||||
await iterateCursor(cursor, (value) => {
|
||||
results.push(value);
|
||||
return {done: predicate(results)};
|
||||
});
|
||||
return results;
|
||||
}
|
||||
async _selectWhile(range, predicate, direction) {
|
||||
const cursor = this._openCursor(range, direction);
|
||||
const results = [];
|
||||
await iterateCursor(cursor, (value) => {
|
||||
results.push(value);
|
||||
return {done: predicate(results)};
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
async _find(range, predicate, direction) {
|
||||
const cursor = this._openCursor(range, direction);
|
||||
let result;
|
||||
const found = await iterateCursor(cursor, (value) => {
|
||||
const found = predicate(value);
|
||||
if (found) {
|
||||
result = value;
|
||||
}
|
||||
return {done: found};
|
||||
});
|
||||
if (found) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
async _find(range, predicate, direction) {
|
||||
const cursor = this._openCursor(range, direction);
|
||||
let result;
|
||||
const found = await iterateCursor(cursor, (value) => {
|
||||
const found = predicate(value);
|
||||
if (found) {
|
||||
result = value;
|
||||
}
|
||||
return {done: found};
|
||||
});
|
||||
if (found) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,39 +2,39 @@ import Transaction from "./transaction.js";
|
|||
import { STORE_NAMES, StorageError } from "../common.js";
|
||||
|
||||
export default class Storage {
|
||||
constructor(idbDatabase) {
|
||||
this._db = idbDatabase;
|
||||
const nameMap = STORE_NAMES.reduce((nameMap, name) => {
|
||||
nameMap[name] = name;
|
||||
return nameMap;
|
||||
}, {});
|
||||
this.storeNames = Object.freeze(nameMap);
|
||||
}
|
||||
constructor(idbDatabase) {
|
||||
this._db = idbDatabase;
|
||||
const nameMap = STORE_NAMES.reduce((nameMap, name) => {
|
||||
nameMap[name] = name;
|
||||
return nameMap;
|
||||
}, {});
|
||||
this.storeNames = Object.freeze(nameMap);
|
||||
}
|
||||
|
||||
_validateStoreNames(storeNames) {
|
||||
const idx = storeNames.findIndex(name => !STORE_NAMES.includes(name));
|
||||
if (idx !== -1) {
|
||||
throw new StorageError(`Tried top, a transaction unknown store ${storeNames[idx]}`);
|
||||
}
|
||||
}
|
||||
_validateStoreNames(storeNames) {
|
||||
const idx = storeNames.findIndex(name => !STORE_NAMES.includes(name));
|
||||
if (idx !== -1) {
|
||||
throw new StorageError(`Tried top, a transaction unknown store ${storeNames[idx]}`);
|
||||
}
|
||||
}
|
||||
|
||||
async readTxn(storeNames) {
|
||||
this._validateStoreNames(storeNames);
|
||||
try {
|
||||
const txn = this._db.transaction(storeNames, "readonly");
|
||||
return new Transaction(txn, storeNames);
|
||||
} catch(err) {
|
||||
throw new StorageError("readTxn failed", err);
|
||||
}
|
||||
}
|
||||
async readTxn(storeNames) {
|
||||
this._validateStoreNames(storeNames);
|
||||
try {
|
||||
const txn = this._db.transaction(storeNames, "readonly");
|
||||
return new Transaction(txn, storeNames);
|
||||
} catch(err) {
|
||||
throw new StorageError("readTxn failed", err);
|
||||
}
|
||||
}
|
||||
|
||||
async readWriteTxn(storeNames) {
|
||||
this._validateStoreNames(storeNames);
|
||||
try {
|
||||
const txn = this._db.transaction(storeNames, "readwrite");
|
||||
return new Transaction(txn, storeNames);
|
||||
} catch(err) {
|
||||
throw new StorageError("readWriteTxn failed", err);
|
||||
}
|
||||
}
|
||||
async readWriteTxn(storeNames) {
|
||||
this._validateStoreNames(storeNames);
|
||||
try {
|
||||
const txn = this._db.transaction(storeNames, "readwrite");
|
||||
return new Transaction(txn, storeNames);
|
||||
} catch(err) {
|
||||
throw new StorageError("readWriteTxn failed", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,23 +57,23 @@ class QueryTargetWrapper {
|
|||
}
|
||||
|
||||
export default class Store extends QueryTarget {
|
||||
constructor(idbStore) {
|
||||
super(new QueryTargetWrapper(idbStore));
|
||||
}
|
||||
constructor(idbStore) {
|
||||
super(new QueryTargetWrapper(idbStore));
|
||||
}
|
||||
|
||||
get _idbStore() {
|
||||
return this._target;
|
||||
}
|
||||
get _idbStore() {
|
||||
return this._target;
|
||||
}
|
||||
|
||||
index(indexName) {
|
||||
return new QueryTarget(new QueryTargetWrapper(this._idbStore.index(indexName)));
|
||||
}
|
||||
index(indexName) {
|
||||
return new QueryTarget(new QueryTargetWrapper(this._idbStore.index(indexName)));
|
||||
}
|
||||
|
||||
put(value) {
|
||||
return reqAsPromise(this._idbStore.put(value));
|
||||
}
|
||||
put(value) {
|
||||
return reqAsPromise(this._idbStore.put(value));
|
||||
}
|
||||
|
||||
add(value) {
|
||||
return reqAsPromise(this._idbStore.add(value));
|
||||
}
|
||||
add(value) {
|
||||
return reqAsPromise(this._idbStore.add(value));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,9 +87,9 @@ class Range {
|
|||
* @property {?Gap} gap if a gap entry, the gap
|
||||
*/
|
||||
export default class TimelineEventStore {
|
||||
constructor(timelineStore) {
|
||||
this._timelineStore = timelineStore;
|
||||
}
|
||||
constructor(timelineStore) {
|
||||
this._timelineStore = timelineStore;
|
||||
}
|
||||
|
||||
/** Creates a range that only includes the given key
|
||||
* @param {EventKey} eventKey the key
|
||||
|
@ -134,11 +134,11 @@ export default class TimelineEventStore {
|
|||
* @param {number} amount
|
||||
* @return {Promise<Entry[]>} a promise resolving to an array with 0 or more entries, in ascending order.
|
||||
*/
|
||||
async lastEvents(roomId, fragmentId, amount) {
|
||||
async lastEvents(roomId, fragmentId, amount) {
|
||||
const eventKey = EventKey.maxKey;
|
||||
eventKey.fragmentId = fragmentId;
|
||||
return this.eventsBefore(roomId, eventKey, amount);
|
||||
}
|
||||
return this.eventsBefore(roomId, eventKey, amount);
|
||||
}
|
||||
|
||||
/** Looks up the first `amount` entries in the timeline for `roomId`.
|
||||
* @param {string} roomId
|
||||
|
@ -146,11 +146,11 @@ export default class TimelineEventStore {
|
|||
* @param {number} amount
|
||||
* @return {Promise<Entry[]>} a promise resolving to an array with 0 or more entries, in ascending order.
|
||||
*/
|
||||
async firstEvents(roomId, fragmentId, amount) {
|
||||
async firstEvents(roomId, fragmentId, amount) {
|
||||
const eventKey = EventKey.minKey;
|
||||
eventKey.fragmentId = fragmentId;
|
||||
return this.eventsAfter(roomId, eventKey, amount);
|
||||
}
|
||||
return this.eventsAfter(roomId, eventKey, amount);
|
||||
}
|
||||
|
||||
/** Looks up `amount` entries after `eventKey` in the timeline for `roomId` within the same fragment.
|
||||
* The entry for `eventKey` is not included.
|
||||
|
@ -159,10 +159,10 @@ export default class TimelineEventStore {
|
|||
* @param {number} amount
|
||||
* @return {Promise<Entry[]>} a promise resolving to an array with 0 or more entries, in ascending order.
|
||||
*/
|
||||
eventsAfter(roomId, eventKey, amount) {
|
||||
eventsAfter(roomId, eventKey, amount) {
|
||||
const idbRange = this.lowerBoundRange(eventKey, true).asIDBKeyRange(roomId);
|
||||
return this._timelineStore.selectLimit(idbRange, amount);
|
||||
}
|
||||
return this._timelineStore.selectLimit(idbRange, amount);
|
||||
}
|
||||
|
||||
/** Looks up `amount` entries before `eventKey` in the timeline for `roomId` within the same fragment.
|
||||
* The entry for `eventKey` is not included.
|
||||
|
|
|
@ -8,58 +8,58 @@ import RoomStateStore from "./stores/RoomStateStore.js";
|
|||
import TimelineFragmentStore from "./stores/TimelineFragmentStore.js";
|
||||
|
||||
export default class Transaction {
|
||||
constructor(txn, allowedStoreNames) {
|
||||
this._txn = txn;
|
||||
this._allowedStoreNames = allowedStoreNames;
|
||||
this._stores = {
|
||||
session: null,
|
||||
roomSummary: null,
|
||||
roomTimeline: null,
|
||||
roomState: null,
|
||||
};
|
||||
}
|
||||
constructor(txn, allowedStoreNames) {
|
||||
this._txn = txn;
|
||||
this._allowedStoreNames = allowedStoreNames;
|
||||
this._stores = {
|
||||
session: null,
|
||||
roomSummary: null,
|
||||
roomTimeline: null,
|
||||
roomState: null,
|
||||
};
|
||||
}
|
||||
|
||||
_idbStore(name) {
|
||||
if (!this._allowedStoreNames.includes(name)) {
|
||||
// more specific error? this is a bug, so maybe not ...
|
||||
throw new StorageError(`Invalid store for transaction: ${name}, only ${this._allowedStoreNames.join(", ")} are allowed.`);
|
||||
}
|
||||
return new Store(this._txn.objectStore(name));
|
||||
}
|
||||
_idbStore(name) {
|
||||
if (!this._allowedStoreNames.includes(name)) {
|
||||
// more specific error? this is a bug, so maybe not ...
|
||||
throw new StorageError(`Invalid store for transaction: ${name}, only ${this._allowedStoreNames.join(", ")} are allowed.`);
|
||||
}
|
||||
return new Store(this._txn.objectStore(name));
|
||||
}
|
||||
|
||||
_store(name, mapStore) {
|
||||
if (!this._stores[name]) {
|
||||
const idbStore = this._idbStore(name);
|
||||
this._stores[name] = mapStore(idbStore);
|
||||
}
|
||||
return this._stores[name];
|
||||
}
|
||||
_store(name, mapStore) {
|
||||
if (!this._stores[name]) {
|
||||
const idbStore = this._idbStore(name);
|
||||
this._stores[name] = mapStore(idbStore);
|
||||
}
|
||||
return this._stores[name];
|
||||
}
|
||||
|
||||
get session() {
|
||||
return this._store("session", idbStore => new SessionStore(idbStore));
|
||||
}
|
||||
get session() {
|
||||
return this._store("session", idbStore => new SessionStore(idbStore));
|
||||
}
|
||||
|
||||
get roomSummary() {
|
||||
return this._store("roomSummary", idbStore => new RoomSummaryStore(idbStore));
|
||||
}
|
||||
get roomSummary() {
|
||||
return this._store("roomSummary", idbStore => new RoomSummaryStore(idbStore));
|
||||
}
|
||||
|
||||
get timelineFragments() {
|
||||
return this._store("timelineFragments", idbStore => new TimelineFragmentStore(idbStore));
|
||||
}
|
||||
|
||||
get timelineEvents() {
|
||||
return this._store("timelineEvents", idbStore => new TimelineEventStore(idbStore));
|
||||
}
|
||||
get timelineEvents() {
|
||||
return this._store("timelineEvents", idbStore => new TimelineEventStore(idbStore));
|
||||
}
|
||||
|
||||
get roomState() {
|
||||
return this._store("roomState", idbStore => new RoomStateStore(idbStore));
|
||||
}
|
||||
get roomState() {
|
||||
return this._store("roomState", idbStore => new RoomStateStore(idbStore));
|
||||
}
|
||||
|
||||
complete() {
|
||||
return txnAsPromise(this._txn);
|
||||
}
|
||||
complete() {
|
||||
return txnAsPromise(this._txn);
|
||||
}
|
||||
|
||||
abort() {
|
||||
this._txn.abort();
|
||||
}
|
||||
abort() {
|
||||
this._txn.abort();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
export default {
|
||||
get minStorageKey() {
|
||||
// for indexeddb, we use unsigned 32 bit integers as keys
|
||||
return 0;
|
||||
},
|
||||
|
||||
get middleStorageKey() {
|
||||
// for indexeddb, we use unsigned 32 bit integers as keys
|
||||
return 0x7FFFFFFF;
|
||||
},
|
||||
get minStorageKey() {
|
||||
// for indexeddb, we use unsigned 32 bit integers as keys
|
||||
return 0;
|
||||
},
|
||||
|
||||
get middleStorageKey() {
|
||||
// for indexeddb, we use unsigned 32 bit integers as keys
|
||||
return 0x7FFFFFFF;
|
||||
},
|
||||
|
||||
get maxStorageKey() {
|
||||
// for indexeddb, we use unsigned 32 bit integers as keys
|
||||
return 0xFFFFFFFF;
|
||||
},
|
||||
get maxStorageKey() {
|
||||
// for indexeddb, we use unsigned 32 bit integers as keys
|
||||
return 0xFFFFFFFF;
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue