diff --git a/package.json b/package.json index b11c9db..3cc50ff 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@vue/eslint-config-typescript": "^5.0.2", "@vue/test-utils": "^2.0.0-0", "@wasm-tool/wasm-pack-plugin": "^1.3.1", - "electron": "^9.0.0", + "electron": "^8.3.3", "electron-devtools-installer": "^3.1.0", "electron-log": "^4.3.4", "eslint": "^6.7.2", diff --git a/src/images/icon.png b/src/images/icon.png new file mode 100644 index 0000000..b925c06 Binary files /dev/null and b/src/images/icon.png differ diff --git a/src/images/icon@2x.png b/src/images/icon@2x.png new file mode 100644 index 0000000..7bf880c Binary files /dev/null and b/src/images/icon@2x.png differ diff --git a/src/images/icon_32x32.png b/src/images/icon_32x32.png new file mode 100644 index 0000000..7bf880c Binary files /dev/null and b/src/images/icon_32x32.png differ diff --git a/src/images/icon_32x32@2x.png b/src/images/icon_32x32@2x.png new file mode 100644 index 0000000..2a9f925 Binary files /dev/null and b/src/images/icon_32x32@2x.png differ diff --git a/src/init.ts b/src/init.ts index 637db63..25de81d 100644 --- a/src/init.ts +++ b/src/init.ts @@ -9,7 +9,7 @@ import { app, protocol } from "electron"; import createWindow from "./window"; import main from "./main"; import { backgroundMitt } from '@/composables/useEmitter'; -import {setWindow, getWindow } from './store'; +import {setWindowOpen, getWindowOpen } from './store'; console.log('Starting Crimata electron app.'); @@ -22,7 +22,7 @@ const isDev = require('electron-is-dev'); // Listen for window creation. backgroundMitt.on('window-active', (state: boolean) => { - setWindow(state) + setWindowOpen(state) }); /* Start main process on ready */ @@ -40,7 +40,7 @@ app.on("window-all-closed", () => { // When user clicks app icon (re-open) app.on("activate", () => { - if (!getWindow()) createWindow(); + if (!getWindowOpen()) createWindow(); }); // Exit cleanly on request from parent process in development mode. diff --git a/src/ipc/listeners.ts b/src/ipc/listeners.ts index f92bead..ef0f965 100644 --- a/src/ipc/listeners.ts +++ b/src/ipc/listeners.ts @@ -1,12 +1,13 @@ - import { IpcListener } from "@/composables/useIpcMain" import { sendMessage } from '@/session'; import { updateAppState } from "@/account"; import { onNavBar } from "@/window"; +import { setWindowFocus } from '@/store'; const CLIENT_MESSAGE_CHANNEL = "post-session-send" const APP_MOUNT_CHANNEL = "post-app-mount"; const NAV_BAR_CHANNEL = "post-nav-bar"; +const POST_WINDOW_FOCUS = 'post-window-focus'; export const messageListener = new IpcListener({ channel: CLIENT_MESSAGE_CHANNEL, @@ -22,3 +23,8 @@ export const navBarListener = new IpcListener({ channel: NAV_BAR_CHANNEL, listenerCallback: onNavBar }); + +export const windowFocusListener = new IpcListener({ + channel: POST_WINDOW_FOCUS, + listenerCallback: ({ isFocused }) => setWindowFocus(isFocused) +}); diff --git a/src/main.ts b/src/main.ts index 334a6fe..2cb205c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -13,8 +13,37 @@ import initIpcMain from "@/ipc/index"; import { accountAuth } from "./account"; import createWindow from "./window"; +import { Menu, Tray } from 'electron'; +const nativeImage = require('electron').nativeImage +import path, {resolve} from 'path'; + +let tray = null export default async function main() { + // TODO: fix image paths + // currently looking in dist-electron directory + // should be looking in source + console.log(resolve(__dirname, './images', 'icon.png')) + console.log(path.join(__dirname, './images/icon.png')) + try { + const image = nativeImage.createFromPath(resolve(__dirname, 'images', 'icon_16x16.png')); + const urlImage = nativeImage.createFromDataURL('https://github.com/vladimiry-playground/electron-quick-start-tray-issue/blob/master/icon.png'); + console.log(image) + console.log(urlImage) + tray = new Tray(resolve(__dirname, 'images', 'icon_16x16.png')) + } catch(e) { + console.log(e) + } + // const contextMenu = Menu.buildFromTemplate([ + // { label: 'Item1', type: 'radio' }, + // { label: 'Item2', type: 'radio' }, + // { label: 'Item3', type: 'radio', checked: true }, + // { label: 'Item4', type: 'radio' } + // ]) + // tray.setToolTip('This is my application.') + // tray.setContextMenu(contextMenu) + + /* initiate controls for frontend to use when needed */ initIpcMain(); diff --git a/src/render/components/messenger.vue b/src/render/components/messenger.vue index df7dc15..ad41e2e 100644 --- a/src/render/components/messenger.vue +++ b/src/render/components/messenger.vue @@ -31,7 +31,7 @@ import ConnectionStatus from "./connectionStatus.vue"; import { profile } from "@/render/shared/profile"; import { messages } from "@/render/shared/messages"; import useScroll from "@/render/composables/useScroll"; -import { postMessage } from "@/render/ipc"; +import { postMessage, postWindowFocus } from "@/render/ipc"; export default defineComponent({ name: "Messenger", @@ -46,6 +46,7 @@ export default defineComponent({ setup() { const onFocus = () => { + postWindowFocus({ isFocused: true }); postMessage({ intent: "focus", params: { "focus": true }, @@ -55,6 +56,7 @@ export default defineComponent({ } const onBlur = () => { + postWindowFocus({ isFocused: false }); postMessage({ intent: "focus", params: { "focus": false }, diff --git a/src/render/ipc.ts b/src/render/ipc.ts index b787831..e6e994c 100644 --- a/src/render/ipc.ts +++ b/src/render/ipc.ts @@ -65,7 +65,7 @@ export const postNavBar = (payload: string): void => ( * */ -export const postWindowBlur = (payload: { isFocused: boolean }): void => ( +export const postWindowFocus = (payload: { isFocused: boolean }): void => ( post('post-window-focus', payload) ); diff --git a/src/session.ts b/src/session.ts index be6fdd3..f379f88 100644 --- a/src/session.ts +++ b/src/session.ts @@ -5,7 +5,7 @@ import { config } from "@/config"; import useWebsockets from "./composables/useWebsockets"; import { backgroundMitt, ipcEmit } from "@/composables/useEmitter"; import { Notification } from 'electron'; -import { getWindow } from './store'; +import { getWindowFocus, getWindowOpen } from './store'; function showNotification (options: { title: string; @@ -40,8 +40,10 @@ const onMessageCallback = (payload: string) => { const body = message.body as Update; uiState.update(body); + const isFocused = getWindowFocus(); + const isOpen = getWindowOpen(); // show notification if window is not active - if (!getWindow()) { + if (!isFocused || !isOpen) { if (body.name === "add") { const data = body.data as Message; showNotification({ @@ -77,7 +79,7 @@ export const updateAppUI = (): void => { uiState.emit(); } -export function sendMessage(message: Raw | Request): void { +export function sendMessage(message: Raw | Request): void { send(message); } diff --git a/src/store.ts b/src/store.ts index 8ac280e..eab4cc7 100644 --- a/src/store.ts +++ b/src/store.ts @@ -4,9 +4,6 @@ const schema = { token: { type: 'string', }, - window: { - type: 'boolean' - } }; const store = new Store({ @@ -32,14 +29,19 @@ export const clearToken = (): void => { /* * Window state management * */ -export const setWindow = (state: boolean): void => { - store.set("window", state); +export const setWindowOpen = (state: boolean): void => { + store.set("window.isOpen", state); } -export const getWindow = (): boolean | undefined => { - return store.get("window"); +export const getWindowOpen = (): boolean | undefined => { + return store.get("window.isOpen"); } -export const clearWindow = (): void => { - store.delete("window"); +export const setWindowFocus = (state: boolean): void => { + store.set("window.isFocused", state); } + +export const getWindowFocus = (): boolean | undefined => { + return store.get("window.isFocused"); +} + diff --git a/src/types.ts b/src/types.ts index ba36056..51d1c68 100644 --- a/src/types.ts +++ b/src/types.ts @@ -125,3 +125,7 @@ interface IpcRendererEvent { payload: T | null; } +interface FocusPayload { + isFocused: boolean; +} + diff --git a/yarn.lock b/yarn.lock index e79f19f..55fa251 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5077,10 +5077,10 @@ electron-updater@^4.3.8: lodash.isequal "^4.5.0" semver "^7.3.4" -electron@^9.0.0: - version "9.3.3" - resolved "https://registry.yarnpkg.com/electron/-/electron-9.3.3.tgz#99a6619d5df68f97697a5d1d82ef3a8a63fcdf36" - integrity sha512-xghKeUY1qgnEcJ5w2rXo/toH+8NT2Dktx2aAxBNPV7CIJr3mejJJAPwLbycwtddzr37tgKxHeHlc8ivfKtMkJQ== +electron@^8.3.3: + version "8.5.5" + resolved "https://registry.yarnpkg.com/electron/-/electron-8.5.5.tgz#17b12bd70139c0099f750fc5de0d480bf03acb96" + integrity sha512-e355H+tRDial0m+X2v+l+0SnaATAPw4sNjv9qmdk/6MJz/glteVJwVJEnxTjPfEELIJSChrBWDBVpjdDvoBF4Q== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12"