diff --git a/bin/builders/common.ts b/bin/builders/common.ts index 08d5428..594ab3d 100644 --- a/bin/builders/common.ts +++ b/bin/builders/common.ts @@ -1,5 +1,5 @@ import { PakeAppOptions } from '@/types.js'; -import prompts, { override } from 'prompts'; +import prompts from 'prompts'; import path from 'path'; import fs from 'fs/promises'; import fs2 from 'fs-extra'; @@ -7,7 +7,6 @@ import {TauriConfig} from 'tauri/src/types'; import { npmDirectory } from '@/utils/dir.js'; import logger from '@/options/logger.js'; -import URL from 'node:url'; type DangerousRemoteDomainIpAccess = { domain: string; @@ -38,7 +37,8 @@ export async function promptText(message: string, initial?: string) { } function setSecurityConfigWithUrl(tauriConfig: NextTauriConfig, url: string) { - const {hostname} = URL.parse(url); + const myURL = new URL(url); + const hostname = myURL.hostname; tauriConfig.tauri.security.dangerousRemoteDomainIpcAccess[0].domain = hostname; } diff --git a/package.json b/package.json index e6298ff..4a133bd 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,8 @@ "exports": "./dist/pake.js", "license": "MIT", "dependencies": { - "@tauri-apps/api": "^1.2.0", - "@tauri-apps/cli": "^1.2.3", + "@tauri-apps/api": "^1.3.0", + "@tauri-apps/cli": "^1.3.1", "axios": "^1.1.3", "chalk": "^5.1.2", "commander": "^9.4.1", diff --git a/src-tauri/src/app/invoke.rs b/src-tauri/src/app/invoke.rs index e199c11..4553d74 100644 --- a/src-tauri/src/app/invoke.rs +++ b/src-tauri/src/app/invoke.rs @@ -8,26 +8,6 @@ pub struct DownloadFileParams { filename: String, } -#[command] -pub fn drag_window(app: AppHandle) { - app.get_window("pake").unwrap().start_dragging().unwrap(); -} - -#[command] -pub fn fullscreen(app: AppHandle) { - let win = app.get_window("pake").unwrap(); - if win.is_fullscreen().unwrap() { - win.set_fullscreen(false).unwrap(); - } else { - win.set_fullscreen(true).unwrap(); - } -} - -#[command] -pub fn open_browser(app: AppHandle, url: String) { - api::shell::open(&app.shell_scope(), url, None).unwrap(); -} - #[command] pub async fn download_file(app: AppHandle, params: DownloadFileParams) -> Result<(), String> { let window: Window = app.get_window("pake").unwrap(); diff --git a/src-tauri/src/inject/event.js b/src-tauri/src/inject/event.js index 82aba8f..bb3e0f1 100644 --- a/src-tauri/src/inject/event.js +++ b/src-tauri/src/inject/event.js @@ -1,84 +1,83 @@ const shortcuts = { - ArrowUp: () => scrollTo(0, 0), - ArrowDown: () => scrollTo(0, document.body.scrollHeight), - // Don't use command + ArrowLeft or command + ArrowRight - // When editing text in page, it causes unintended page navigation. - // ArrowLeft: () => window.history.back(), - // ArrowRight: () => window.history.forward(), - '[': () => window.history.back(), - ']': () => window.history.forward(), - r: () => window.location.reload(), - '-': () => zoomOut(), - '=': () => zoomIn(), - '+': () => zoomIn(), - 0: () => setZoom('100%'), + ArrowUp: () => scrollTo(0, 0), + ArrowDown: () => scrollTo(0, document.body.scrollHeight), + // Don't use command + ArrowLeft or command + ArrowRight + // When editing text in page, it causes unintended page navigation. + // ArrowLeft: () => window.history.back(), + // ArrowRight: () => window.history.forward(), + '[': () => window.history.back(), + ']': () => window.history.forward(), + r: () => window.location.reload(), + '-': () => zoomOut(), + '=': () => zoomIn(), + '+': () => zoomIn(), + 0: () => setZoom('100%'), }; function setZoom(zoom) { - const html = document.getElementsByTagName('html')[0]; - html.style.zoom = zoom; - window.localStorage.setItem('htmlZoom', zoom); + const html = document.getElementsByTagName('html')[0]; + html.style.zoom = zoom; + window.localStorage.setItem('htmlZoom', zoom); } function zoomCommon(zoomChange) { - const currentZoom = window.localStorage.getItem('htmlZoom') || '100%'; - setZoom(zoomChange(currentZoom)); + const currentZoom = window.localStorage.getItem('htmlZoom') || '100%'; + setZoom(zoomChange(currentZoom)); } function zoomIn() { - zoomCommon((currentZoom) => `${Math.min(parseInt(currentZoom) + 10, 200)}%`); + zoomCommon((currentZoom) => `${Math.min(parseInt(currentZoom) + 10, 200)}%`); } function zoomOut() { - zoomCommon((currentZoom) => `${Math.max(parseInt(currentZoom) - 10, 30)}%`); + zoomCommon((currentZoom) => `${Math.max(parseInt(currentZoom) - 10, 30)}%`); } function handleShortcut(event) { - if (shortcuts[event.key]) { - event.preventDefault(); - shortcuts[event.key](); - } + if (shortcuts[event.key]) { + event.preventDefault(); + shortcuts[event.key](); + } } //这里参考 ChatGPT 的代码 const uid = () => window.crypto.getRandomValues(new Uint32Array(1))[0]; -function transformCallback(callback = () => { -}, once = false) { - const identifier = uid(); - const prop = `_${identifier}`; - Object.defineProperty(window, prop, { - value: (result) => { - if (once) { - Reflect.deleteProperty(window, prop); - } - return callback(result); - }, - writable: false, - configurable: true, - }); - return identifier; +function transformCallback(callback = () => {}, once = false) { + const identifier = uid(); + const prop = `_${identifier}`; + Object.defineProperty(window, prop, { + value: (result) => { + if (once) { + Reflect.deleteProperty(window, prop); + } + return callback(result); + }, + writable: false, + configurable: true, + }); + return identifier; } async function invoke(cmd, args) { - return new Promise((resolve, reject) => { - if (!window.__TAURI_POST_MESSAGE__) - reject('__TAURI_POST_MESSAGE__ does not exist~'); - const callback = transformCallback((e) => { - resolve(e); - Reflect.deleteProperty(window, `_${error}`); - }, true); - const error = transformCallback((e) => { - reject(e); - Reflect.deleteProperty(window, `_${callback}`); - }, true); - window.__TAURI_POST_MESSAGE__({ - cmd, - callback, - error, - ...args, - }); + return new Promise((resolve, reject) => { + if (!window.__TAURI_POST_MESSAGE__) + reject('__TAURI_POST_MESSAGE__ does not exist~'); + const callback = transformCallback((e) => { + resolve(e); + Reflect.deleteProperty(window, `_${error}`); + }, true); + const error = transformCallback((e) => { + reject(e); + Reflect.deleteProperty(window, `_${callback}`); + }, true); + window.__TAURI_POST_MESSAGE__({ + cmd, + callback, + error, + ...args, }); + }); } // Judgment of file download. @@ -95,145 +94,160 @@ function isDownloadLink(url) { // No need to go to the download link. function externalDownLoadLink() { - return ['quickref.me'].indexOf(location.hostname) > -1; + return ['quickref.me'].indexOf(location.hostname) > -1; +} + +// Directly jumping out without hostname address. +function externalTargetLink() { + return ['zbook.lol'].indexOf(location.hostname) > -1; } document.addEventListener('DOMContentLoaded', () => { - const topDom = document.createElement('div'); - topDom.id = 'pack-top-dom'; - document.body.appendChild(topDom); - const domEl = document.getElementById('pack-top-dom'); + const tauri = window.__TAURI__; + const appWindow = tauri.window.appWindow; - domEl.addEventListener('mousedown', (e) => { - e.preventDefault(); - if (e.buttons === 1 && e.detail !== 2) { - invoke('drag_window'); - } + const topDom = document.createElement('div'); + topDom.id = 'pack-top-dom'; + document.body.appendChild(topDom); + const domEl = document.getElementById('pack-top-dom'); + + domEl.addEventListener('mousedown', (e) => { + e.preventDefault(); + if (e.buttons === 1 && e.detail !== 2) { + appWindow.startDragging(); + } + }); + + domEl.addEventListener('touchstart', () => { + appWindow.startDragging(); + }); + + domEl.addEventListener('dblclick', () => { + appWindow.isFullscreen().then((fullscreen) => { + appWindow.setFullscreen(!fullscreen); }); + }); - domEl.addEventListener('touchstart', () => { - invoke('drag_window'); - }); + document.addEventListener('keyup', (event) => { + if (/windows|linux/i.test(navigator.userAgent) && event.ctrlKey) { + handleShortcut(event); + } + if (/macintosh|mac os x/i.test(navigator.userAgent) && event.metaKey) { + handleShortcut(event); + } + }); - domEl.addEventListener('dblclick', () => { - invoke('fullscreen'); - }); + const detectAnchorElementClick = (e) => { + const anchorElement = e.target.closest('a'); + console.log(">>>>>>>>>",anchorElement); + if (anchorElement && anchorElement.href) { + const target = anchorElement.target; + anchorElement.target = '_self'; + const hrefUrl = new URL(anchorElement.href); + const absoluteUrl = hrefUrl.href; - document.addEventListener('keyup', (event) => { - if (/windows|linux/i.test(navigator.userAgent) && event.ctrlKey) { - handleShortcut(event); - } - if (/macintosh|mac os x/i.test(navigator.userAgent) && event.metaKey) { - handleShortcut(event); - } - }); - - const detectAnchorElementClick = (e) => { - const anchorElement = e.target.closest('a'); - if (anchorElement && anchorElement.href) { - const target = anchorElement.target; - anchorElement.target = '_self'; - const hrefUrl = new URL(anchorElement.href); - const absoluteUrl = hrefUrl.href; - - // Convert blob url to binary file - if (absoluteUrl.includes('blob:')) { - convertBlobUrlToBinary(absoluteUrl).then(binary => { - const tauri = window.__TAURI__; - tauri.fs.writeBinaryFile(anchorElement.download, binary, { - dir: tauri.fs.BaseDirectory.Download, - }); - }) - return; - } - - // Handling external link redirection. - if ( - window.location.host !== hrefUrl.host && - (target === '_blank' || target === '_new') - ) { - e.preventDefault(); - invoke('open_browser', {url: absoluteUrl}); - return; - } - - let filename = anchorElement.download ? anchorElement.download : getFilenameFromUrl(absoluteUrl) - // Process download links for Rust to handle. - // If the download attribute is set, the download attribute is used as the file name. - if ((anchorElement.download || e.metaKey || e.ctrlKey || isDownloadLink(absoluteUrl)) - && !externalDownLoadLink() - ) { - e.preventDefault(); - invoke('download_file', { - params: { - url: absoluteUrl, - filename, - }, - }); - } + // Convert blob url to binary file + if (absoluteUrl.includes('blob:')) { + convertBlobUrlToBinary(absoluteUrl).then((binary) => { + tauri.fs.writeBinaryFile(anchorElement.download, binary, { + dir: tauri.fs.BaseDirectory.Download, + }); + }); + return; } + + // Handling external link redirection. + if ( + window.location.host !== hrefUrl.host && + (target === '_blank' || target === '_new' || externalTargetLink()) + ) { + e.preventDefault && e.preventDefault(); + tauri.shell.open(absoluteUrl); + return; + } + + let filename = anchorElement.download + ? anchorElement.download + : getFilenameFromUrl(absoluteUrl); + // Process download links for Rust to handle. + // If the download attribute is set, the download attribute is used as the file name. + if ( + (anchorElement.download || + e.metaKey || + e.ctrlKey || + isDownloadLink(absoluteUrl)) && + !externalDownLoadLink() + ) { + e.preventDefault(); + invoke('download_file', { + params: { + url: absoluteUrl, + filename, + }, + }); + } + } }; - // Prevent some special websites from executing in advance, before the click event is triggered. - document.addEventListener('mousedown', detectAnchorElementClick); + // Prevent some special websites from executing in advance, before the click event is triggered. + document.addEventListener('click', detectAnchorElementClick, true); - collectUrlToBlobs(); + collectUrlToBlobs(); - // Rewrite the window.open function. - const originalWindowOpen = window.open; - window.open = function (url, name, specs) { - // Apple login and google login - if (name === 'AppleAuthentication') { - //do nothing - } else if (specs.includes('height=') || specs.includes('width=')) { - location.href = url; - } else { - const baseUrl = window.location.origin + window.location.pathname; - const hrefUrl = new URL(url, baseUrl); - invoke('open_browser', {url: hrefUrl.href}); - } - // Call the original window.open function to maintain its normal functionality. - return originalWindowOpen.call(window, url, name, specs); - }; - - // Set the default zoom, There are problems with Loop without using try-catch. - try { - setDefaultZoom(); - } catch (e) { - console.log(e); + // Rewrite the window.open function. + const originalWindowOpen = window.open; + window.open = function (url, name, specs) { + // Apple login and google login + if (name === 'AppleAuthentication') { + //do nothing + } else if (specs.includes('height=') || specs.includes('width=')) { + location.href = url; + } else { + const baseUrl = window.location.origin + window.location.pathname; + const hrefUrl = new URL(url, baseUrl); + tauri.shell.open(hrefUrl.href); } + // Call the original window.open function to maintain its normal functionality. + return originalWindowOpen.call(window, url, name, specs); + }; + + // Set the default zoom, There are problems with Loop without using try-catch. + try { + setDefaultZoom(); + } catch (e) { + console.log(e); + } }); function setDefaultZoom() { - const htmlZoom = window.localStorage.getItem('htmlZoom'); - if (htmlZoom) { - setZoom(htmlZoom); - } + const htmlZoom = window.localStorage.getItem('htmlZoom'); + if (htmlZoom) { + setZoom(htmlZoom); + } } function getFilenameFromUrl(url) { - const urlPath = new URL(url).pathname; - const filename = urlPath.substring(urlPath.lastIndexOf('/') + 1); - return filename; + const urlPath = new URL(url).pathname; + const filename = urlPath.substring(urlPath.lastIndexOf('/') + 1); + return filename; } function removeUrlParameters(url) { - const parsedUrl = new URL(url); - parsedUrl.search = ''; - return parsedUrl.toString(); + const parsedUrl = new URL(url); + parsedUrl.search = ''; + return parsedUrl.toString(); } - // Toggle video playback when the window is hidden. function toggleVideoPlayback(pause) { - const videos = document.getElementsByTagName('video'); - for (const video of videos) { - if (pause) { - video.pause(); - } else { - video.play(); - } + const videos = document.getElementsByTagName('video'); + for (const video of videos) { + if (pause) { + video.pause(); + } else { + video.play(); } + } } // Collect blob urls to blob by overriding window.URL.createObjectURL @@ -244,10 +258,9 @@ function collectUrlToBlobs() { const url = backupCreateObjectURL.call(window.URL, blob); window.blobToUrlCaches.set(url, blob); return url; - } + }; } - function convertBlobUrlToBinary(blobUrl) { return new Promise((resolve) => { const blob = window.blobToUrlCaches.get(blobUrl); @@ -257,6 +270,5 @@ function convertBlobUrlToBinary(blobUrl) { reader.onload = () => { resolve(reader.result); }; - }) - + }); } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index ca5a401..e51ca4f 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -7,7 +7,7 @@ mod app; mod util; use app::{invoke, menu, window}; -use invoke::{download_file, drag_window, fullscreen, open_browser}; +use invoke::download_file; use menu::{get_menu, menu_event_handle}; use tauri_plugin_window_state::Builder as windowStatePlugin; use util::{get_data_dir, get_pake_config}; @@ -41,12 +41,7 @@ pub fn run_app() { tauri_app .plugin(windowStatePlugin::default().build()) - .invoke_handler(tauri::generate_handler![ - drag_window, - fullscreen, - open_browser, - download_file - ]) + .invoke_handler(tauri::generate_handler![download_file]) .setup(|app| { let _window = get_window(app, pake_config, data_dir); // Prevent initial shaking