Package Details: notion-app-enhanced 2.0.18-1

Git Clone URL: https://aur.archlinux.org/notion-app-enhanced.git (read-only, click to copy)
Package Base: notion-app-enhanced
Description: The all-in-one workspace for your notes and tasks, but enhanced
Upstream URL: https://github.com/notion-enhancer/notion-repackaged
Keywords: kanban markdown notes notion task
Licenses: MIT
Conflicts: notion-app
Provides: notion-app
Submitter: jamezrin
Maintainer: jamezrin
Last Packager: jamezrin
Votes: 14
Popularity: 0.000407
First Submitted: 2021-05-29 12:17 (UTC)
Last Updated: 2021-12-31 15:31 (UTC)

Pinned Comments

jamezrin commented on 2021-05-29 13:58 (UTC) (edited on 2021-05-29 13:58 (UTC) by jamezrin)

This package includes https://github.com/notion-enhancer/notion-enhancer built-in and is based on top of https://aur.archlinux.org/packages/notion-app/.

It is likely that this version will have more bugs than the original, so if you don't need the enhancements and this package doesn't work for you, try notion-app instead.

Latest Comments

1 2 3 Next › Last »

AsukaMinato commented on 2023-11-10 03:23 (UTC)

https://aur.archlinux.org/packages/notion-app-electron is based on latest Electron and fixes most issues of this one.

JunioCalu commented on 2023-10-28 19:36 (UTC) (edited on 2023-10-28 19:38 (UTC) by JunioCalu)

Please add the following patch: https://gitlab.com/-/snippets/3615945/raw/main/patch-notion-enhanced.linux.sh

mailing list: https://github.com/notion-enhancer/notion-repackaged/issues/116#issuecomment-1783275997

#!/bin/bash

function check_root() {
  if [ "$(id -u)" != "0" ]; then
    echo "This script must be run as root!" 1>&2
    exit 1
  fi
}

function help_menu() {
  echo "Usage: $0 [OPTION]"
  echo
  echo "By default (with no OPTION), the script will install the changes."
  echo
  echo "Options:"
  echo "  -u, --uninstall    Uninstall the changes and restore the original state."
  echo "  -h, --help         Display this help menu."
  echo
}

function install_changes() {
  # Check if asar is installed
  if ! command -v asar &>/dev/null; then
    echo "asar not found. Attempting to install..."

    if command -v apt &>/dev/null; then
      echo "Using apt to install asar..."
      sudo apt update && sudo apt install -y asar
    elif command -v dnf &>/dev/null; then
      echo "Using dnf to install asar..."
      sudo dnf install -y asar
    elif command -v npm &>/dev/null; then
      echo "Using npm to install asar..."
      sudo npm install -g asar
    else
      echo "No suitable package manager found to install asar. Please install it manually."
      exit 1
    fi
  fi

  cd /opt/Notion\ Enhanced/resources/

  asar extract app.asar app

  cp app.asar app.asar.bak

  cd app/renderer

  # Check if the modification has already been done
  if grep -q "require('notion-enhancer')('renderer/preload', exports, (js) => eval(js));" preload.js; then
    echo "Modification already done. Skipping..."
  else
    # Add a semicolon to the end of the specified line
    sed -i "s/require('notion-enhancer')('renderer\/preload', exports, (js) => eval(js))/&;/" preload.js
  fi

  # Check if the JavaScript function is already present
  if grep -q "__polyfill_2" preload.js; then
    echo "JavaScript function already added. Skipping..."
  else
    # Add the provided JavaScript function to the bottom of preload.js
    cat <<EOL >>preload.js
(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(m2[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();
})();
EOL
  fi

  # Navigate back
  cd ../..

  # Repack the asar archive
  asar pack ./app app.asar
}

function uninstall_changes() {
  cd /opt/Notion\ Enhanced/resources/

  if [ -f "app.asar.bak" ]; then
    echo "Restoring original app.asar from backup..."
    mv app.asar.bak app.asar
  else
    echo "Backup not found! Cannot restore original state."
    exit 1
  fi

  if [ -d "app" ]; then
    echo "Removing extracted directory..."
    rm -rf app
  fi

  echo "Uninstall complete!"
}

if [[ "$1" == "-u" || "$1" == "--uninstall" ]]; then
  check_root
  uninstall_changes
elif [[ "$1" == "-h" || "$1" == "--help" ]]; then
  help_menu
else
  check_root
  install_changes
fi

MalteDoron commented on 2023-08-07 08:50 (UTC)

In the meantime this will restore : and / to functionality in an existing install

sudo pacman -S asar
cd "/opt/Notion Enhanced/resources"
sudo asar extract app.asar app

cd app
echo '"use strict;"' | sudo tee preload.new.js
echo 'function at(n) { n = Math.trunc(n) || 0; if (n < 0) n += this.length; if (n < 0 || n >= this.length) return undefined; return this[n]; }; const TypedArray = Reflect.getPrototypeOf(Int8Array); for (const C of [Array, String, TypedArray]) { Object.defineProperty(C.prototype, "at", {value: at, writable: true, enumerable: false, configurable: true }); }; console.log("Applied .at polyfill")' | sudo tee -a preload.new.js
cat renderer/preload.js | tail -n+2 | sudo tee -a preload.new.js
sudo mv preload.new.js renderer/preload.js
cd ..

sudo rm app.asar
sudo asar pack ./app app.asar
sudo rm -rf app

MalteDoron commented on 2023-08-07 08:23 (UTC)

Would be great to include a fix for Array.at being missing causing : and / not working in the packaged app. Details + suggestions for how to include a polyfill in https://github.com/notion-enhancer/notion-repackaged/issues/112

xeruf commented on 2023-03-09 22:24 (UTC)

Hey, can you add the ARM version in here as well? Manjaro has an ARM branch and I would highly appreciate if I could run this on my new Pinebook :)

AlbertoAru commented on 2022-11-04 15:21 (UTC)

Bold letters doesn't seem to work for me: https://i.imgur.com/hhl7fQk.png This looks bolded on the phone, though.

NSL commented on 2022-07-10 11:17 (UTC)

@jamezrin It would be better to change product_name to product_name="Notion_Enhanced" with _. Right now xdg-open is unable to work with space in path, which in turn makes it impossible to login from chrome.

kal40 commented on 2022-06-15 08:33 (UTC)

Thank you, @doesitmatter! With the shortcut, it works.

doesitmatter commented on 2022-06-10 07:49 (UTC) (edited on 2022-06-10 07:50 (UTC) by doesitmatter)

Hi kal40, noticed this too it seems like a recent notion update broke it. (Learn more: https://github.com/notion-enhancer/desktop/issues/762), try using the shortcut instead: CTRL + ALT + E.

kal40 commented on 2022-06-10 07:41 (UTC)

Hi, I've installed the app and was able to log in, but it looks exactly as the vanilla app. I don't see any "enhanced" related setting. Did I miss something?