Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
fix: wait for successful file read before restoring app state
Browse files Browse the repository at this point in the history
  • Loading branch information
marionebl committed Sep 10, 2018
1 parent f34dba8 commit 805106e
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 81 deletions.
49 changes: 37 additions & 12 deletions src/electron/create-app-message-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import * as Electron from 'electron';
import * as Message from '../message';
import * as uuid from 'uuid';
import { checkForUpdates } from './auto-updater';
import * as electronIsDev from 'electron-is-dev';
import { showError } from './show-error';
import { requestAppSafely } from './request-app';
import { requestProjectSafely } from './request-project';
import { showContextMenu } from './show-context-menu';
import { showMainMenu } from './show-main-menu';
import * as Types from '../types';

import {
ServerMessageHandlerContext,
Expand All @@ -29,24 +29,49 @@ export async function createAppMessageHandler(
case Message.MessageType.AppLoaded: {
const pathToOpen = await injection.ephemeralStore.getProjectPath();

injection.sender.send({
if (!pathToOpen) {
return injection.sender.send({
id: uuid.v4(),
type: Message.MessageType.StartApp,
payload: {
app: undefined,
port: ctx.port as number
}
});
}

const projectResponse = await injection.sender.request<
Message.OpenFileRequestResponsePair
>(
{
id: uuid.v4(),
type: Message.MessageType.OpenFileRequest,
payload: pathToOpen ? { path: pathToOpen, silent: true } : undefined
},
Message.MessageType.OpenFileResponse
);

if (projectResponse.payload.status === Types.ProjectPayloadStatus.Error) {
injection.ephemeralStore.clearProjectPath();

return injection.sender.send({
id: uuid.v4(),
type: Message.MessageType.StartApp,
payload: {
app: undefined,
port: ctx.port as number
}
});
}

return injection.sender.send({
id: uuid.v4(),
type: Message.MessageType.StartApp,
payload: {
app: await injection.ephemeralStore.getAppState(),
port: ctx.port as number
}
});

if (electronIsDev && pathToOpen) {
injection.sender.send({
id: uuid.v4(),
type: Message.MessageType.OpenFileRequest,
payload: { path: pathToOpen }
});
}

break;
}
case Message.MessageType.Reload: {
injection.emitter.emit('reload', message.payload || {});
Expand Down
37 changes: 28 additions & 9 deletions src/electron/create-file-message-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import * as Fs from 'fs';
import * as Message from '../message';
import * as MimeTypes from 'mime-types';
import * as Model from '../model';
import { Persistence } from '../persistence';
import { readProjectOrError } from './read-project-or-error';
import { Persistence, PersistenceState } from '../persistence';
import { showOpenDialog } from './show-open-dialog';
import { showSaveDialog } from './show-save-dialog';
import * as Types from '../types';
import * as Util from 'util';

import {
Expand Down Expand Up @@ -47,34 +47,53 @@ export async function createFileMessageHandler(
id: message.id,
payload: {
path,
contents: project.toJSON()
contents: project.toJSON(),
status: Types.ProjectPayloadStatus.Ok
}
});
}
break;
}
case Message.MessageType.OpenFileRequest: {
const path = await getPath(message.payload);
const silent = message.payload ? message.payload.silent : false;

if (!path) {
return;
}

// tslint:disable-next-line:no-any
const project = (await readProjectOrError(path)) as any;

if (!project) {
return;
const projectResult = await Persistence.read<Types.SavedProject>(path);

if (projectResult.state === PersistenceState.Error) {
if (!silent) {
injection.sender.send({
type: Message.MessageType.ShowError,
id: message.id,
payload: {
message: [projectResult.error.message].join('\n'),
stack: projectResult.error.stack || ''
}
});
}

return injection.sender.send({
type: Message.MessageType.OpenFileResponse,
id: message.id,
payload: { error: projectResult.error, status: Types.ProjectPayloadStatus.Error }
});
}

const savedProject = projectResult.contents;
const project = savedProject as Types.SerializedProject;

if (typeof project === 'object') {
project.path = path;
}

injection.sender.send({
type: Message.MessageType.OpenFileResponse,
id: message.id,
payload: { path, contents: project }
payload: { path, contents: project, status: Types.ProjectPayloadStatus.Ok }
});

injection.ephemeralStore.setProjectPath(path);
Expand Down
5 changes: 5 additions & 0 deletions src/electron/ephemeral-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const ElectronStore = require('electron-store');

interface Store {
clear(): void;
delete(key: string): void;
// tslint:disable-next-line:no-any
get(key: string): any;
// tslint:disable-next-line:no-any
Expand Down Expand Up @@ -48,6 +49,10 @@ export class EphemeralStore {
);
}

public async clearProjectPath(): Promise<void> {
this.store.delete('project-path');
}

public async getProjectPath(): Promise<string | undefined> {
const raw = this.store.get('project-path');

Expand Down
21 changes: 0 additions & 21 deletions src/electron/read-project-or-error.ts

This file was deleted.

5 changes: 4 additions & 1 deletion src/message/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,10 @@ export type DuplicatePageElement = Envelope<MessageType.DuplicateElement, string
export type Log = Envelope<MessageType.Log, any>;
export type Maximize = EmptyEnvelope<MessageType.Maximize>;
export type OpenExternalURL = Envelope<MessageType.OpenExternalURL, string>;
export type OpenFileRequest = Envelope<MessageType.OpenFileRequest, { path: string } | undefined>;
export type OpenFileRequest = Envelope<
MessageType.OpenFileRequest,
{ path: string; silent?: boolean } | undefined
>;
export type OpenFileResponse = Envelope<MessageType.OpenFileResponse, Types.ProjectPayload>;
export type PageChange = Envelope<MessageType.PageChange, Types.PageChangePayload>;
export type ProjectChange = Envelope<MessageType.ProjectChange, Types.SerializedProject>;
Expand Down
10 changes: 9 additions & 1 deletion src/message/request-response.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import * as Message from './message';

export type RequestResponsePair = AppRequestResponsePair | ProjectRequestResponsePair;
export type RequestResponsePair =
| AppRequestResponsePair
| ProjectRequestResponsePair
| OpenFileRequestResponsePair;

export interface AppRequestResponsePair {
request: Message.AppRequest;
Expand All @@ -11,3 +14,8 @@ export interface ProjectRequestResponsePair {
request: Message.ProjectRequest;
response: Message.ProjectResponse;
}

export interface OpenFileRequestResponsePair {
request: Message.OpenFileRequest;
response: Message.OpenFileResponse;
}
9 changes: 5 additions & 4 deletions src/model/element/element-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,16 +157,17 @@ export class ElementContent {
return this.parentElementId;
}

public getSlot(): PatternSlot {
return this.project.getPatternSlotById(this.slotId) as PatternSlot;
public getSlot(): PatternSlot | undefined {
return this.project.getPatternSlotById(this.slotId);
}

public getSlotId(): string {
return this.slotId;
}

public getSlotType(): Types.SlotType {
return this.getSlot().getType();
public getSlotType(): Types.SlotType | undefined {
const slot = this.getSlot();
return slot ? slot.getType() : undefined;
}

@Mobx.action
Expand Down
7 changes: 7 additions & 0 deletions src/persistence/persistence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ export class Persistence {
public static read<T>(path: string): Promise<PersistenceReadResult<T>> {
return new Promise(resolve => {
Fs.readFile(path, (error, contents) => {
if (error) {
return resolve({
state: PersistenceState.Error,
error
});
}

try {
resolve({
state: PersistenceState.Success,
Expand Down
4 changes: 3 additions & 1 deletion src/preview/preview-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,9 @@ export class PreviewStore<V> {
.reduce((renderProperties, content) => {
const slot = content.getSlot();

renderProperties[slot.getPropertyName()] = content.getElements().map(render);
if (slot) {
renderProperties[slot.getPropertyName()] = content.getElements().map(render);
}

return renderProperties;
}, {});
Expand Down
75 changes: 44 additions & 31 deletions src/renderer/create-init-message-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,48 +36,35 @@ export function createInitMessageHandler({

break;
}
case Message.MessageType.OpenFileResponse: {
history.clear();
case Message.MessageType.OpenFileResponse:
case Message.MessageType.CreateNewFileResponse: {
if (message.payload.status === Types.ProjectPayloadStatus.Error) {
return;
}

try {
const newProject = Model.Project.from(message.payload.contents);
newProject.setPath(message.payload.path);
store.setProject(newProject);
const payload = message.payload as Types.ProjectPayloadSuccess;

app.setActiveView(Types.AlvaView.PageDetail);
store.getProject().setFocusedItem(Types.ItemType.Page, store.getActivePage());
store.commit();
history.clear();

Sender.send({
id: uuid.v4(),
payload: {
libraries: store
.getProject()
.getPatternLibraries()
.map(lib => lib.getId())
},
type: Message.MessageType.CheckLibraryRequest
});
} catch (err) {
Sender.send({
const projectResult = createProject(payload.contents);

if (projectResult.status === ProjectCreateStatus.Error) {
return Sender.send({
id: uuid.v4(),
payload: {
message: `Sorry, we had trouble opening the file "${Path.basename(
message.payload.path
)}".\n Parsing the project failed with: ${err.message}`,
stack: err.stack
message: `Sorry, we had trouble reading the project in file "${Path.basename(
payload.path
)}".\n Parsing the project failed with: ${projectResult.error.message}`,
stack: projectResult.error.stack || ''
},
type: Message.MessageType.ShowError
});
}

break;
}
case Message.MessageType.CreateNewFileResponse: {
history.clear();
const newProject = Model.Project.from(message.payload.contents);
store.setProject(newProject);
store.setProject(projectResult.project);
app.setActiveView(Types.AlvaView.PageDetail);
store.getProject().setFocusedItem(Types.ItemType.Page, store.getActivePage());

store.commit();
break;
}
Expand All @@ -95,3 +82,29 @@ export function createInitMessageHandler({
}
};
}

export enum ProjectCreateStatus {
Success,
Error
}

export type ProjectCreateResult = ProjectCreateSuccess | ProjectCreateError;

export interface ProjectCreateSuccess {
status: ProjectCreateStatus.Success;
project: Model.Project;
}

export interface ProjectCreateError {
status: ProjectCreateStatus.Error;
error: Error;
}

function createProject(data: Types.SerializedProject): ProjectCreateResult {
try {
const project = Model.Project.from(data);
return { project, status: ProjectCreateStatus.Success };
} catch (error) {
return { error, status: ProjectCreateStatus.Error };
}
}
2 changes: 2 additions & 0 deletions src/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export class AlvaServer extends EventEmitter {
this.server = init.server;
this.webSocketServer = init.webSocketServer;

this.app.get('/', (_, res) => res.send('ok'));

this.app.get('/preview.html', createPreviewRoute({ sender: this.options.sender }));

this.app.use('/static', createStaticRoute({ sender: this.options.sender }));
Expand Down
15 changes: 14 additions & 1 deletion src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,22 @@ export interface PageChangePayload {
userStore: UserStore.SerializedUserStore;
}

export interface ProjectPayload {
export enum ProjectPayloadStatus {
Ok,
Error
}

export type ProjectPayload = ProjectPayloadError | ProjectPayloadSuccess;

export interface ProjectPayloadError {
error: Error;
status: ProjectPayloadStatus;
}

export interface ProjectPayloadSuccess {
contents: SerializedProject;
path: string;
status: ProjectPayloadStatus;
}

export interface SavePayload {
Expand Down

0 comments on commit 805106e

Please sign in to comment.