From 7b80cc7eb2d762576d4f9db50addd3f44afd2221 Mon Sep 17 00:00:00 2001 From: L1Z3 <10276179+L1Z3@users.noreply.github.com> Date: Wed, 17 Jul 2024 15:37:59 -0400 Subject: [PATCH] notion-app-enhanced: fix infinite loading fixes upstream issues that cause the app to be unable to load, see https://github.com/notion-enhancer/notion-enhancer/issues/812 https://github.com/notion-enhancer/notion-repackaged/issues/116 --- .../office/notion-app-enhanced/default.nix | 21 +- .../notion-infinite-load-fix.patch | 265 ++++++++++++++++++ 2 files changed, 282 insertions(+), 4 deletions(-) create mode 100644 pkgs/applications/office/notion-app-enhanced/notion-infinite-load-fix.patch diff --git a/pkgs/applications/office/notion-app-enhanced/default.nix b/pkgs/applications/office/notion-app-enhanced/default.nix index 59c36ab17a876..fa52cf9b550a5 100644 --- a/pkgs/applications/office/notion-app-enhanced/default.nix +++ b/pkgs/applications/office/notion-app-enhanced/default.nix @@ -1,4 +1,4 @@ -{ appimageTools, lib, fetchurl }: +{ appimageTools, lib, fetchurl, asar, dos2unix }: let pname = "notion-app-enhanced"; version = "2.0.18-1"; @@ -8,9 +8,22 @@ let sha256 = "sha256-SqeMnoMzxxaViJ3NPccj3kyMc1xvXWULM6hQIDZySWY="; }; - appimageContents = appimageTools.extract { inherit pname version src; }; -in appimageTools.wrapType2 { - inherit pname version src; + appimageContents = appimageTools.extract { + inherit pname version src; + postExtract = '' + # fix https://github.com/notion-enhancer/notion-enhancer/issues/812 + ${asar}/bin/asar extract $out/resources/app.asar app + ${dos2unix}/bin/dos2unix app/renderer/preload.js + patch app/renderer/preload.js ${./notion-infinite-load-fix.patch} + ${dos2unix}/bin/unix2dos app/renderer/preload.js + ${asar}/bin/asar pack app $out/resources/app.asar + ''; + }; + # wrapAppImage instead of wrapType2 to avoid re-extracting the AppImage +in appimageTools.wrapAppImage { + inherit pname version; + + src = appimageContents; extraInstallCommands = '' install -m 444 -D ${appimageContents}/${pname}.desktop -t $out/share/applications diff --git a/pkgs/applications/office/notion-app-enhanced/notion-infinite-load-fix.patch b/pkgs/applications/office/notion-app-enhanced/notion-infinite-load-fix.patch new file mode 100644 index 0000000000000..d9bf65376eaa1 --- /dev/null +++ b/pkgs/applications/office/notion-app-enhanced/notion-infinite-load-fix.patch @@ -0,0 +1,265 @@ +--- app/renderer/preload.js ++++ app/renderer/preload.js +@@ -1,4 +1,262 @@ + "use strict"; ++(function __polyfill_2() { ++ function getClientHints(navigator) { ++ let { userAgent } = navigator; ++ let mobile, platform = '', platformVersion = '', architecture = '', bitness = '', model = '', uaFullVersion = '', fullVersionList = []; ++ let platformInfo = userAgent; ++ let found = false; ++ let versionInfo = userAgent.replace(/\(([^)]+)\)?/g, ($0, $1) => { ++ if (!found) { ++ platformInfo = $1; ++ found = true; ++ } ++ return ''; ++ }); ++ let items = versionInfo.match(/(\S+)\/(\S+)/g); ++ let webview = false; ++ // detect mobile ++ mobile = userAgent.indexOf('Mobile') !== -1; ++ let m; ++ let m2; ++ // detect platform ++ if ((m = /Windows NT (\d+(\.\d+)*)/.exec(platformInfo)) !== null) { ++ platform = 'Windows'; ++ // see https://docs.microsoft.com/en-us/microsoft-edge/web-platform/how-to-detect-win11 ++ let nt2win = { ++ '6.1': '0.1', // win-7 ++ '6.2': '0.2', // win-8 ++ '6.3': '0.3', // win-8.1 ++ '10.0': '10.0', // win-10 ++ '11.0': '13.0', // win-11 ++ }; ++ let ver = nt2win[m[1]]; ++ if (ver) ++ platformVersion = padVersion(ver, 3); ++ if ((m2 = /\b(WOW64|Win64|x64)\b/.exec(platformInfo)) !== null) { ++ architecture = 'x86'; ++ bitness = '64'; ++ } ++ } else if ((m = /Android (\d+(\.\d+)*)/.exec(platformInfo)) !== null) { ++ platform = 'Android'; ++ platformVersion = padVersion(m[1]); ++ if ((m2 = /Linux (\w+)/.exec(navigator.platform)) !== null) { ++ if (m2[1]) { ++ m2 = parseArch(m2[1]); ++ architecture = m2[0]; ++ bitness = m2[1]; ++ } ++ } ++ } else if ((m = /(iPhone|iPod touch); CPU iPhone OS (\d+(_\d+)*)/.exec(platformInfo)) !== null) { ++ // see special notes at https://www.whatismybrowser.com/guides/the-latest-user-agent/safari ++ platform = 'iOS'; ++ platformVersion = padVersion(m[2].replace(/_/g, '.')); ++ } else if ((m = /(iPad); CPU OS (\d+(_\d+)*)/.exec(platformInfo)) !== null) { ++ platform = 'iOS'; ++ platformVersion = padVersion(m[2].replace(/_/g, '.')); ++ } else if ((m = /Macintosh; (Intel|\w+) Mac OS X (\d+(_\d+)*)/.exec(platformInfo)) !== null) { ++ platform = 'macOS'; ++ platformVersion = padVersion(m[2].replace(/_/g, '.')); ++ } else if ((m = /Linux/.exec(platformInfo)) !== null) { ++ platform = 'Linux'; ++ platformVersion = ''; ++ // TODO ++ } else if ((m = /CrOS (\w+) (\d+(\.\d+)*)/.exec(platformInfo)) !== null) { ++ platform = 'Chrome OS'; ++ platformVersion = padVersion(m[2]); ++ m2 = parseArch(m[1]); ++ architecture = m2[0]; ++ bitness = m2[1]; ++ } ++ if (!platform) { ++ platform = 'Unknown'; ++ } ++ // detect fullVersionList / brands ++ let notABrand = { brand: ' Not;A Brand', version: '99.0.0.0' }; ++ if ((m = /Chrome\/(\d+(\.\d+)*)/.exec(versionInfo)) !== null && navigator.vendor === 'Google Inc.') { ++ fullVersionList.push({ brand: 'Chromium', version: padVersion(m[1], 4) }); ++ if ((m2 = /(Edge?)\/(\d+(\.\d+)*)/.exec(versionInfo)) !== null) { ++ let identBrandMap = { ++ 'Edge': 'Microsoft Edge', ++ 'Edg': 'Microsoft Edge', ++ }; ++ let brand = identBrandMap[m[1]]; ++ fullVersionList.push({ brand: brand, version: padVersion(m2[2], 4) }); ++ } else { ++ fullVersionList.push({ brand: 'Google Chrome', version: padVersion(m[1], 4) }); ++ } ++ if (/\bwv\b/.exec(platformInfo)) { ++ webview = true; ++ } ++ } else if ((m = /AppleWebKit\/(\d+(\.\d+)*)/.exec(versionInfo)) !== null && navigator.vendor === 'Apple Computer, Inc.') { ++ fullVersionList.push({ brand: 'WebKit', version: padVersion(m[1]) }); ++ if (platform === 'iOS' && (m2 = /(CriOS|EdgiOS|FxiOS|Version)\/(\d+(\.\d+)*)/.exec(versionInfo)) != null) { ++ let identBrandMap = { // no ++ 'CriOS': 'Google Chrome', ++ 'EdgiOS': 'Microsoft Edge', ++ 'FxiOS': 'Mozilla Firefox', ++ 'Version': 'Apple Safari', ++ }; ++ let brand = identBrandMap[m2[1]]; ++ fullVersionList.push({ brand, version: padVersion(m2[2]) }); ++ if (items.findIndex((s) => s.startsWith('Safari/')) === -1) { ++ webview = true; ++ } ++ } ++ } else if ((m = /Firefox\/(\d+(\.\d+)*)/.exec(versionInfo)) !== null) { ++ fullVersionList.push({ brand: 'Firefox', version: padVersion(m[1]) }); ++ } else if ((m = /(MSIE |rv:)(\d+\.\d+)/.exec(platformInfo)) !== null) { ++ fullVersionList.push({ brand: 'Internet Explorer', version: padVersion(m[2]) }); ++ } else { ++ fullVersionList.push(notABrand); ++ } ++ uaFullVersion = fullVersionList.length > 0 ? fullVersionList[fullVersionList.length - 1] : ''; ++ let brands = fullVersionList.map((b) => { ++ let pos = b.version.indexOf('.'); ++ let version = pos === -1 ? b.version : b.version.slice(0, pos); ++ return { brand: b.brand, version }; ++ }); ++ // TODO detect architecture, bitness and model ++ return { ++ mobile, ++ platform, ++ brands, ++ platformVersion, ++ architecture, ++ bitness, ++ model, ++ uaFullVersion, ++ fullVersionList, ++ webview ++ }; ++ } ++ ++ function parseArch(arch) { ++ switch (arch) { ++ case 'x86_64': ++ case 'x64': ++ return ['x86', '64']; ++ case 'x86_32': ++ case 'x86': ++ return ['x86', '']; ++ case 'armv6l': ++ case 'armv7l': ++ case 'armv8l': ++ return [arch, '']; ++ case 'aarch64': ++ return ['arm', '64']; ++ default: ++ return ['', '']; ++ } ++ } ++ function padVersion(ver, minSegs = 3) { ++ let parts = ver.split('.'); ++ let len = parts.length; ++ if (len < minSegs) { ++ for (let i = 0, lenToPad = minSegs - len; i < lenToPad; i += 1) { ++ parts.push('0'); ++ } ++ return parts.join('.'); ++ } ++ return ver; ++ } ++ ++ class NavigatorUAData { ++ constructor() { ++ this._ch = getClientHints(navigator); ++ Object.defineProperties(this, { ++ _ch: { enumerable: false }, ++ }); ++ } ++ get mobile() { ++ return this._ch.mobile; ++ } ++ get platform() { ++ return this._ch.platform; ++ } ++ get brands() { ++ return this._ch.brands; ++ } ++ getHighEntropyValues(hints) { ++ return new Promise((resolve, reject) => { ++ if (!Array.isArray(hints)) { ++ throw new TypeError('argument hints is not an array'); ++ } ++ let hintSet = new Set(hints); ++ let data = this._ch; ++ let obj = { ++ mobile: data.mobile, ++ platform: data.platform, ++ brands: data.brands, ++ }; ++ if (hintSet.has('architecture')) ++ obj.architecture = data.architecture; ++ if (hintSet.has('bitness')) ++ obj.bitness = data.bitness; ++ if (hintSet.has('model')) ++ obj.model = data.model; ++ if (hintSet.has('platformVersion')) ++ obj.platformVersion = data.platformVersion; ++ if (hintSet.has('uaFullVersion')) ++ obj.uaFullVersion = data.uaFullVersion; ++ if (hintSet.has('fullVersionList')) ++ obj.fullVersionList = data.fullVersionList; ++ resolve(obj); ++ }); ++ } ++ toJSON() { ++ let data = this._ch; ++ return { ++ mobile: data.mobile, ++ brands: data.brands, ++ }; ++ } ++ } ++ Object.defineProperty(NavigatorUAData.prototype, Symbol.toStringTag, { ++ enumerable: false, ++ configurable: true, ++ writable: false, ++ value: 'NavigatorUAData' ++ }); ++ ++ function ponyfill() { ++ return new NavigatorUAData(navigator); ++ } ++ function polyfill() { ++ console.log("Try polyfill . . ."); ++ ++ // When Notion , no need https? ++ const ____use_https = false; ++ ++ if ( ++ (!____use_https || location.protocol === 'https:') ++ && !navigator.userAgentData ++ ) { ++ console.log("Here,begin userAgentData polyfill . . .") ++ let userAgentData = new NavigatorUAData(navigator); ++ Object.defineProperty(Navigator.prototype, 'userAgentData', { ++ enumerable: true, ++ configurable: true, ++ get: function getUseAgentData() { ++ return userAgentData; ++ } ++ }); ++ Object.defineProperty(window, 'NavigatorUAData', { ++ enumerable: false, ++ configurable: true, ++ writable: true, ++ value: NavigatorUAData ++ }); ++ return true; ++ } ++ return false; ++ } ++ ++ ++ // Simple Apply this code. ++ ponyfill(); ++ polyfill(); ++})(); ++ + var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });