Site icon May's Notes

[Electron筆記] mainWindow & Tray & context-isolation & MessagePort

Electron logo

只做記錄用,不是教學

mainWindow

const { app, BrowserWindow, screen } = require('electron')

let mainWindow: Electron.CrossProcessExports.BrowserWindow

// 從隱藏狀態恢復視窗
const openWindow = () => {
  if (mainWindow) {
    mainWindow.restore()
    mainWindow.show()
  }
}


const createWindow = () => {
  const screenDimention = screen.getPrimaryDisplay().workAreaSize
  const scaleFactor = getScaleFactor(screenDimention.width)
  const windowSize = getWindowSize(scaleFactor)

  mainWindow = new BrowserWindow({
    transparent: true,
    width: windowSize.width,
    height: windowSize.height,
    frame: false,
    resizable: false,
    autoHideMenuBar: true,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js'),
      zoomFactor: scaleFactor,
    },
    show: false,
  })
  
  // 關閉改為隱藏
  mainWindow.on('close', (event) => {
    event.preventDefault()
    mainWindow.hide()
  })

  if (MAIN_WINDOW_VITE_DEV_SERVER_URL) {
    mainWindow.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL)

    mainWindow.webContents.openDevTools()
  } else {
    mainWindow.loadFile(
      path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`),
    )
  }
}
app.on('ready', createWindow)

app.on('activate', () => {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})

context-isolation & MessagePort

在 main windows 開啟應用中的設置 modal

main-windows.ts

const { app, BrowserWindow, screen } = require('electron')

let mainWindow: Electron.CrossProcessExports.BrowserWindow

const openWindow = () => {
  if (mainWindow) {
    mainWindow.restore()
    mainWindow.show()
  }
}

// 開啟主視窗底下的設定 modal
const openSettingModal = () => {
  openWindow()
  mainWindow.webContents.postMessage('OPEN-SETTING-MODAL', undefined)
}

const createWindow = () => {
  const screenDimention = screen.getPrimaryDisplay().workAreaSize
  const scaleFactor = getScaleFactor(screenDimention.width)
  const windowSize = getWindowSize(scaleFactor)

  mainWindow = new BrowserWindow({
    transparent: true,
    width: windowSize.width,
    height: windowSize.height,
    frame: false,
    resizable: false,
    autoHideMenuBar: true,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js'),
      zoomFactor: scaleFactor,
    },
    show: false,
  })
  // ...  
}

app.tsx

const AppContent = () => {
  const { show } = useSettingsModal()

  useEffect(() => {
    window.bridge.listenChannel('OPEN-SETTINGS-MODAL', show)
  }, [])
  
  //...
  
}

preload.ts

import { contextBridge, ipcRenderer } from 'electron'

export type ContextBridgeApiType = {
  listenChannel: (channel: string, func: Function) => void
}
const contextBridgeApi: ContextBridgeApiType = {
  listenChannel: (channel, func) =>
    ipcRenderer.on(channel, (_, ...args) => func(...args)),
}

contextBridge.exposeInMainWorld('bridge', contextBridgeApi)

Tray

只顯示 Tray 不顯示主視窗,或者只顯示主視窗不顯示 Tray

Tray:https://www.electronjs.org/docs/latest/api/tray

const { app, BrowserWindow, Tray, Menu, screen } = require('electron')

let mainWindow: Electron.CrossProcessExports.BrowserWindow
// Tray
let tray: Electron.CrossProcessExports.Tray

const openWindow = () => {
  if (mainWindow) {
    mainWindow.restore()
    mainWindow.show()
  }
}

const exitApp = () => mainWindow.destroy()

// Tray menu
const generateContextMenu = (): Electron.Menu => {
  const menu = Menu.buildFromTemplate([
    { label: 'Open APP', type: 'normal', click: openWindow },
    {
      label: 'Settings', type: 'normal', click: openSettingModal
    },
    { label: 'Exit', type: 'normal', click: exitApp }
  ])
  return menu
}

// 創建 Tray
const createSystemTray = () => {
  if (tray) return

  tray = new Tray('public/images/logo.png')

  const contextMenu = generateContextMenu()

  tray.setContextMenu(contextMenu)
  tray.on('click', openWindow)
}

const createWindow = () => {
  const screenDimention = screen.getPrimaryDisplay().workAreaSize
  const scaleFactor = getScaleFactor(screenDimention.width)
  const windowSize = getWindowSize(scaleFactor)

  mainWindow = new BrowserWindow({
    transparent: true,
    width: windowSize.width,
    height: windowSize.height,
    frame: false,
    resizable: false,
    autoHideMenuBar: true,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js'),
      zoomFactor: scaleFactor,
    },
    show: false,
  })

  // 根據存在 localStorage 中的資料判斷是只開啟 tray 還是要顯示主視窗畫面
  mainWindow.webContents.executeJavaScript('localStorage.getItem("application-storage")', true)
    .then((res) => {
      if (xxxxx) {
        // 只顯示 tray
        createSystemTray()
      } else {
        // 顯示主視窗
        mainWindow.show()
      }
    })

  // ...
}
Exit mobile version