Compare commits

..

2 Commits

5 changed files with 55 additions and 141 deletions

View File

@@ -9,5 +9,15 @@ export function useFileStorage() {
return result;
}
return {writeFile, readFile};
const fileExists = async (file : string, inWorkingDir : boolean = true) => {
const result = await window.electron.ipcRenderer.invoke('fileStorage:fileExists', file, inWorkingDir);
return result;
}
const size = async (file : string, inWorkingDir : boolean = true) => {
const result = await window.electron.ipcRenderer.invoke('fileStorage:size', file, inWorkingDir);
return result;
}
return {writeFile, readFile, fileExists, size};
}

View File

@@ -30,7 +30,7 @@ export function useAttachment(attachment: Attachment, keyPlain: string) {
const downloadPercentage = useDownloadStatus(attachment.id);
const [downloadStatus, setDownloadStatus] = useMemory("attachment-downloaded-status-" + attachment.id, DownloadStatus.PENDING, true);
const [downloadTag, setDownloadTag] = useState("");
const {readFile, writeFile} = useFileStorage();
const {readFile, writeFile, fileExists, size} = useFileStorage();
const { downloadFile } = useTransport();
const publicKey = usePublicKey();
const privatePlain = usePrivatePlain();
@@ -83,10 +83,12 @@ export function useAttachment(attachment: Attachment, keyPlain: string) {
* а в загрузках
*/
const preview = getPreview();
const filesize = parseInt(preview.split("::")[0]);
const filename = preview.split("::")[1];
let pathInDownloads = window.downloadsPath + "/Rosetta Downloads/" + filename;
const fileData = await readFile(pathInDownloads, false);
if(fileData){
const exists = await fileExists(pathInDownloads, false);
const existsLength = await size(pathInDownloads, false);
if(exists && existsLength == filesize){
setDownloadStatus(DownloadStatus.DOWNLOADED);
return;
}
@@ -150,7 +152,6 @@ export function useAttachment(attachment: Attachment, keyPlain: string) {
}
setDownloadStatus(DownloadStatus.DECRYPTING);
//console.info("Decrypted attachment ", Buffer.from(keyPlain, 'binary').toString('hex'));
console.info("KP", keyPlain);
const decrypted = await decodeWithPassword(keyPlain, downloadedBlob);
setDownloadTag("");
if(attachment.type == AttachmentType.FILE) {
@@ -162,7 +163,17 @@ export function useAttachment(attachment: Attachment, keyPlain: string) {
const filename = preview.split("::")[1];
let buffer = Buffer.from(decrypted.split(",")[1], 'base64');
let pathInDownloads = window.downloadsPath + "/Rosetta Downloads/" + filename;
await writeFile(pathInDownloads, buffer, false);
/**
* Пишем файл в загрузки, но перед этим выбираем ему название, если файл в загрузках
* уже есть с таким названием то добавляем к названию (1), (2) и так далее, чтобы не перезаписать существующий файл
*/
let finalPath = pathInDownloads;
let fileIndex = 1;
while (await fileExists(finalPath, false)) {
finalPath = window.downloadsPath + "/Rosetta Downloads/" + filename.split(".").slice(0, -1).join(".") + ` (${fileIndex})` + "." + filename.split(".").slice(-1);
fileIndex++;
}
await writeFile(finalPath, buffer, false);
setDownloadStatus(DownloadStatus.DOWNLOADED);
return;
}

View File

@@ -1,4 +1,4 @@
import { app, BrowserWindow, ipcMain } from "electron";
import { app, BrowserWindow } from "electron";
import fs from 'fs/promises'
import { WORKING_DIR } from "../constants";
import path from "path";
@@ -6,30 +6,6 @@ import { Logger } from "../logger";
const logger = Logger('bootloader');
ipcMain.handleOnce('report-boot-process-failed', async () => {
/**
* Если процесс загрузки не завершился успешно, то preload показывает
* экран ошибки, а нам нужно откатиться назад к загрузке dev.html
* и удалить скомпилированные файлы, чтобы при следующем запуске
* приложение попыталось загрузиться в режиме разработки.
*/
let filePath = path.join(WORKING_DIR, 'b');
if(!await existsFile(filePath)){
/**
* Исправление ошибки когда директории нет.
*/
logger.log("No compiled files to remove");
return;
}
await fs.rmdir(filePath, { recursive: true });
logger.log("Boot process failed, removed compiled files");
logger.log(`Removed compiled files at ${filePath}`);
logger.log(`Restarting application in safe mode`);
app.relaunch();
app.exit(0);
});
/**
* Boot функция, эта функция запускает приложение
* @param window окно

View File

@@ -2,16 +2,20 @@ import { ipcMain } from "electron";
import { WORKING_DIR } from "../constants";
import fs from 'fs/promises'
import path from 'path'
import { Logger } from "../logger";
const logger = Logger('ipcFilestorage');
ipcMain.handle('fileStorage:writeFile', async (_, file: string, data: string | Buffer, inWorkingDir : boolean = true) => {
logger.log(`System call fileStorage:writeFile with file=${file} inWorkingDir=${inWorkingDir}`);
const fullPath = path.join(inWorkingDir ? WORKING_DIR : '', file);
await fs.mkdir(path.dirname(fullPath), { recursive: true });
await fs.writeFile(fullPath, data);
console.info("File written to " + fullPath);
return true;
});
ipcMain.handle('fileStorage:readFile', async (_, file: string, inWorkingDir : boolean = true) => {
logger.log(`System call fileStorage:readFile with file=${file} inWorkingDir=${inWorkingDir}`);
try{
const fullPath = path.join(inWorkingDir ? WORKING_DIR : '', file);
const data = await fs.readFile(fullPath);
@@ -19,4 +23,26 @@ ipcMain.handle('fileStorage:readFile', async (_, file: string, inWorkingDir : bo
}catch(e){
return null;
}
});
ipcMain.handle('fileStorage:size', async (_, file: string, inWorkingDir : boolean = true) => {
logger.log(`System call fileStorage:size with file=${file} inWorkingDir=${inWorkingDir}`);
try{
const fullPath = path.join(inWorkingDir ? WORKING_DIR : '', file);
const stats = await fs.stat(fullPath);
return stats.size;
}catch(e){
return 0;
}
});
ipcMain.handle('fileStorage:fileExists', async (_, file: string, inWorkingDir : boolean = true) => {
logger.log(`System call fileStorage:fileExists with file=${file} inWorkingDir=${inWorkingDir}`);
try{
const fullPath = path.join(inWorkingDir ? WORKING_DIR : '', file);
await fs.access(fullPath);
return true;
}catch(e){
return false;
}
});

View File

@@ -2,86 +2,6 @@ import { contextBridge, ipcRenderer, shell } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'
import api from './api'
const applicationLoader = `
<div style="
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #ffffff;
margin-top: 40px;
text-align: center;
">
<div style="
width: 48px;
height: 48px;
border: 4px solid #333333;
border-top-color: #0071e3;
border-radius: 50%;
animation: spin 1s linear infinite;
"></div>
<style>
@keyframes spin {
to { transform: rotate(360deg); }
}
</style>
</div>
`;
const applicationError = `
<div style="
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
height: 100vh;
color: #ffffff;
padding: 40px;
text-align: center;
">
<div style="
flex-direction: column;
align-items: center;
justify-content: center;
">
<div style="
font-size: 72px;
margin-bottom: 20px;
">
<svg width="64" height="64" zoomAndPan="magnify" viewBox="0 0 384 383.999986" preserveAspectRatio="xMidYMid meet" version="1.0"><defs><clipPath id="ab9f3e3410"><path d="M 134 109 L 369.46875 109 L 369.46875 381.34375 L 134 381.34375 Z M 134 109 " clip-rule="nonzero"/></clipPath><clipPath id="39bead0a6b"><path d="M 14.71875 2.59375 L 249 2.59375 L 249 222 L 14.71875 222 Z M 14.71875 2.59375 " clip-rule="nonzero"/></clipPath></defs><g clip-path="url(#ab9f3e3410)"><path fill="#ffffff" d="M 254.15625 284.453125 C 288.414062 275.191406 316.179688 260.617188 337.414062 240.769531 C 358.632812 220.917969 369.257812 195.238281 369.257812 163.691406 L 369.257812 109.996094 L 249.550781 110.222656 L 249.550781 168.148438 C 249.550781 184.847656 241.75 198.195312 226.148438 208.21875 C 210.550781 218.226562 188.175781 223.234375 159.007812 223.234375 L 134.070312 223.234375 L 134.070312 300.996094 L 206.652344 381.429688 L 344.765625 381.429688 L 254.15625 284.453125 " fill-opacity="1" fill-rule="nonzero"/></g><g clip-path="url(#39bead0a6b)"><path fill="#ffffff" d="M 248.417969 109.257812 L 248.417969 2.605469 L 14.769531 2.605469 L 14.769531 221.519531 L 132.9375 221.519531 L 132.9375 109.257812 L 248.417969 109.257812 " fill-opacity="1" fill-rule="nonzero"/></g></svg>
</div>
<h1 style="
font-size: 32px;
font-weight: 600;
margin: 0 0 12px 0;
letter-spacing: -0.5px;
">Application Error</h1>
<p style="
font-size: 17px;
color: #a1a1a6;
margin: 0 0 32px 0;
max-width: 500px;
line-height: 1.5;
">The application failed to load properly. Please wait for application repairing or reinstall application.</p>
${applicationLoader}
</div>
<div style="
display: flex;
flex-direction: row;
gap: 8px;
justify-content: center;
align-items: center;
">
<p style="
font-size: 13px;
color: #5a5a5f;
">rosetta - powering freedom. visit about rosetta-im.com. error: boot_process_failed</p>
</div>
</div>
`;
const exposeContext = async () => {
let version = await ipcRenderer.invoke("get-core-version");
@@ -89,35 +9,6 @@ const exposeContext = async () => {
let arch = await ipcRenderer.invoke("get-arch");
let deviceName = await ipcRenderer.invoke("device:name");
let deviceId = await ipcRenderer.invoke("device:id");
let interval : any = 0;
interval = setInterval(() => {
/**
* Если после определенного таймаута приложение так и
* не загрузилось, то считаем, что процесс завис,
* и показываем экран ошибки. Так же отправляем
* сигнал в main процесс, чтобы тот мог попытаться
* откатить обновление
*/
if (document.body.innerHTML.indexOf("preloadersignature") !== -1) {
/**
* Если сейчас показывается прелоадер, то не считаем
* что обновление битое, так как само обновление еще не
* загрузилось в приложение
*/
return;
}
if (document.body.innerHTML.length < 100) {
/**
* Приложение загружено, а прошло больше 5 секунд
* с момента прелоадера, значит что-то пошло не так
* и нужно показать экран ошибки
*/
document.body.innerHTML = applicationError;
ipcRenderer.invoke("report-boot-process-failed");
}
clearInterval(interval);
}, 5000);
let downloadsPath = await ipcRenderer.invoke("get-downloads-path");
if (process.contextIsolated) {