출처. https://www.electronjs.org/docs/latest/tutorial/dark-mode
앞서 공부했던 mainProcess, rendererProcess와
ipc, 프로그램의 전체적인 Process를 공부해보자!!
ps. 항상 출처를 앞에 다는 이유는 내가 비전공자이기 때문에 정확하지 않은 정보를 제공할 수 있으므로!!
html button에서 toggle 된 값을 가지고 css theme을 변경해주는 예제다.
우선 nativeTheme.shouldUseDarkColors가 true일 때 접근 가능하다고 API문서에서 설명하고 있다.
https://www.electronjs.org/docs/latest/api/native-theme#nativethemethemesource
이 점을 기억하고 시작해보자.
html에서 버튼과 글을 추가해준다.
//index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<link href="./styles.css" rel="stylesheet">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
//main.js에서 innerHTML로 접근할 예정
<p>Current Theme Source: <strong id="theme-source">System</strong><p>
//renderer.js에서 이벤트를 읽을 예정
<button id="toggle-dark-mode">Toggle Dark Mode</button>
<button id="reset-to-system">Reset to System Theme</button>
<!-- You can also require other files to run in this process -->
<script src="renderer.js"></script>
</body>
</html>
css에서 실제로 바꿔줄 값을 지정해준다.
/* styles.css */
@media (prefers-color-scheme: dark) {
body { background: #333; color: white;
}
@media (prefers-color-scheme: light) {
body { background: #ddd; color: black;
}
main.js의 window 객체가 darkMode를 호출할 수 있게
preload.js에 contextBridge를 이용해서 darkMode를 추가해준다.
이 contextBridge안의 채널인 toggle과 system을 통해 신호를 주고 받는다.
신호는 dark-mode-toggle, dark-mode-system이다.
//preload.js
const { contextBridge, ipcRenderer } = require('electron')
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
contextBridge.exposeInMainWorld('darkMode', {
toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
system: () => ipcRenderer.invoke('dark-mode:system')
})
그럼 이 채널을 가지고 renderer.js에서 main.js에게 특정 행동을 요청하고 html 소스도 수정한다.
여기서 main.js에게 특정 행동을 요청할 땐 window Object를 이용한다.
//renderer.js
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
const isDarkMode = await window.darkMode.toggle()
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
})
document.getElementById('reset-to-system').addEventListener('click', async () => {
await window.darkMode.system()
document.getElementById('theme-source').innerHTML = 'System'
})
최종적으로 renderer.js에게 받은 요청을 ipcMain.handle을 통해 메인 프로세스에서 처리하게 된다.
//main.js
const {app, BrowserWindow, ipcMain, nativeTheme} = require('electron')
const path = require('path')
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.loadFile('index.html')
ipcMain.handle('dark-mode:toggle', () => {
if(nativeTheme.shouldUseDarkColors) {
nativeTheme.themeSource = 'light'
}else {
nativeTheme.themeSource = 'dark'
}
return nativeTheme.shouldUseDarkColors
})
ipcMain.handle('dark-mode:system', () => {
nativeTheme.themeSource = 'system'
})
}
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
main.js의 window에서 preload.js의 채널을 통해 받은 명령만 처리하기 위해 이렇게 복잡한 로직이 생긴 것 같다....
이런 식으로 잘 동작한다.
생각보다 복잡한..... 이벤트 처리 방식이다. 이래서 리소스를 많이 차지한다고 하는 건가??
다른 예제들도 많이 해보면서 실력을 키워야겠다.
'Study & Project ✏️ > electron 🐣' 카테고리의 다른 글
[라즈베리파이 크로스컴파일] 4. electron desktop file 예제 (0) | 2022.01.05 |
---|---|
[라즈베리파이 크로스컴파일] 3. electron keyboard shortcuts 예제 (0) | 2022.01.05 |
[라즈베리파이 크로스컴파일] electron process model 공부2! (0) | 2022.01.03 |
[라즈베리파이 크로스컴파일] 라즈베리파이에 node.js 설치하기 (0) | 2021.12.28 |
[라즈베리파이 크로스컴파일] electron process model 공부! (0) | 2021.12.28 |