개요
일렉트론의 기본 타이틀바를 제거하고, 최대화(Maximize), 최소화(minimize), 닫기(close) 기능만 있는 타이틀바를 새로 추가한다.
Modal Window 재사용 이슈
모달 창에 데이터 표시는 잘되지만, 모달 창을 닫은 후 다시 열려고 하면 에러가 발생한다.
Error decompressing a compressed file: TypeError: Object has been destroyed
at viewRcpDetail (D:\\vscode workspace\\recipe.electron\\.webpack\\main\\index.js:13610:39)
at D:\\vscode workspace\\recipe.electron\\.webpack\\main\\index.js:13411:7
at D:\\vscode workspace\\recipe.electron\\.webpack\\main\\index.js:13378:9
위와 같이 Object가 파괴되었다는 에러가 발생하여, 압축 해제를 실행하지 못한다. 이는 모달 창을 닫을 시에 Modal Window 인스턴스가 아예 삭제되기 때문으로 추측한다.
해결법
따라서 일렉트론 앱의 기본 타이틀바를 삭제하고, 임의의 타이틀바 및 닫기 버튼을 추가한다. 닫기 버튼을 클릭할 시에 요청을 main으로 보내고, main에서는 모달 창을 삭제하지 않고 숨김 처리하도록 한다.
타이틀바 기능 구현
//preload.js
...
contextBridge.exposeInMainWorld('apis', {
minimize: (thisWindow) => ipcRenderer.invoke('minimize', thisWindow),
maximize: (thisWindow) => ipcRenderer.invoke('maximize', thisWindow),
unmaximize: (thisWindow) => ipcRenderer.invoke('unmaximize', thisWindow),
close: (thisWindow) => ipcRenderer.invoke('close', thisWindow),
viewMaximizeBtn: (callback) => ipcRenderer.on('viewMaximizeBtn', callback),
...
preload.js: renderer에서 사용할 ipc 함수를 window 전역 변수에 설정한다.
- viewMaimizeBtn 함수는 Maximize(최대화) 상태일 때는 Unmaximize(최대화 해제) 버튼을 표시하고, Maximize 상태가 아닐 때는 Maximize 버튼을 표시하도록 하는 함수이다.
//rcp_ipc.js
...
addTitleBar() {
ipcMain.handle('minimize', (event, thisWindow) => {
if (thisWindow == 'main') {
this.mainWindow.minimize();
} else {
this.modalWindow.minimize();
}
});
ipcMain.handle('maximize', (event, thisWindow) => {
if (thisWindow == 'main') {
this.mainWindow.maximize();
} else {
this.modalWindow.maximize();
}
});
ipcMain.handle('unmaximize', (event, thisWindow) => {
if (thisWindow == 'main') {
this.mainWindow.unmaximize();
} else {
this.modalWindow.unmaximize();
}
});
ipcMain.handle('close', (event, thisWindow) => {
if (thisWindow == 'main') {
this.mainWindow.close();
} else {
// fade out effect
/*
* If you close modalWindow,
* it cannot be reused again, so hide it.
*/
let opacity = 1;
const interval = setInterval(() => {
opacity -= 0.25;
this.modalWindow.setOpacity(opacity);
if (opacity <= 0) {
clearInterval(interval);
this.modalWindow.setHasShadow(false);
this.modalWindow.hide();
this.modalWindow.unmaximize();
this.mainWindow.focus();
}
}, 25);
}
});
}
...
rcp_ipc.js: 타이틀바 관련 IPC 채널 모두 어떤 window에서 온 요청인지 인자로 받아 확인한다. 그리고 해당 window에 알맞는 함수를 호출한다. 단 Modal window에서는 close 함수를 호출하지 않는다. 재사용 이슈를 해결하기 위해 창을 닫지 않고 숨겨두었다가 다시 사용할 수 있도록한다.
//title_bar.js
window.$ = window.jQuery = require('jquery');
/**
* A listener that determines which 'maximize' or 'unmaximize' buttons
* to display on the title bar
*/
window.apis.viewMaximizeBtn((event, value) => {
if (value == 'unmaximize') {
$('#unmaximize').hide();
$('#maximize').show();
} else if (value == 'maximize') {
$('#unmaximize').show();
$('#maximize').hide();
}
});
export class Titlebar {
isMaximized = false;
constructor(_thisWindow) {
this.initTitlebar(_thisWindow);
}
/**
* A function that sets the appropriate click listener f
* or the title bar buttons of '_thisWindow'.
* @param {*} _thisWindow
*/
initTitlebar(_thisWindow) {
$('#minimize').on('click', function () {
window.apis.minimize(_thisWindow);
});
$('#unmaximize').on('click', function () {
this.isMaximized = !this.isMaximized;
window.apis.unmaximize(_thisWindow);
$('#unmaximize').hide();
$('#maximize').show();
});
$('#maximize').on('click', function () {
this.isMaximized = !this.isMaximized;
window.apis.maximize(_thisWindow);
$('#unmaximize').show();
$('#maximize').hide();
});
$('#close').on('click', function () {
window.apis.close(_thisWindow);
});
}
}
title_bar.js: 타이틀바가 필요한 각 renderer.js 에서 import 하여 사용할 js 파일. TitleBar 클래스의 함수는 타이틀바 각 버튼 클릭 리스너에 알맞은 IPC 함수를 매핑해준다.
//main.js
...
mainWindow.on('unmaximize', () => {
mainWindow.webContents.send('viewMaximizeBtn', 'unmaximize');
});
mainWindow.on('maximize', () => {
mainWindow.webContents.send('viewMaximizeBtn', 'maximize');
});
...
main.js: renderer의 타이틀바 Maximize 버튼 표시를 위해 최대화 상태의 여부를 리스너로 받아, renderer로 송신한다.
결과 화면
'토이 프로젝트 > 레시피 일렉트론 앱 (완)' 카테고리의 다른 글
[Electron] 13.멀티스레딩 구현 with worker(2) - 레시피 일렉트론 앱 (0) | 2024.02.12 |
---|---|
[Electron] 12.멀티스레딩 구현 with worker(1) - 레시피 일렉트론 앱 (0) | 2024.02.11 |
[Electron] 10.검색 기능 구현(4): 상세보기 기능(Decompress to modal window) - 레시피 일렉트론 앱 (0) | 2024.02.03 |
[Electron] 9.검색 기능 구현(3): 다운로드 기능(Download buffer) - 레시피 일렉트론 앱 (0) | 2024.02.02 |
[Electron] 8.검색 기능 구현(2): 이미지 설정(Buffer to Data URL) - 레시피 일렉트론 앱 (0) | 2024.02.01 |