forked from mystiq/hydrogen-web
port SessionPickerViewModel to SessionContainer
This commit is contained in:
parent
a5965ad378
commit
f4983b5ba6
3 changed files with 51 additions and 47 deletions
|
@ -1,6 +1,7 @@
|
|||
import {SortedArray} from "../observable/index.js";
|
||||
import {EventEmitter} from "../utils/EventEmitter.js";
|
||||
import {createNewSessionId} from "./BrawlViewModel.js"
|
||||
import {LoadStatus} from "../matrix/SessionContainer.js";
|
||||
import {SyncStatus} from "../matrix/Sync.js";
|
||||
|
||||
class SessionItemViewModel extends EventEmitter {
|
||||
constructor(sessionInfo, pickerVM) {
|
||||
|
@ -99,22 +100,58 @@ class SessionItemViewModel extends EventEmitter {
|
|||
}
|
||||
|
||||
export class SessionPickerViewModel {
|
||||
constructor({storageFactory, sessionInfoStorage, sessionCallback}) {
|
||||
constructor({storageFactory, sessionInfoStorage, sessionCallback, createSessionContainer}) {
|
||||
this._storageFactory = storageFactory;
|
||||
this._sessionInfoStorage = sessionInfoStorage;
|
||||
this._sessionCallback = sessionCallback;
|
||||
this._createSessionContainer = createSessionContainer;
|
||||
this._sessions = new SortedArray((s1, s2) => s1.id.localeCompare(s2.id));
|
||||
this._loading = false;
|
||||
}
|
||||
|
||||
// this loads all the sessions
|
||||
async load() {
|
||||
const sessions = await this._sessionInfoStorage.getAll();
|
||||
this._sessions.setManyUnsorted(sessions.map(s => new SessionItemViewModel(s, this)));
|
||||
}
|
||||
|
||||
pick(id) {
|
||||
// this is the loading of a single picked session
|
||||
get loading() {
|
||||
return this._loading;
|
||||
}
|
||||
|
||||
get loadStatus() {
|
||||
return this._sessionContainer && this._sessionContainer.loadStatus;
|
||||
}
|
||||
|
||||
get loadError() {
|
||||
if (this._sessionContainer) {
|
||||
const error = this._sessionContainer.loadError;
|
||||
if (error) {
|
||||
return error.message;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async pick(id) {
|
||||
const sessionVM = this._sessions.array.find(s => s.id === id);
|
||||
if (sessionVM) {
|
||||
this._sessionCallback(sessionVM.sessionInfo);
|
||||
this._loading = true;
|
||||
this.emit("change", "loading");
|
||||
this._sessionContainer = this._createSessionContainer();
|
||||
this._sessionContainer.startWithExistingSession(sessionVM.sessionInfo.id);
|
||||
// TODO: allow to cancel here
|
||||
const waitHandle = this._sessionContainer.loadStatus.waitFor(s => {
|
||||
this.emit("change", "loadStatus");
|
||||
// wait for initial sync, but not catchup sync
|
||||
return (
|
||||
s === LoadStatus.FirstSync &&
|
||||
this._sessionContainer.sync.status === SyncStatus.CatchupSync
|
||||
) || s === LoadStatus.Ready;
|
||||
});
|
||||
await waitHandle.promise;
|
||||
this._sessionCallback(this._sessionContainer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,7 +166,7 @@ export class SessionPickerViewModel {
|
|||
const data = JSON.parse(json);
|
||||
const {sessionInfo} = data;
|
||||
sessionInfo.comment = `Imported on ${new Date().toLocaleString()} from id ${sessionInfo.id}.`;
|
||||
sessionInfo.id = createNewSessionId();
|
||||
sessionInfo.id = this._createSessionContainer().createNewSessionId();
|
||||
await this._storageFactory.import(sessionInfo.id, data.stores);
|
||||
await this._sessionInfoStorage.add(sessionInfo);
|
||||
this._sessions.set(new SessionItemViewModel(sessionInfo, this));
|
||||
|
|
|
@ -23,19 +23,21 @@ export default async function main(container) {
|
|||
const request = fetchRequest;
|
||||
const sessionInfoStorage = new SessionInfoStorage("brawl_sessions_v1");
|
||||
const clock = new Clock();
|
||||
const storageFactory = new StorageFactory();
|
||||
|
||||
const vm = new BrawlViewModel({
|
||||
createSessionContainer: () => {
|
||||
return new SessionContainer({
|
||||
random: Math.random,
|
||||
onlineStatus: new OnlineStatus(),
|
||||
storageFactory: new StorageFactory(),
|
||||
storageFactory,
|
||||
sessionInfoStorage,
|
||||
request,
|
||||
clock,
|
||||
});
|
||||
},
|
||||
sessionInfoStorage,
|
||||
storageFactory,
|
||||
clock,
|
||||
});
|
||||
await vm.load();
|
||||
|
|
|
@ -43,7 +43,7 @@ export class SessionContainer {
|
|||
this._storage = null;
|
||||
}
|
||||
|
||||
_createNewSessionId() {
|
||||
createNewSessionId() {
|
||||
return (Math.floor(this._random() * Number.MAX_SAFE_INTEGER)).toString();
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,9 @@ export class SessionContainer {
|
|||
this._status.set(LoadStatus.Loading);
|
||||
try {
|
||||
const sessionInfo = await this._sessionInfoStorage.get(sessionId);
|
||||
if (!sessionInfo) {
|
||||
throw new Error("Invalid session id: " + sessionId);
|
||||
}
|
||||
await this._loadSessionInfo(sessionInfo);
|
||||
} catch (err) {
|
||||
this._error = err;
|
||||
|
@ -70,7 +73,7 @@ export class SessionContainer {
|
|||
try {
|
||||
const hsApi = new HomeServerApi({homeServer, request: this._request});
|
||||
const loginData = await hsApi.passwordLogin(username, password).response();
|
||||
const sessionId = this._createNewSessionId();
|
||||
const sessionId = this.createNewSessionId();
|
||||
sessionInfo = {
|
||||
id: sessionId,
|
||||
deviceId: loginData.device_id,
|
||||
|
@ -211,6 +214,7 @@ export class SessionContainer {
|
|||
}
|
||||
if (this._storage) {
|
||||
this._storage.close();
|
||||
this._storage = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,42 +230,3 @@ export class SessionContainer {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
function main() {
|
||||
// these are only required for external classes,
|
||||
// SessionFactory has it's defaults for internal classes
|
||||
const sessionFactory = new SessionFactory({
|
||||
Clock: DOMClock,
|
||||
OnlineState: DOMOnlineState,
|
||||
SessionInfoStorage: LocalStorageSessionStore, // should be called SessionInfoStore?
|
||||
StorageFactory: window.indexedDB ? IDBStorageFactory : MemoryStorageFactory, // should be called StorageManager?
|
||||
// should be moved to StorageFactory as `KeyBounds`?: minStorageKey, middleStorageKey, maxStorageKey
|
||||
// would need to pass it into EventKey though
|
||||
request,
|
||||
});
|
||||
|
||||
// lets not do this in a first cut
|
||||
// internally in the matrix lib
|
||||
const room = new creator.ctor("Room", Room)({});
|
||||
|
||||
// or short
|
||||
const sessionFactory = new SessionFactory(WebFactory);
|
||||
// sessionFactory.sessionInfoStore
|
||||
|
||||
// registration
|
||||
// const registration = sessionFactory.registerUser();
|
||||
// registration.stage
|
||||
|
||||
|
||||
const container = sessionFactory.startWithRegistration(registration);
|
||||
const container = sessionFactory.startWithLogin(server, username, password);
|
||||
const container = sessionFactory.startWithExistingSession(sessionId);
|
||||
// container.loadStatus is an ObservableValue<LoadStatus>
|
||||
await container.loadStatus.waitFor(s => s === LoadStatus.FirstSync && container.sync.status === SyncStatus.CatchupSync || s === LoadStatus.Ready);
|
||||
|
||||
// loader isn't needed anymore from now on
|
||||
const {session, sync, reconnector} = container;
|
||||
container.stop();
|
||||
}
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue