main.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. const { app, BrowserWindow, Menu, session, ipcMain, screen } = require('electron');
  2. const path = require('path');
  3. const fs = require('fs');
  4. const crypto = require('crypto');
  5. const isDev = process.env.NODE_ENV === 'development';
  6. const algorithm = 'aes-256-ctr';
  7. const password = 'skyfffire-password';
  8. const key = crypto.createHash('sha256').update(password).digest();
  9. let memoryCache = {};
  10. const loginFilePath = path.join(app.getPath('userData'), 'loginSession2.json');
  11. const symbolFilePath = path.join(app.getPath('userData'), 'symbolSession.json');
  12. const persistentFilePath = path.join(app.getPath('userData'), 'persistentSession.json');
  13. const mergeFilePath = path.join(app.getPath('userData'), 'mergeSession.json');
  14. const dbBasePath = path.join(app.getPath('userData'))
  15. function readData(filePath) {
  16. try {
  17. if (fs.existsSync(filePath)) {
  18. const rawData = fs.readFileSync(filePath);
  19. return JSON.parse(rawData);
  20. }
  21. } catch (error) {
  22. console.error('Error reading data:', error);
  23. }
  24. return {};
  25. }
  26. function writeData(filePath, data) {
  27. try {
  28. fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
  29. } catch (error) {
  30. console.error(`Error writing data to ${filePath}:`, error);
  31. }
  32. }
  33. // Function to decrypt a file and store its content in memory
  34. function decryptFile(filePath) {
  35. const fileContent = fs.readFileSync(filePath);
  36. const iv = fileContent.slice(0, 16); // Extract IV
  37. const encrypted = fileContent.slice(16); // Extract encrypted data
  38. const decipher = crypto.createDecipheriv(algorithm, key, iv);
  39. const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
  40. let relativePath = path.relative(process.resourcesPath, filePath).replace(/\\/g, '/');
  41. if (isDev) relativePath = relativePath.replace('../../../..', '')
  42. memoryCache[relativePath] = decrypted;
  43. }
  44. // Recursively decrypt files in a directory and store their content in memory
  45. function decryptDirectory(directoryPath) {
  46. const files = fs.readdirSync(directoryPath);
  47. files.forEach(file => {
  48. const fullPath = path.join(directoryPath, file);
  49. if (fs.lstatSync(fullPath).isDirectory()) {
  50. decryptDirectory(fullPath);
  51. } else {
  52. decryptFile(fullPath);
  53. }
  54. });
  55. }
  56. function createWindow() {
  57. const directoryToDecrypt = isDev ? path.join(__dirname, 'build', 'static') : path.join(process.resourcesPath, 'app.asar', 'static');
  58. decryptDirectory(directoryToDecrypt);
  59. const { width, height } = screen.getPrimaryDisplay().workAreaSize;
  60. console.log(`Screen resolution: ${width}x${height}`);
  61. const WIDTH = parseInt(1600 * width / 1920)
  62. const HEIGHT = parseInt(900 * width / 1920)
  63. const win = new BrowserWindow({
  64. width: WIDTH,
  65. height: HEIGHT,
  66. icon: path.join(__dirname, 'favicon.ico'), // 设置窗口图标
  67. webPreferences: {
  68. preload: path.join(__dirname, 'src', 'preload.js'), // 确认预加载脚本路径正确
  69. nodeIntegration: false,
  70. contextIsolation: true,
  71. },
  72. });
  73. // Load the index.html from disk
  74. const index = isDev ? path.join(__dirname, 'build', 'index.html') : 'index.html';
  75. win.loadFile(index); // 确保路径正确
  76. // 打开调试工具
  77. if (isDev) win.webContents.openDevTools();
  78. // 创建菜单模板,只包含一个刷新按钮
  79. const menuTemplate = [
  80. {
  81. label: 'View',
  82. submenu: [
  83. {
  84. label: 'Reload',
  85. accelerator: 'CmdOrCtrl+R',
  86. click: () => {
  87. win.reload();
  88. },
  89. },
  90. ],
  91. },
  92. ];
  93. // 创建菜单
  94. const menu = Menu.buildFromTemplate(menuTemplate);
  95. // 设置应用程序的菜单
  96. Menu.setApplicationMenu(menu);
  97. console.log(Object.keys(memoryCache))
  98. }
  99. let memoryDbData = []
  100. let memoryDbPath = undefined
  101. app.whenReady().then(() => {
  102. ipcMain.handle('get-login-info-data', () => {
  103. return readData(loginFilePath);
  104. });
  105. ipcMain.handle('set-login-info-data', (event, newData) => {
  106. writeData(loginFilePath, newData);
  107. });
  108. ipcMain.handle('get-symbol-data', () => {
  109. return readData(symbolFilePath);
  110. });
  111. ipcMain.handle('set-symbol-data', (event, newData) => {
  112. writeData(symbolFilePath, newData);
  113. });
  114. ipcMain.handle('get-is-persistent-data', () => {
  115. return readData(persistentFilePath);
  116. });
  117. ipcMain.handle('set-is-persistent-data', (event, newData) => {
  118. writeData(persistentFilePath, newData);
  119. });
  120. ipcMain.handle('get-is-merge-data', () => {
  121. return readData(mergeFilePath);
  122. });
  123. ipcMain.handle('set-is-merge-data', (event, newData) => {
  124. writeData(mergeFilePath, newData);
  125. });
  126. ipcMain.handle('set-db-data', (event, dataList, symbol) => {
  127. const finalPath = path.join(dbBasePath, `${symbol}.json`)
  128. writeData(finalPath, dataList)
  129. console.log(`Local db is set. ${finalPath}`)
  130. })
  131. ipcMain.handle('get-db-data', (event, symbol) => {
  132. const finalPath = path.join(dbBasePath, `${symbol}.json`)
  133. const rst = readData(finalPath)
  134. if (JSON.stringify(rst) === '{}') {
  135. console.log(`No local db is found:${finalPath}`)
  136. return []
  137. } else {
  138. console.log(`Local db is found:${finalPath}, length: ${rst.length}`)
  139. return rst
  140. }
  141. })
  142. ipcMain.handle('flush-memory-db-data', (event, data, symbol) => {
  143. memoryDbData = data
  144. if (!memoryDbPath) memoryDbPath = path.join(dbBasePath, `${symbol}.json`)
  145. // console.log(`Memory db is flush。length: ${memoryDbData.length}, symbol: ${symbol}`)
  146. })
  147. });
  148. app.on('ready', () => {
  149. // Intercept file requests and serve from memory
  150. session.defaultSession.webRequest.onBeforeRequest((details, callback) => {
  151. const url = new URL(details.url);
  152. const filePath = path.normalize(decodeURIComponent(url.pathname));
  153. let relativePath = filePath.replace(path.normalize(process.resourcesPath), '').replace(/\\/g, '/').replace('//', '');
  154. if (isDev && relativePath.indexOf('react-stock-heatmap/example') !== -1) {
  155. relativePath = relativePath.split('react-stock-heatmap/example')[1]
  156. }
  157. // console.log(relativePath)
  158. if (memoryCache[relativePath]) {
  159. let sanitizedRelativePath = relativePath.replace('app.asar', 'app_asar'); // 避免路径中包含 app.asar
  160. // console.log(app.getPath('temp'), sanitizedRelativePath)
  161. const tempFilePath = path.join(app.getPath('temp'), sanitizedRelativePath);
  162. // console.log(`Temp File Path: ${tempFilePath}`);
  163. const tempDir = path.dirname(tempFilePath);
  164. // console.log(`Temp Directory Path: ${tempDir}`);
  165. // 确保临时目录路径存在
  166. if (!fs.existsSync(tempDir)) {
  167. // console.log(`Creating directory: ${tempDir}`);
  168. fs.mkdirSync(tempDir, { recursive: true });
  169. // console.log(`Directory created: ${tempDir}`);
  170. } else {
  171. // console.log(`Directory already exists: ${tempDir}`);
  172. }
  173. // 确保目录存在后再写入文件
  174. if (fs.existsSync(tempDir)) {
  175. // console.log(`Writing file: ${tempFilePath}`);
  176. fs.writeFileSync(tempFilePath, memoryCache[relativePath]);
  177. // console.log(`File written: ${tempFilePath}`);
  178. // console.log(`Intercepting request for: ${relativePath}, redirectURL: ${tempFilePath}`);
  179. callback({ cancel: false, redirectURL: tempFilePath });
  180. } else {
  181. // console.error(`Directory does not exist after creation attempt: ${tempDir}`);
  182. callback({ cancel: false });
  183. }
  184. } else {
  185. callback({ cancel: false });
  186. }
  187. });
  188. createWindow();
  189. });
  190. app.on('window-all-closed', () => {
  191. if (memoryDbData.length > 0 && memoryDbPath) {
  192. writeData(memoryDbPath, memoryDbData);
  193. console.log(`Exit saved db is ok. length: ${memoryDbData.length}, path:${memoryDbPath}`)
  194. }
  195. if (process.platform !== 'darwin') {
  196. app.quit();
  197. }
  198. });
  199. app.on('activate', () => {
  200. if (BrowserWindow.getAllWindows().length === 0) {
  201. createWindow();
  202. }
  203. });