-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
340 additions
and
347 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,340 +0,0 @@ | ||
const shortcuts = { | ||
ArrowUp: () => scrollTo(0, 0), | ||
ArrowDown: () => scrollTo(0, document.body.scrollHeight), | ||
'[': () => 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) | ||
} | ||
|
||
function zoomCommon(zoomChange) { | ||
const currentZoom = window.localStorage.getItem('htmlZoom') || '100%' | ||
setZoom(zoomChange(currentZoom)) | ||
} | ||
|
||
function zoomIn() { | ||
zoomCommon((currentZoom) => `${Math.min(parseInt(currentZoom) + 10, 200)}%`) | ||
} | ||
|
||
function zoomOut() { | ||
zoomCommon((currentZoom) => `${Math.max(parseInt(currentZoom) - 10, 30)}%`) | ||
} | ||
|
||
function handleShortcut(event) { | ||
if (shortcuts[event.key]) { | ||
event.preventDefault() | ||
shortcuts[event.key]() | ||
} | ||
} | ||
|
||
// Judgment of file download. | ||
function isDownloadLink(url) { | ||
const fileExtensions = [ | ||
'3gp', | ||
'7z', | ||
'ai', | ||
'apk', | ||
'avi', | ||
'bmp', | ||
'csv', | ||
'dmg', | ||
'doc', | ||
'docx', | ||
'fla', | ||
'flv', | ||
'gif', | ||
'gz', | ||
'gzip', | ||
'ico', | ||
'iso', | ||
'indd', | ||
'jar', | ||
'jpeg', | ||
'jpg', | ||
'm3u8', | ||
'mov', | ||
'mp3', | ||
'mp4', | ||
'mpa', | ||
'mpg', | ||
'mpeg', | ||
'msi', | ||
'odt', | ||
'ogg', | ||
'ogv', | ||
'pdf', | ||
'png', | ||
'ppt', | ||
'pptx', | ||
'psd', | ||
'rar', | ||
'raw', | ||
'rss', | ||
'svg', | ||
'swf', | ||
'tar', | ||
'tif', | ||
'tiff', | ||
'ts', | ||
'txt', | ||
'wav', | ||
'webm', | ||
'webp', | ||
'wma', | ||
'wmv', | ||
'xls', | ||
'xlsx', | ||
'xml', | ||
'zip', | ||
] | ||
const downloadLinkPattern = new RegExp( | ||
`\\.(${fileExtensions.join('|')})$`, | ||
'i' | ||
) | ||
return downloadLinkPattern.test(url) | ||
} | ||
|
||
// No need to go to the download link. | ||
function externalDownLoadLink() { | ||
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 tauri = window.__TAURI__ | ||
const appWindow = tauri.window.appWindow | ||
const invoke = tauri.tauri.invoke | ||
|
||
const topDom = document.createElement('div') | ||
topDom.id = 'pack-top-dom' | ||
document.body.appendChild(topDom) | ||
const domEl = document.getElementById('pack-top-dom') | ||
|
||
domEl.addEventListener('touchstart', () => { | ||
appWindow.startDragging().then() | ||
}) | ||
|
||
domEl.addEventListener('mousedown', (e) => { | ||
e.preventDefault() | ||
if (e.buttons === 1 && e.detail !== 2) { | ||
appWindow.startDragging().then() | ||
} | ||
}) | ||
|
||
domEl.addEventListener('dblclick', () => { | ||
appWindow.isFullscreen().then((fullscreen) => { | ||
appWindow.setFullscreen(!fullscreen).then() | ||
}) | ||
}) | ||
|
||
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) | ||
} | ||
}) | ||
|
||
// Collect blob urls to blob by overriding window.URL.createObjectURL | ||
function collectUrlToBlobs() { | ||
const backupCreateObjectURL = window.URL.createObjectURL | ||
window.blobToUrlCaches = new Map() | ||
window.URL.createObjectURL = (blob) => { | ||
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) | ||
const reader = new FileReader() | ||
|
||
reader.readAsArrayBuffer(blob) | ||
reader.onload = () => { | ||
resolve(Array.from(new Uint8Array(reader.result))) | ||
} | ||
}) | ||
} | ||
|
||
function downloadFromDataUri(dataURI, filename) { | ||
const byteString = atob(dataURI.split(',')[1]) | ||
// write the bytes of the string to an ArrayBuffer | ||
const bufferArray = new ArrayBuffer(byteString.length) | ||
|
||
// create a view into the buffer | ||
const binary = new Uint8Array(bufferArray) | ||
|
||
// set the bytes of the buffer to the correct values | ||
for (let i = 0; i < byteString.length; i++) { | ||
binary[i] = byteString.charCodeAt(i) | ||
} | ||
|
||
// write the ArrayBuffer to a binary, and you're done | ||
invoke('download_file_by_binary', { | ||
params: { | ||
filename, | ||
binary: Array.from(binary), | ||
}, | ||
}) | ||
} | ||
|
||
function downloadFromBlobUrl(blobUrl, filename) { | ||
convertBlobUrlToBinary(blobUrl).then((binary) => { | ||
invoke('download_file_by_binary', { | ||
params: { | ||
filename, | ||
binary, | ||
}, | ||
}) | ||
}) | ||
} | ||
|
||
// detect blob download by createElement("a") | ||
function detectDownloadByCreateAnchor() { | ||
const createEle = document.createElement | ||
document.createElement = (el) => { | ||
if (el !== 'a') return createEle.call(document, el) | ||
const anchorEle = createEle.call(document, el) | ||
|
||
// use addEventListener to avoid overriding the original click event. | ||
anchorEle.addEventListener( | ||
'click', | ||
(e) => { | ||
console.log('anchorEle.addEventListener') | ||
const url = anchorEle.href | ||
const filename = | ||
anchorEle.download || getFilenameFromUrl(url) | ||
if (window.blobToUrlCaches.has(url)) { | ||
downloadFromBlobUrl(url, filename) | ||
// case: download from dataURL -> convert dataURL -> | ||
} else if (url.startsWith('data:')) { | ||
downloadFromDataUri(url, filename) | ||
} else if ( | ||
isDownloadLink(url) || | ||
anchorEle.hostname !== window.location.host | ||
) { | ||
handleExternalLink(e, url) | ||
} | ||
}, | ||
true | ||
) | ||
|
||
return anchorEle | ||
} | ||
} | ||
|
||
const isExternalLink = (link) => window.location.host !== link.host | ||
// process special download protocol['data:','blob:'] | ||
const isSpecialDownload = (url) => | ||
['blob', 'data'].some((protocol) => url.startsWith(protocol)) | ||
|
||
const isDownloadRequired = (url, anchorElement, e) => | ||
anchorElement.download || e.metaKey || e.ctrlKey || isDownloadLink(url) | ||
|
||
const handleExternalLink = (e, url) => { | ||
e.preventDefault() | ||
tauri.shell.open(url) | ||
} | ||
|
||
const handleDownloadLink = (e, url, filename) => { | ||
e.preventDefault() | ||
invoke('download_file', { params: { url, filename } }) | ||
} | ||
|
||
collectUrlToBlobs() | ||
detectDownloadByCreateAnchor() | ||
|
||
// 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) | ||
} | ||
|
||
// Fix Chinese input method "Enter" on Safari | ||
document.addEventListener( | ||
'keydown', | ||
(e) => { | ||
if (e.keyCode === 229) e.stopPropagation() | ||
}, | ||
true | ||
) | ||
}) | ||
|
||
function setDefaultZoom() { | ||
const htmlZoom = window.localStorage.getItem('htmlZoom') | ||
if (htmlZoom) { | ||
setZoom(htmlZoom) | ||
} | ||
} | ||
|
||
function getFilenameFromUrl(url) { | ||
const urlPath = new URL(url).pathname | ||
return urlPath.substring(urlPath.lastIndexOf('/') + 1) | ||
} | ||
|
||
// click a link to blank | ||
const detectAnchorElementClick = (e) => { | ||
const anchorElement = e.target.closest('a') | ||
if (anchorElement && anchorElement.href) { | ||
anchorElement.target = '_self' | ||
const hrefUrl = new URL(anchorElement.href) | ||
const absoluteUrl = hrefUrl.href | ||
let filename = anchorElement.download || getFilenameFromUrl(absoluteUrl) | ||
|
||
// Handling external link redirection. | ||
if ( | ||
isExternalLink(absoluteUrl) && | ||
(['_blank', '_new'].includes(anchorElement.target) || | ||
externalTargetLink()) | ||
) { | ||
handleExternalLink(e, absoluteUrl) | ||
return | ||
} | ||
|
||
// Process download links for Rust to handle. | ||
if ( | ||
isDownloadRequired(absoluteUrl, anchorElement, e) && | ||
!externalDownLoadLink() && | ||
!isSpecialDownload(absoluteUrl) | ||
) { | ||
handleDownloadLink(e, absoluteUrl, filename) | ||
} | ||
} | ||
} | ||
|
||
// Prevent some special websites from executing in advance, before the click event is triggered. | ||
document.addEventListener('click', detectAnchorElementClick, true) | ||
Oops, something went wrong.