Skip to content

Commit 34fa50f

Browse files
committed
feat(stage-tamagotchi): chat window
1 parent 26f4d91 commit 34fa50f

File tree

6 files changed

+67
-12
lines changed

6 files changed

+67
-12
lines changed

apps/stage-tamagotchi/src/main/index.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { openDebugger, setupDebugger } from './app/debugger'
1818
import { emitAppBeforeQuit, emitAppReady, emitAppWindowAllClosed, onAppBeforeQuit } from './libs/bootkit/lifecycle'
1919
import { setElectronMainDirname } from './libs/electron/location'
2020
import { setupCaptionWindowManager } from './windows/caption'
21+
import { setupChatWindowReusableFunc } from './windows/chat'
2122
import { setupInlayWindow } from './windows/inlay'
2223
import { setupMainWindow } from './windows/main'
2324
import { setupSettingsWindowReusableFunc } from './windows/settings'
@@ -130,17 +131,20 @@ app.whenReady().then(async () => {
130131
const settingsWindow = injecta.provide('windows:settings', {
131132
build: () => setupSettingsWindowReusableFunc(),
132133
})
134+
const chatWindow = injecta.provide('windows:chat', {
135+
build: () => setupChatWindowReusableFunc(),
136+
})
133137
const mainWindow = injecta.provide('windows:main', {
134-
dependsOn: { settingsWindow },
138+
dependsOn: { settingsWindow, chatWindow },
135139
build: async ({ dependsOn }) => setupMainWindow(dependsOn),
136140
})
137141
const captionWindow = injecta.provide('windows:caption', {
138142
dependsOn: { mainWindow },
139-
build: async ({ dependsOn }) => setupCaptionWindowManager({ mainWindow: dependsOn.mainWindow }),
143+
build: async ({ dependsOn }) => setupCaptionWindowManager(dependsOn),
140144
})
141145
const tray = injecta.provide('app:tray', {
142146
dependsOn: { mainWindow, settingsWindow, captionWindow },
143-
build: async ({ dependsOn }) => setupTray(dependsOn as any),
147+
build: async ({ dependsOn }) => setupTray(dependsOn),
144148
})
145149
injecta.invoke({
146150
dependsOn: { mainWindow, tray },
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { join, resolve } from 'node:path'
2+
3+
import { BrowserWindow, shell } from 'electron'
4+
5+
import icon from '../../../../resources/icon.png?asset'
6+
7+
import { baseUrl, getElectronMainDirname, load, withHashRoute } from '../../libs/electron/location'
8+
import { createReusableWindow } from '../../libs/electron/window-manager'
9+
10+
export function setupChatWindowReusableFunc() {
11+
return createReusableWindow(async () => {
12+
const window = new BrowserWindow({
13+
title: 'Chat',
14+
width: 600.0,
15+
height: 800.0,
16+
show: false,
17+
icon,
18+
webPreferences: {
19+
preload: join(__dirname, '../preload/index.mjs'),
20+
sandbox: false,
21+
},
22+
})
23+
24+
window.on('ready-to-show', () => window.show())
25+
window.webContents.setWindowOpenHandler((details) => {
26+
shell.openExternal(details.url)
27+
return { action: 'deny' }
28+
})
29+
30+
await load(window, withHashRoute(baseUrl(resolve(getElectronMainDirname(), '..', 'renderer')), '/chat'))
31+
32+
return window
33+
}).getWindow
34+
}

apps/stage-tamagotchi/src/main/windows/main/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ interface AppConfig {
2727

2828
export async function setupMainWindow(params: {
2929
settingsWindow: () => Promise<BrowserWindow>
30+
chatWindow: () => Promise<BrowserWindow>
3031
}) {
3132
const {
3233
setup: setupConfig,
@@ -122,7 +123,7 @@ export async function setupMainWindow(params: {
122123

123124
await load(window, baseUrl(resolve(getElectronMainDirname(), '..', 'renderer')))
124125

125-
setupMainWindowElectronInvokes({ window, settingsWindow: params.settingsWindow })
126+
setupMainWindowElectronInvokes({ window, settingsWindow: params.settingsWindow, chatWindow: params.chatWindow })
126127

127128
/**
128129
* This is a know issue (or expected behavior maybe) to Electron.

apps/stage-tamagotchi/src/main/windows/main/rpc/index.electron.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ import { defineInvokeHandler } from '@unbird/eventa'
44
import { createContext } from '@unbird/eventa/adapters/electron/main'
55
import { ipcMain } from 'electron'
66

7-
import { electronOpenMainDevtools, electronOpenSettings } from '../../../../shared/eventa'
7+
import { electronOpenChat, electronOpenMainDevtools, electronOpenSettings } from '../../../../shared/eventa'
88
import { createScreenService, createWindowService } from '../../../services/electron'
99
import { toggleWindowShow } from '../../shared'
1010

11-
export function setupMainWindowElectronInvokes(params: { window: BrowserWindow, settingsWindow: () => Promise<BrowserWindow> }) {
11+
export function setupMainWindowElectronInvokes(params: {
12+
window: BrowserWindow
13+
settingsWindow: () => Promise<BrowserWindow>
14+
chatWindow: () => Promise<BrowserWindow>
15+
}) {
1216
// TODO: once we refactored eventa to support window-namespaced contexts,
1317
// we can remove the setMaxListeners call below since eventa will be able to dispatch and
1418
// manage events within eventa's context system.
@@ -21,4 +25,5 @@ export function setupMainWindowElectronInvokes(params: { window: BrowserWindow,
2125

2226
defineInvokeHandler(context, electronOpenMainDevtools, () => params.window.webContents.openDevTools({ mode: 'detach' }))
2327
defineInvokeHandler(context, electronOpenSettings, async () => toggleWindowShow(await params.settingsWindow()))
28+
defineInvokeHandler(context, electronOpenChat, async () => toggleWindowShow(await params.chatWindow()))
2429
}

apps/stage-tamagotchi/src/renderer/components/Widgets/ControlsIsland/index.vue

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import { HearingConfigDialog } from '@proj-airi/stage-ui/components'
33
import { useSettingsAudioDevice } from '@proj-airi/stage-ui/stores/settings'
44
import { defineInvoke } from '@unbird/eventa'
5-
import { createContext } from '@unbird/eventa/adapters/electron/renderer'
65
import { useDark, useToggle } from '@vueuse/core'
76
import { storeToRefs } from 'pinia'
87
import { ref } from 'vue'
@@ -12,25 +11,26 @@ import ControlButton from './ControlButton.vue'
1211
import ControlButtonTooltip from './ControlButtonTooltip.vue'
1312
import IndicatorMicVolume from './IndicatorMicVolume.vue'
1413
15-
import { electronOpenSettings, electronStartDraggingWindow } from '../../../../shared/eventa'
14+
import { electronOpenChat, electronOpenSettings, electronStartDraggingWindow } from '../../../../shared/eventa'
15+
import { useElectronEventaContext, useElectronEventaInvoke } from '../../../composables/electron-vueuse/use-electron-eventa-context'
1616
import { isLinux } from '../../../utils/platform'
1717
1818
const isDark = useDark({ disableTransition: false })
1919
const toggleDark = useToggle(isDark)
2020
2121
const settingsAudioDeviceStore = useSettingsAudioDevice()
22+
const context = useElectronEventaContext()
2223
const { enabled: isAudioEnabled } = storeToRefs(settingsAudioDeviceStore)
23-
24-
const { context } = createContext(window.electron.ipcRenderer)
25-
const openSettings = defineInvoke(context, electronOpenSettings)
24+
const openSettings = useElectronEventaInvoke(electronOpenSettings)
25+
const openChat = useElectronEventaInvoke(electronOpenChat)
2626
2727
/**
2828
* This is a know issue (or expected behavior maybe) to Electron.
2929
* We don't use this approach on Linux because it's not working.
3030
*
3131
* See `apps/stage-tamagotchi/src/main/windows/main/index.ts` for handler definition
3232
*/
33-
const startDraggingWindow = !isLinux ? defineInvoke(context, electronStartDraggingWindow) : undefined
33+
const startDraggingWindow = !isLinux ? defineInvoke(context.value, electronStartDraggingWindow) : undefined
3434
3535
// Expose whether hearing dialog is open so parent can disable click-through
3636
const hearingDialogOpen = ref(false)
@@ -50,6 +50,16 @@ defineExpose({ hearingDialogOpen })
5050
</template>
5151
</ControlButtonTooltip>
5252

53+
<ControlButtonTooltip>
54+
<ControlButton @click="openChat">
55+
<div i-solar:chat-line-line-duotone size-5 text="neutral-800 dark:neutral-300" />
56+
</ControlButton>
57+
58+
<template #tooltip>
59+
Open Chat
60+
</template>
61+
</ControlButtonTooltip>
62+
5363
<ControlButtonTooltip>
5464
<HearingConfigDialog v-model:show="hearingDialogOpen">
5565
<div class="relative">

apps/stage-tamagotchi/src/shared/eventa.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export const electronStartTrackMousePosition = defineInvokeEventa('eventa:invoke
44
export const electronStartDraggingWindow = defineInvokeEventa('eventa:invoke:electron:start-dragging-window')
55
export const electronOpenMainDevtools = defineInvokeEventa('eventa:invoke:electron:windows:main:devtools:open')
66
export const electronOpenSettings = defineInvokeEventa('eventa:invoke:electron:windows:settings:open')
7+
export const electronOpenChat = defineInvokeEventa('eventa:invoke:electron:windows:chat:open')
78
export const electronOpenSettingsDevtools = defineInvokeEventa('eventa:invoke:electron:windows:settings:devtools:open')
89
export const captionIsFollowingWindowChanged = defineEventa<boolean>('eventa:event:electron:windows:caption-overlay:is-following-window-changed')
910
export const captionGetIsFollowingWindow = defineInvokeEventa<boolean>('eventa:invoke:electron:windows:caption-overlay:get-is-following-window')

0 commit comments

Comments
 (0)