view-preload.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import { ipcRenderer, webFrame } from 'electron';
  2. import AutoComplete from './models/auto-complete';
  3. import { getTheme } from '~/utils/themes';
  4. import { ERROR_PROTOCOL, WEBUI_BASE_URL } from '~/constants/files';
  5. import { injectChromeWebstoreInstallButton } from './chrome-webstore';
  6. const tabId = ipcRenderer.sendSync('get-webcontents-id');
  7. export const windowId: number = ipcRenderer.sendSync('get-window-id');
  8. const goBack = () => {
  9. ipcRenderer.invoke(`web-contents-call`, {
  10. webContentsId: tabId,
  11. method: 'goBack',
  12. });
  13. };
  14. const goForward = () => {
  15. ipcRenderer.invoke(`web-contents-call`, {
  16. webContentsId: tabId,
  17. method: 'goForward',
  18. });
  19. };
  20. window.addEventListener('mouseup', (e) => {
  21. if (e.button === 3) {
  22. e.preventDefault();
  23. goBack();
  24. } else if (e.button === 4) {
  25. e.preventDefault();
  26. goForward();
  27. }
  28. });
  29. let beginningScrollLeft: number = null;
  30. let beginningScrollRight: number = null;
  31. let horizontalMouseMove = 0;
  32. let verticalMouseMove = 0;
  33. const resetCounters = () => {
  34. beginningScrollLeft = null;
  35. beginningScrollRight = null;
  36. horizontalMouseMove = 0;
  37. verticalMouseMove = 0;
  38. };
  39. function getScrollStartPoint(x: number, y: number) {
  40. let left = 0;
  41. let right = 0;
  42. let n = document.elementFromPoint(x, y);
  43. while (n) {
  44. if (n.scrollLeft !== undefined) {
  45. left = Math.max(left, n.scrollLeft);
  46. right = Math.max(right, n.scrollWidth - n.clientWidth - n.scrollLeft);
  47. }
  48. n = n.parentElement;
  49. }
  50. return { left, right };
  51. }
  52. document.addEventListener('wheel', (e) => {
  53. verticalMouseMove += e.deltaY;
  54. horizontalMouseMove += e.deltaX;
  55. if (beginningScrollLeft === null || beginningScrollRight === null) {
  56. const result = getScrollStartPoint(e.deltaX, e.deltaY);
  57. beginningScrollLeft = result.left;
  58. beginningScrollRight = result.right;
  59. }
  60. });
  61. ipcRenderer.on('scroll-touch-end', () => {
  62. if (
  63. horizontalMouseMove - beginningScrollRight > 150 &&
  64. Math.abs(horizontalMouseMove / verticalMouseMove) > 2.5
  65. ) {
  66. if (beginningScrollRight < 10) {
  67. goForward();
  68. }
  69. }
  70. if (
  71. horizontalMouseMove + beginningScrollLeft < -150 &&
  72. Math.abs(horizontalMouseMove / verticalMouseMove) > 2.5
  73. ) {
  74. if (beginningScrollLeft < 10) {
  75. goBack();
  76. }
  77. }
  78. resetCounters();
  79. });
  80. if (process.env.ENABLE_AUTOFILL) {
  81. window.addEventListener('load', AutoComplete.loadForms);
  82. window.addEventListener('mousedown', AutoComplete.onWindowMouseDown);
  83. }
  84. const postMsg = (data: any, res: any) => {
  85. window.postMessage(
  86. {
  87. id: data.id,
  88. result: res,
  89. type: 'result',
  90. },
  91. '*',
  92. );
  93. };
  94. const hostname = window.location.href.substr(WEBUI_BASE_URL.length);
  95. if (
  96. process.env.ENABLE_EXTENSIONS &&
  97. window.location.host === 'chrome.google.com'
  98. ) {
  99. injectChromeWebstoreInstallButton();
  100. }
  101. const settings = ipcRenderer.sendSync('get-settings-sync');
  102. if (
  103. window.location.href.startsWith(WEBUI_BASE_URL) ||
  104. window.location.protocol === `${ERROR_PROTOCOL}:`
  105. ) {
  106. (async function () {
  107. const w = await webFrame.executeJavaScript('window');
  108. w.settings = settings;
  109. w.require = (id: string) => {
  110. if (id === 'electron') {
  111. return { ipcRenderer };
  112. }
  113. return undefined;
  114. };
  115. if (window.location.pathname.startsWith('//network-error')) {
  116. w.theme = getTheme(w.settings.theme);
  117. w.errorURL = await ipcRenderer.invoke(`get-error-url-${tabId}`);
  118. } else if (hostname.startsWith('history')) {
  119. w.getHistory = async () => {
  120. return await ipcRenderer.invoke(`history-get`);
  121. };
  122. w.removeHistory = (ids: string[]) => {
  123. ipcRenderer.send(`history-remove`, ids);
  124. };
  125. } else if (hostname.startsWith('newtab')) {
  126. w.getTopSites = async (count: number) => {
  127. return await ipcRenderer.invoke(`topsites-get`, count);
  128. };
  129. }
  130. })();
  131. } else {
  132. (async function () {
  133. if (settings.doNotTrack) {
  134. const w = await webFrame.executeJavaScript('window');
  135. Object.defineProperty(w.navigator, 'doNotTrack', { value: 1 });
  136. }
  137. })();
  138. }
  139. if (window.location.href.startsWith(WEBUI_BASE_URL)) {
  140. window.addEventListener('DOMContentLoaded', () => {
  141. if (hostname.startsWith('settings')) document.title = '设置';
  142. else if (hostname.startsWith('history')) document.title = '历史记录';
  143. else if (hostname.startsWith('bookmarks')) document.title = '管理书签';
  144. else if (hostname.startsWith('extensions')) document.title = '扩展';
  145. else if (hostname.startsWith('newtab')) {
  146. document.title = '新建标签页';
  147. }
  148. });
  149. window.addEventListener('message', async ({ data }) => {
  150. if (data.type === 'storage') {
  151. const res = await ipcRenderer.invoke(`storage-${data.operation}`, {
  152. scope: data.scope,
  153. ...data.data,
  154. });
  155. postMsg(data, res);
  156. } else if (data.type === 'credentials-get-password') {
  157. const res = await ipcRenderer.invoke(
  158. 'credentials-get-password',
  159. data.data,
  160. );
  161. postMsg(data, res);
  162. } else if (data.type === 'save-settings') {
  163. ipcRenderer.send('save-settings', { settings: data.data });
  164. }
  165. });
  166. ipcRenderer.on('update-settings', async (e, data) => {
  167. const w = await webFrame.executeJavaScript('window');
  168. if (w.updateSettings) {
  169. w.updateSettings(data);
  170. }
  171. });
  172. ipcRenderer.on('credentials-insert', (e, data) => {
  173. window.postMessage(
  174. {
  175. type: 'credentials-insert',
  176. data,
  177. },
  178. '*',
  179. );
  180. });
  181. ipcRenderer.on('credentials-update', (e, data) => {
  182. window.postMessage(
  183. {
  184. type: 'credentials-update',
  185. data,
  186. },
  187. '*',
  188. );
  189. });
  190. ipcRenderer.on('credentials-remove', (e, data) => {
  191. window.postMessage(
  192. {
  193. type: 'credentials-remove',
  194. data,
  195. },
  196. '*',
  197. );
  198. });
  199. }