Electron и Typescript - Приложение для просмотра файлов на рабочем столе
Библиотека Electron проста в использовании для нативных настольных приложений со знанием веб-технологий. Если вы новичок в Electron и нуждаетесь в представлении, ознакомьтесь с этой статьей. В этой статье мы собираемся создать собственный файловый менеджер с возможностью просмотра нескольких папок или файлов одновременно. Мы будем использовать TypeScript поверх библиотеки Electron.
Приступим
Мы можем начать с проекта шаблона из этого github репозитория. Просто клонируйте проект и выполните следующие команды:
npm install
npm start
Это запустит наше приложение и отобразит окно браузера, которое отображает версию Node и Electron, которую мы используем.
Теперь мы добавим кнопку для открытия диалогового окна выбора папок и кнопку ввода для отображения выбранных папок и файлов.
В renderer.ts у нас есть обработчик события клик у кнопок для отправки канала ipcRenderer
.
btn.addEventListener("click", (ev: Event) => {
ipcRenderer.send("showFolderDialog");
});
В main.ts, у нас есть подписчик showfolderdialog
, по событию которого затем откроется диалог. Диалог будет предоставлен Electron, который имеет свойства openfile
и opendirectory
с несколькими вариантами выбора.
Затем, когда обещание выполняется, мы получаем пути к выбранным файлам, которые отображают путь для чтения каталога и получают все файлы внутри каталога. Их мы отправляем в функцию reduce
, чтобы получить статистику файлов. Он будет отправлять файлы со статистикой, отправленной через канал filelist
.
Функция Reduce состоит в том, чтобы объединить все файлы разных папок в один список.
Мы также отправляем пути к файлам отдельно, отправляя selectedfolders
для отображения пути к папкам в поле ввода.
ipcMain.on("showFolderDialog", (event: IpcMainEvent) => {
let fileSelectionPromise = dialog.showOpenDialog({
properties: ["openFile", "openDirectory", "multiSelections"]
});
fileSelectionPromise.then(function(obj) {
event.sender.send("selectedfolders", obj.filePaths);
let cumfileslist = obj.filePaths.map((filePath, index)=>{
return fs.readdirSync(filePath, {withFileTypes: true})
.filter(dirent=>!dirent.isDirectory())
.map(dirent=>filePath + "/" + dirent.name);
}).reduce((filesacc, files) => {
filesacc = filesacc.concat(files);
return filesacc;
}).every((absolutefilepath, index, array) => {
let stats:fs.Stats = fs.statSync(absolutefilepath);
event.sender.send("fileslist", path.basename(absolutefilepath), stats);
return true;
});
});
});
В renderer.ts, используются selectedfolders
для создания слушателя событий, чтобы получить все пути к файлам, а затем объединить их с pipe и поместить его в значении.
ipcRenderer.on("selectedfolders", (evt: IpcRendererEvent, selectedfolders: string[]) => {
const selectedFolderElem: HTMLInputElement = document.getElementById("selectedfolders") as HTMLInputElement;
selectedFolderElem.value = selectedFolderElem.value !== "" ? selectedFolderElem.value + "|"
: selectedFolderElem.value;
selectedFolderElem.value += selectedfolders.join(" | ");
});
Чтобы получить список всех файлов, у нас может быть ul
элемент и элемент шаблона, который можно развернуть для каждого отображения файла.
234234
234
В renderer.ts он прослушивает элемент filelist
, который получает параметры (имя файла, статистика) и заполняет все элементы span
в шаблоне. Затем шаблон клонируется и добавляется к элементу ul
.
ipcRenderer.on("fileslist", (event: IpcRendererEvent, fileName: string, stats: fs.Stats) => {
const filetemplate = document.getElementById("filerec") as HTMLTemplateElement;
const filedisplayrec = filetemplate.content;
const spanElements = filedisplayrec.querySelectorAll("span");
spanElements[0].innerText = fileName;
spanElements[1].innerText = stats.size.toString();
spanElements[2].innerText = stats.mtime.toString();
const nodeElement: Node = filedisplayrec.cloneNode(true);
document.getElementById("filelist").appendChild(nodeElement);
});
Настольное приложение наконец-то будет выглядеть так. Полный исходный код доступен на github.