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

Commit

Permalink
feat: enable clipboard usage between alva instances
Browse files Browse the repository at this point in the history
  • Loading branch information
marionebl committed Sep 10, 2018
1 parent 615a4bc commit f516ee8
Show file tree
Hide file tree
Showing 22 changed files with 1,263 additions and 708 deletions.
2 changes: 1 addition & 1 deletion src/container/page-list/page-tile-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class PageTileContainer extends React.Component<PageTileContainerProps> {

if (rootElement) {
store.setSelectedElement(rootElement);
store.getProject().setFocusedItem(Types.FocusedItemType.Page, this.props.page);
store.getProject().setFocusedItem(Types.ItemType.Page, this.props.page);
}
}

Expand Down
44 changes: 44 additions & 0 deletions src/electron/clipboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as AlvaUtil from '../alva-util';
import * as Electron from 'electron';
import * as Message from '../message';
import { isMessage } from '../sender/is-message';
import * as uuid from 'uuid';

export function setClipboard(payload: Message.Clipboard['payload']): void {
Electron.clipboard.writeBuffer(
'application/alva',
Buffer.from(
JSON.stringify({
type: Message.MessageType.Clipboard,
id: uuid.v4(),
payload
})
)
);
}

export function getClipboard(): Message.Clipboard | undefined {
const rawData = Electron.clipboard.readBuffer('application/alva').toString();

if (!rawData) {
return;
}

const parseResult = AlvaUtil.parseJSON(rawData);

if (parseResult.type === AlvaUtil.ParseResultType.Error) {
console.error(parseResult.error);
return;
}

if (!isMessage(parseResult.result)) {
console.error(`Received malformed clipboard message: ${parseResult.data}`);
return;
}

if (parseResult.result.type !== Message.MessageType.Clipboard) {
return;
}

return parseResult.result as Message.Clipboard;
}
100 changes: 100 additions & 0 deletions src/electron/create-app-message-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
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 {
ServerMessageHandlerContext,
ServerMessageHandlerInjection
} from './create-server-message-handler';

export async function createAppMessageHandler(
ctx: ServerMessageHandlerContext,
injection: ServerMessageHandlerInjection
): Promise<(message: Message.Message) => Promise<void>> {
return async function appMessageHandler(message: Message.Message): Promise<void> {
switch (message.type) {
case Message.MessageType.CheckForUpdatesRequest: {
if (ctx.win) {
checkForUpdates(ctx.win, true);
}
break;
}
case Message.MessageType.AppLoaded: {
const pathToOpen = await injection.ephemeralStore.getProjectPath();

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 || {});
break;
}
case Message.MessageType.Maximize: {
if (ctx.win) {
ctx.win.isMaximized() ? ctx.win.unmaximize() : ctx.win.maximize();
}
break;
}
case Message.MessageType.ShowError: {
const error = new Error(message.payload.message);
error.stack = message.payload.stack;
showError(error);
break;
}
case Message.MessageType.OpenExternalURL: {
Electron.shell.openExternal(message.payload);
break;
}
case Message.MessageType.ContextMenuRequest: {
showContextMenu(message.payload, { sender: injection.sender });
break;
}
case Message.MessageType.ChangeApp: {
injection.ephemeralStore.setAppState(message.payload.app);
const project = await requestProjectSafely(injection.sender);

showMainMenu(
{ app: message.payload.app, project: project ? project.toJSON() : undefined },
{ sender: injection.sender }
);

break;
}
case Message.MessageType.ChangeProject: {
const app = await requestAppSafely(injection.sender);

if (!app) {
return;
}

showMainMenu(
{ app: app.toJSON(), project: message.payload.project },
{ sender: injection.sender }
);
}
}
};
}
114 changes: 114 additions & 0 deletions src/electron/create-edit-message-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import * as Clipboard from './clipboard';
import * as Message from '../message';
import { requestProject } from './request-project';
import * as Types from '../types';
import * as uuid from 'uuid';

import {
ServerMessageHandlerContext,
ServerMessageHandlerInjection
} from './create-server-message-handler';

export async function createEditMessageHandler(
ctx: ServerMessageHandlerContext,
injection: ServerMessageHandlerInjection
): Promise<(message: Message.Message) => Promise<void>> {
return async function editMessageHandler(message: Message.Message): Promise<void> {
switch (message.type) {
case Message.MessageType.Cut:
case Message.MessageType.Copy: {
const project = await requestProject(injection.sender);
const focusedItemType = project.getFocusedItemType();
const focusedItem = project.getFocusedItem();

if (!focusedItem || focusedItemType === Types.ItemType.None) {
return;
}

Clipboard.setClipboard({
type: serializeItemType(focusedItemType),
item: focusedItem.toJSON(),
project: project.toJSON()
});

break;
}
case Message.MessageType.CutElement:
case Message.MessageType.CopyElement: {
const project = await requestProject(injection.sender);
const element = project.getElementById(message.payload);

if (!element) {
return;
}

Clipboard.setClipboard({
type: serializeItemType(Types.ItemType.Element),
item: element.toJSON(),
project: project.toJSON()
});

break;
}
case Message.MessageType.Paste: {
const clipboard = Clipboard.getClipboard();

if (!clipboard) {
return;
}

const itemType = deserializeItemType(clipboard.payload.type);
const targetType = message.payload
? message.payload.targetType
: Types.ElementTargetType.Auto;
const targetId = message.payload ? message.payload.id : '';

switch (itemType) {
case Types.ItemType.Element:
injection.sender.send({
id: uuid.v4(),
type: Message.MessageType.PasteElement,
payload: {
element: clipboard.payload.item as Types.SerializedElement,
project: clipboard.payload.project,
targetType,
targetId
}
});
break;
case Types.ItemType.Page:
injection.sender.send({
id: uuid.v4(),
type: Message.MessageType.PastePage,
payload: {
page: clipboard.payload.item as Types.SerializedPage,
project: clipboard.payload.project
}
});
}
}
}
};
}

function serializeItemType(type: Types.ItemType): Types.SerializedItemType {
switch (type) {
case Types.ItemType.Element:
return 'element';
case Types.ItemType.Page:
return 'page';
case Types.ItemType.None:
return 'none';
}
}

function deserializeItemType(type: Types.SerializedItemType): Types.ItemType {
switch (type) {
case 'element':
return Types.ItemType.Element;
case 'page':
return Types.ItemType.Page;
case 'none':
return Types.ItemType.None;
}
}
Loading

0 comments on commit f516ee8

Please sign in to comment.