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> => {
const parsed = parseAuthRes(res);
setToken(parsed.token)
+ setProfile(parsed.profile);
return {
profile: parsed.profile,
} catch(e) {
console.log('[ACCOUNT]', e);
- clearToken();
+ clearStore();
throw(new Error('Failed to authenticate.'));
}
// save jwt token and profile
setToken(parsed.token);
+ setProfile(parsed.profile);
// launch session
launchSession(parsed.token);
return parsed.profile;
} catch(e) {
+ clearStore();
throw e;
}
}
await postLogout();
// remove key and crimataId
- clearToken();
+ clearStore();
// kill crimata platform session
endSession();
}
+export const updateAppState = (): void => {
+
+ const profile = getProfile();
+
+ ipcEmit("set-profile", profile);
+
+ // ipcEmit('messages') etc
+
+}
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);
}
}
-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);
}
}
}
-
-
-
-
"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";
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,
channel: GET_AUDIO_CHANNEL,
listenerCallback: collect
});
+
+export const appMountListener = new IpcListener<null>({
+ channel: APP_MOUNT_CHANNEL,
+ listenerCallback: updateAppState
+});
*/
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;
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();
}
}
<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({
setup() {
- const authComplete = ref(false);
-
- 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;
- });
-
- });
+ const { profile, authComplete } = useProfile();
- onUnmounted(() => {
- window.ipcRenderer.removeAllListeners("set-profile");
- });
+ onMounted(() => postAppMount());
return {
authComplete,
-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 {
const res = await window.ipcRenderer.invoke(endpoint, payload);
return {
invoke,
- post
+ post,
}
}
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,
}
}
import useIpc from "@/render/composables/useIpcRend";
+import * as rendererListeners from "./listeners";
const { post, invoke } = useIpc();
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 = {};
+};
+
--- /dev/null
+
+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: () => {}
+});
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");
const Store = require('electron-store');
const schema = {
- key: {
+ token: {
type: 'string',
},
+ profile: {}
};
const store = new Store({
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();
+}
+
(payload: I | null): Promise<Error | O>;
}
-interface IpcListenerCallback<I> {
- (payload: I | null): void;
+interface IpcListenerCallback<T> {
+ (payload: T | null): void;
}
interface IIpcHandler<I, O> {
}
interface IPCListeners {
- [listener: string]: IIpcListener<any>;
+ [listener: string]: IIpcListener<any> | null;
+}
+
+interface IpcEmitPayload<T> {
+ message: T | null;
}