refactor frontend ipc

This commit is contained in:
riqo 2021-06-19 15:22:17 -05:00
commit 56196bcbcf
13 changed files with 177 additions and 52 deletions

View file

@ -1,8 +1,9 @@
import { postAuth, postLogin, postLogout } from "@/api/account";
import { endSession, launchSession } from "@/session";
import { getToken, clearToken, setToken } from "./store";
import { getToken, setToken, setProfile, getProfile, clearStore } from "./store";
import { parseAuthRes } from "./auth";
import { ipcEmit } from "@/composables/useEmitter";
export const accountAuth = async (): Promise<Error | AuthState> => {
@ -18,6 +19,7 @@ export const accountAuth = async (): Promise<Error | AuthState> => {
const parsed = parseAuthRes(res);
setToken(parsed.token)
setProfile(parsed.profile);
return {
profile: parsed.profile,
@ -26,7 +28,7 @@ export const accountAuth = async (): Promise<Error | AuthState> => {
} catch(e) {
console.log('[ACCOUNT]', e);
clearToken();
clearStore();
throw(new Error('Failed to authenticate.'));
}
@ -45,6 +47,7 @@ export const accountLogin: IpcHandlerCallback<AccountCredentials, Profile> = asy
// save jwt token and profile
setToken(parsed.token);
setProfile(parsed.profile);
// launch session
launchSession(parsed.token);
@ -53,6 +56,7 @@ export const accountLogin: IpcHandlerCallback<AccountCredentials, Profile> = asy
return parsed.profile;
} catch(e) {
clearStore();
throw e;
}
}
@ -65,7 +69,7 @@ export const accountLogout = async (): Promise<Error | void> => {
await postLogout();
// remove key and crimataId
clearToken();
clearStore();
// kill crimata platform session
endSession();
@ -79,4 +83,13 @@ export const accountLogout = async (): Promise<Error | void> => {
}
export const updateAppState = (): void => {
const profile = getProfile();
ipcEmit("set-profile", profile);
// ipcEmit('messages') etc
}

View file

@ -1,22 +1,21 @@
import { ipcMain, IpcMainInvokeEvent, IpcMainEvent } from "electron";
export class IpcHandler<InputType, ReturnType> implements IIpcHandler<InputType, ReturnType> {
export class IpcHandler<InputParam, ReturnType> implements IIpcHandler<InputParam, ReturnType> {
readonly channel: string;
readonly _handlerCallback: IpcHandlerCallback<InputType, ReturnType>;
readonly _handlerCallback: IpcHandlerCallback<InputParam, ReturnType>;
constructor(options: {
channel: string;
handlerCallback: IpcHandlerCallback<InputType, ReturnType>;
handlerCallback: IpcHandlerCallback<InputParam, ReturnType>;
}) {
this.channel = options.channel;
this._handlerCallback = options.handlerCallback;
}
handle() {
console.log(`[IPC] INIT: ${this.channel}`);
this.remove();
ipcMain.handle(this.channel, this._onInvoke);
}
@ -49,22 +48,21 @@ export class IpcHandler<InputType, ReturnType> implements IIpcHandler<InputType,
}
export class IpcListener<InputType> implements IIpcListener<InputType> {
export class IpcListener<InputParam> implements IIpcListener<InputParam> {
readonly channel: string;
readonly _listenerCallback: IpcListenerCallback<InputType>;
readonly _listenerCallback: IpcListenerCallback<InputParam>;
constructor(options: {
channel: string;
listenerCallback: IpcListenerCallback<InputType>;
listenerCallback: IpcListenerCallback<InputParam>;
}) {
this.channel = options.channel;
this._listenerCallback = options.listenerCallback;
}
listen() {
console.log(`[IPC] Init: ${this.channel}`);
this.remove();
ipcMain.on(this.channel, this._onPost);
}
@ -82,7 +80,3 @@ export class IpcListener<InputType> implements IIpcListener<InputType> {
}
}

View file

@ -1,10 +1,11 @@
"use strict";
import { accountLogin, accountLogout } from "@/account";
import { accountLogin, accountLogout, accountProfile } from "@/account";
import { IpcHandler } from "@/composables/useIpcMain";
import { flush } from "@/audio";
const LOGIN_CHANNEL = "invoke-account-login";
const LOGOUT_CHANNEL = "invoke-account-logout";
const GET_AUDIO_CHANNEL = "invoke-audio-flush";

View file

@ -2,9 +2,11 @@
import { IpcListener } from "@/composables/useIpcMain"
import { sendMessage } from '@/session';
import { collect } from "@/audio";
import { updateAppState } from "@/account";
const CLIENT_MESSAGE_CHANNEL = "post-session-send"
const GET_AUDIO_CHANNEL = "post-audio-collect";
const APP_MOUNT_CHANNEL = "post-app-mount";
export const messageListener = new IpcListener<Message>({
channel: CLIENT_MESSAGE_CHANNEL,
@ -15,3 +17,8 @@ export const audioChunkListener = new IpcListener<ArrayBuffer>({
channel: GET_AUDIO_CHANNEL,
listenerCallback: collect
});
export const appMountListener = new IpcListener<null>({
channel: APP_MOUNT_CHANNEL,
listenerCallback: updateAppState
});

View file

@ -10,9 +10,8 @@
*/
import initIpcMain from "@/ipc/index";
import { accountAuth } from "./account";
import { accountAuth, updateAppState } from "./account";
import { launchSession } from "./session";
import { ipcEmit } from "./composables/useEmitter";
import createWindow from "./window";
let authState: AuthState | null;
@ -31,12 +30,10 @@ export default async function main() {
console.log('AUTH:', e);
authState = null;
} finally {
let profile = null;
if (authState) {
launchSession(authState.token as string);
profile = authState.profile;
}
ipcEmit("set-profile", profile);
updateAppState();
}
}

View file

@ -23,14 +23,16 @@
<script lang="ts">
import { defineComponent, onMounted, onUnmounted, Ref, ref } from "vue";
import { defineComponent, onMounted } from "vue";
import { IpcRendererEvent } from "electron";
import Splash from "@/render/components/splash.vue";
import Messenger from "@/render/components/messenger.vue";
import Login from "@/render/components/login.vue";
import Header from "@/render/components/header.vue";
import useProfile from "@/render/composables/useProfile";
import { postAppMount } from "@/render/ipc";
export default defineComponent({
@ -43,25 +45,9 @@ export default defineComponent({
setup() {
const authComplete = ref(false);
const { profile, authComplete } = useProfile();
const { setProfile, clearProfile, profile } = useProfile();
onMounted(async () => {
console.log("[APP]:mounted.");
/* listen for auth related messages */
window.ipcRenderer.on("set-profile", (_event: IpcRendererEvent, payload: any) => {
console.log('progfile', payload.message)
payload.message ? setProfile(payload.message) : clearProfile();
authComplete.value = true;
});
});
onUnmounted(() => {
window.ipcRenderer.removeAllListeners("set-profile");
});
onMounted(() => postAppMount());
return {
authComplete,

View file

@ -1,5 +1,38 @@
export default function useIpc () {
import { IpcRendererEvent } from "electron";
export class IpcRendererListener<InputParam> implements IIpcListener<InputParam> {
readonly channel: string;
readonly _listenerCallback: IpcListenerCallback<InputParam>;
constructor(options: {
channel: string;
listenerCallback: IpcListenerCallback<InputParam>;
}) {
this.channel = options.channel;
this._listenerCallback = options.listenerCallback;
}
listen() {
this.remove();
window.ipcRenderer.on(this.channel, this._onPost);
}
remove() {
window.ipcRenderer.removeAllListeners(this.channel);
}
private _onPost = (_e: IpcRendererEvent, payload: IpcEmitPayload<InputParam>): void => {
console.log(`[IPC] Post: ${this.channel}`);
this._listenerCallback(payload.message);
}
}
export default function useIpcRenderer () {
const invoke = async (endpoint: string, payload: any) => {
try {
@ -16,6 +49,6 @@ export default function useIpc () {
return {
invoke,
post
post,
}
}

View file

@ -2,20 +2,30 @@ import { ref } from "vue";
const profile = ref();
const authComplete = ref(false);
const useProfile = () => {
const setProfile = (payload: Profile) => {
profile.value = payload;
const setProfile: IpcListenerCallback<Profile | null> = (payload) => {
payload ? profile.value = payload : clearProfile();
showRender();
}
const clearProfile = () => {
profile.value = null;
}
const showRender = () => {
authComplete.value = true;
}
return {
setProfile,
clearProfile,
profile
profile,
showRender,
authComplete,
}
}

View file

@ -1,5 +1,6 @@
import useIpc from "@/render/composables/useIpcRend";
import * as rendererListeners from "./listeners";
const { post, invoke } = useIpc();
@ -47,3 +48,33 @@ export const invokeSession = async (cid: string): Promise<Profile | Error> => (
export const postMessage = (payload: Message): void => (
post('post-session-send', payload)
);
export const postAppMount = (): void => (
post('post-app-mount', null)
);
/**
*
* Ipc Renderer Listeners
*
*/
let ipcListeners: IPCListeners = {};
export const initIpcRendererListeners = () => {
for (const [key, listener] of Object.entries(rendererListeners)) {
if (!(key in ipcListeners)) {
ipcListeners[key] = listener;
listener.listen();
}
}
};
export const removeListeners = () => {
for (const [key, listener] of Object.entries(rendererListeners)) {
listener.remove();
}
ipcListeners = {};
};

32
src/render/listeners.ts Normal file
View file

@ -0,0 +1,32 @@
import { IpcRendererListener } from "./composables/useIpcRend"
import useProfile from "./composables/useProfile";
const { setProfile } = useProfile();
const SET_PROFILE_CHANNEL = "set-profile";
const INIT_MESSAGES_CHANNEL = "init-messages";
const ADD_MESSAGE_CHANNEL = "add-message";
const UPDATE_MESSAGE_CHANNEL = "update-message";
export const setProfileListener = new IpcRendererListener({
channel: SET_PROFILE_CHANNEL,
listenerCallback: setProfile
});
export const initMessagesListener = new IpcRendererListener({
channel: INIT_MESSAGES_CHANNEL,
listenerCallback: () => {}
});
export const addMessagesListener = new IpcRendererListener({
channel: ADD_MESSAGE_CHANNEL,
listenerCallback: () => {}
});
export const updateMessagesListener = new IpcRendererListener({
channel: UPDATE_MESSAGE_CHANNEL,
listenerCallback: () => {}
});

View file

@ -6,11 +6,16 @@ import App from "./App.vue";
import mitt from "mitt";
import { createApp } from "vue";
import { initIpcRendererListeners } from "./ipc"
// Handle ipcMain events.
initIpcRendererListeners();
// Handle events.
const emitter = mitt();
const app = createApp(App)
const app = createApp(App);
app.provide("mitt", emitter)
app.provide("mitt", emitter);
app.mount("#app");

View file

@ -1,9 +1,10 @@
const Store = require('electron-store');
const schema = {
key: {
token: {
type: 'string',
},
profile: {}
};
const store = new Store({
@ -17,3 +18,14 @@ export const clearToken = (): void => (store.delete("token"));
export const setToken = (token: string): void => (store.set('token', token));
export const setProfile = (profile: Profile): Profile => (store.set('profile', profile));
export const getProfile = (): Profile => (store.get('profile'));
export const clearProfile = (): void => (store.delete('profile'));
export const clearStore = (): void => {
clearToken();
clearProfile();
}

View file

@ -46,8 +46,8 @@ interface IpcHandlerCallback<I, O> {
(payload: I | null): Promise<Error | O>;
}
interface IpcListenerCallback<I> {
(payload: I | null): void;
interface IpcListenerCallback<T> {
(payload: T | null): void;
}
interface IIpcHandler<I, O> {
@ -67,6 +67,10 @@ interface IPCHandlers {
}
interface IPCListeners {
[listener: string]: IIpcListener<any>;
[listener: string]: IIpcListener<any> | null;
}
interface IpcEmitPayload<T> {
message: T | null;
}