From 7836e7c95de243c7d352af8a44a757c4b611855d Mon Sep 17 00:00:00 2001 From: TarasokUA Date: Sun, 23 Feb 2020 16:50:58 +0200 Subject: [PATCH] Add files via upload --- Notion Customization/Customization Patcher.py | 370 ++++++++++++++++++ Notion Customization/Customization Remover.py | 80 ++++ .../resources/custom_style.css | 135 +++++++ Notion Customization/resources/icon.ico | Bin 0 -> 112696 bytes Notion Customization/resources/main.user.js | 93 +++++ Notion Customization/resources/store.js | 30 ++ 6 files changed, 708 insertions(+) create mode 100644 Notion Customization/Customization Patcher.py create mode 100644 Notion Customization/Customization Remover.py create mode 100644 Notion Customization/resources/custom_style.css create mode 100644 Notion Customization/resources/icon.ico create mode 100644 Notion Customization/resources/main.user.js create mode 100644 Notion Customization/resources/store.js diff --git a/Notion Customization/Customization Patcher.py b/Notion Customization/Customization Patcher.py new file mode 100644 index 0000000..558bd35 --- /dev/null +++ b/Notion Customization/Customization Patcher.py @@ -0,0 +1,370 @@ +""" +# Step 1 +1.Locating notion app at ./%Username%/AppData/Local/Programs/Notion +2.Unpacking app.asar in new folder at./Notion/resources/app +3.Renaming file app.asar to app.asar.bak (because instead app won't use folder "app" to get all resources from it) +4.If app.asar already unpacked - it will try to locate folder "app" and skip to next step + +# Step 2 +1. Editing userscript file to replace "full_path_to_custom_style" with full path to ./custom_style.css +2. Adding userscript from main.user.js(should be in same folder with this .py file) to the ./app/renderer/preload.js +3. If there is already userscript - it will overwrite it. + +# Step 3 +1. Adding property "frame: false" to the place where application window is creating + +# Step 4 +1. Changes "window drag" area, to make window draggable + 1.1. You can change it by yourself, if you experiencing problems with dragging window or with clicking buttons on app topbar + Because this "draggable area" is creating on top of the other stuff, so if it will have button behind it - it won't be clickable. + You should change top,left,right properties. Now it's 2px on top, 390px on left and 420px on right; +""" +import os +from time import sleep +from shutil import copyfile +import re + +try: + sleepTime = 0.5 + sleep(sleepTime) + print("========= START OF LOG =========") + sleep(sleepTime) + LOCALAPPDATA = os.getenv('LOCALAPPDATA') + notionResourcesPath = LOCALAPPDATA + '/Programs/Notion/resources' + windowToggleHotkey = "'ctrl+shift+a'" + + # Step 1 + print("Step 1") + sleep(sleepTime) + if os.path.isfile(notionResourcesPath + '/app.asar'): + sleep(sleepTime) + print(" Unpacking app.asar") + os.system("asar extract %LOCALAPPDATA%/Programs/Notion/resources/app.asar %LOCALAPPDATA%/Programs/Notion/resources/app") + sleep(sleepTime) + renameSource = notionResourcesPath + '/app.asar' + renameDestination = renameSource + '.bak' + os.rename(renameSource, renameDestination) + print(" Renaming asar.app to asar.app.bak") + sleep(sleepTime) + else: + sleep(sleepTime) + print(" There is no file at Notion/resources/app.asar") + sleep(sleepTime) + print(" Trying to locate unpacked app.asar") + sleep(sleepTime) + if os.path.exists(notionResourcesPath + '/app'): + print(" app.asar already unpacked - Moving to the next step") + sleep(sleepTime) + else: + print(" Nothing found at Notion/resources/app. Exiting. ") + input("Press Enter to exit...") + exit() + print("-Done-\n") + sleep(sleepTime) + + print("Step 2") + sleep(sleepTime) + # Step 2 + if os.path.isfile(notionResourcesPath + '/app/renderer/preload.js'): + print(" Adding userscript to Notion/resources/app/renderer/preload.js") + sleep(sleepTime) + + preload = open(notionResourcesPath + '/app/renderer/preload.js', 'rt') + preloadStr = preload.read() + preload.close() + if 'function userscript()' in preloadStr: + print(" Userscript already added. Replacing it") + sleep(sleepTime) + userscript_line = 0 + with open(notionResourcesPath + '/app/renderer/preload.js') as myFile: + for num, line in enumerate(myFile, 1): + if "function userscript()" in line: + userscript_line = num-1 + + preload = open(notionResourcesPath + '/app/renderer/preload.js', 'rt') + preloadLines = preload.readlines() + preload.close() + + with open(notionResourcesPath + '/app/renderer/preload.js', 'w') as fin: + for lineno, line in enumerate(preloadLines, 1): + if lineno < userscript_line: + fin.write(line) + + print(" Creating link to ./resources/custom_style.css") + sleep(sleepTime) + preload = open(notionResourcesPath + '/app/renderer/preload.js', 'a') + userscript = open('./resources/main.user.js') + scriptPath = os.getcwd() + scriptPath = scriptPath.replace('\\', '/') + userscriptStr = userscript.read() + userscriptStr = userscriptStr.replace('full_path_to_custom_style',scriptPath + '/resources/custom_style.css') + preload.write('\n' + userscriptStr) + preload.close() + else: + print(" There is no files at Notion/resources/app/renderer/preload.js or/and ./resources/main.user.js - Nothing was done") + sleep(sleepTime) + print("-Done-\n") + sleep(sleepTime) + + print("Step 3") + sleep(sleepTime) + # Step 3 + if os.path.isfile(notionResourcesPath + '/app/main/createWindow.js'): + print(" Making window frameless at Notion/resources/app/main/createWindow.js") + sleep(sleepTime) + + createWindow = open(notionResourcesPath + '/app/main/createWindow.js', 'rt') + createWindowText = createWindow.read() + createWindowText = createWindowText.replace('{ show: false', '{ frame: false, show: false') + + print(" Adding ""Run Hidden"" functionality at Notion/resources/app/main/createWindow.js") + sleep(sleepTime) + createWindowText = createWindowText.replace('window.show();', """ + const path = require("path"); + const Store = require(path.join(__dirname,'../','store.js')); + const store = new Store({ + configName: "user-preferences", + defaults: { + runHidden: false, + alwaysMaximized: false + }}); + + var RunHiddenCheckboxState = store.get("runHidden"); + var AlwaysMaximizedCheckboxState = store.get("alwaysMaximized"); + + if(RunHiddenCheckboxState) { + //Do nothing + } else { + if(AlwaysMaximizedCheckboxState) { + window.maximize(); + } else { + window.show() + } + }""") + createWindow.close() + + createWindow = open(notionResourcesPath + '/app/main/createWindow.js', 'wt') + createWindow.write(createWindowText) + createWindow.close() + else: + print(" There is no files at Notion/resources/app/main/createWindow.js - Nothing was done") + sleep(sleepTime) + print("-Done-\n") + sleep(sleepTime) + + print("Step 4") + sleep(sleepTime) + # Step 4 + if os.path.isfile(notionResourcesPath + '/app/renderer/index.js'): + print(" Adjusting drag area for frameless window in Notion/resources/app/renderer/index.js") + sleep(sleepTime) + createWindow = open(notionResourcesPath + '/app/renderer/index.js', 'rt') + createWindowText = createWindow.read() + topIndex = createWindowText.rfind("top") + createWindowTextSplit = createWindowText[topIndex:] + createWindowTextSplit = createWindowTextSplit.replace("right: 0", "right: 420 ") + createWindowTextSplit = createWindowTextSplit.replace("top: 0", "top: 1 ") + createWindowTextSplit = createWindowTextSplit.replace("height: 34", "height: 16") + createWindowText = createWindowText[:topIndex] + createWindowTextSplit + createWindow.close() + + createWindow = open(notionResourcesPath + '/app/renderer/index.js', 'wt') + createWindow.write(createWindowText) + createWindow.close() + else: + print(" There is no files at Notion/resources/app/renderer/index.js - Nothing was done") + sleep(sleepTime) + print("-Done-\n") + sleep(sleepTime) + + print("Step 5") + sleep(sleepTime) + # Step 5 + if os.path.isfile(notionResourcesPath + '/app/main/main.js'): + print(" Adding tray support at Notion/resources/app/main/main.js") + sleep(sleepTime) + print(" Adding context menu with settings to tray") + sleep(sleepTime) + + hotkeysCodeText = """ + const {Tray, Menu} = require("electron"); + let tray = null; + electron_1.app.on("ready", function() { + handleReady(); + + const path = require("path"); + const Store = require(path.join(__dirname,'../','store.js')); + + const store = new Store({ + configName: "user-preferences", + defaults: { + alwaysMaximized: false, + CloseToTrayCheckbox: false, + runHidden: false + } + }); + + var RunAtStartupCheckboxState = electron_1.app.getLoginItemSettings().openAtLogin; + var RunHiddenCheckboxState = store.get("runHidden"); + var AlwaysMaximizedCheckboxState = store.get("alwaysMaximized"); + var CloseToTrayCheckboxState = store.get("CloseToTrayCheckbox"); + + tray = new Tray(path.join(__dirname,"./icon.ico")); + const contextMenu = Menu.buildFromTemplate([ + { + id: "RunAtStartupCheckbox", + label: "Run at Startup", + type:"checkbox", + checked: RunAtStartupCheckboxState, + click() { + var isChecked = contextMenu.getMenuItemById("RunAtStartupCheckbox").checked; + if(isChecked) { + electron_1.app.setLoginItemSettings({ openAtLogin: true}); + } else { + electron_1.app.setLoginItemSettings({ openAtLogin: false}); + } + } + }, + { + id: "runHidden", + label: "Run Hidden", + type:"checkbox", + checked: RunHiddenCheckboxState, + click() { + var isChecked = contextMenu.getMenuItemById("runHidden").checked; + if(isChecked) { + store.set("runHidden", true); + } else { + store.set("runHidden", false); + } + } + }, + { + id: "AlwaysMaximizedCheckbox", + label: "Open Maximized", + type: "checkbox", + checked: AlwaysMaximizedCheckboxState, + click() { + var isChecked = contextMenu.getMenuItemById("AlwaysMaximizedCheckbox").checked; + if(isChecked) { + store.set("alwaysMaximized", true); + } else { + store.set("alwaysMaximized", false); + } + } + }, + { + id: "CloseToTrayCheckbox", + label: "Close To Tray", + type: "checkbox", + checked: CloseToTrayCheckboxState, + click() { + var isChecked = contextMenu.getMenuItemById("CloseToTrayCheckbox").checked; + if(isChecked) { + store.set("CloseToTrayCheckbox", true); + } else { + store.set("CloseToTrayCheckbox", false); + } + } + }, + { + type: "separator" + }, + { + label: "Quit", + role: "quit" + } + ]); + tray.setContextMenu(contextMenu); + + tray.on("click", function() { + var win = electron_1.BrowserWindow.getAllWindows()[0]; + var alwaysMax = contextMenu.getMenuItemById("AlwaysMaximizedCheckbox").checked; + if (win.isVisible()) { + if(win.isMinimized()) { + win.show() + } else { + win.hide(); + } + } else { + if(alwaysMax){ + win.maximize(); + } else { + win.show(); + } + } + }); + + var notionToggleHotkey = 'ctrl+shift+a'; + const globalShortcut = electron_1.globalShortcut; + globalShortcut.register(notionToggleHotkey, function() { + var win = electron_1.BrowserWindow.getAllWindows()[0]; + var alwaysMax = contextMenu.getMenuItemById("AlwaysMaximizedCheckbox").checked; + if (win.isVisible()) { + win.hide(); + } else { + if(alwaysMax){ + win.maximize(); + } else { + win.show(); + } + } + }); + }); + """ + mainJs = open(notionResourcesPath + '/app/main/main.js', 'rt') + mainJsText = mainJs.read() + mainJs.close() + + print(" Adding hotkey to show/hide Notion window") + sleep(sleepTime) + if "var notionToggleHotkey" in mainJsText: + mainJsText = re.sub(r"var notionToggleHotkey = '([A-Za-z0-9+_\./\\-]*)'", "var notionToggleHotkey = " + windowToggleHotkey, mainJsText) + else : + mainJsText = mainJsText.replace('electron_1.app.on("ready", handleReady);' , hotkeysCodeText) + mainJsText = mainJsText.replace('win.focus()','win.show()',1) + + print(" Copying tray icon ""icon.ico"" to /app/main/ ") + sleep(sleepTime) + copyfile('./resources/icon.ico', notionResourcesPath + '/app/main/icon.ico' ) + + print(" Copying settings saver class ""store.js"" to /app/ ") + sleep(sleepTime) + copyfile('./resources/store.js', notionResourcesPath + '/app/store.js' ) + + mainJs = open(notionResourcesPath + '/app/main/main.js', 'wt') + mainJs.write(mainJsText) + mainJs.close() + sleep(sleepTime) + else: + print(" There is no files at Notion/resources/app/main/main.js - Nothing was done") + sleep(sleepTime) + print("-Done-") + sleep(sleepTime) + + sleep(0.5) + print("========= END OF LOG =========") + sleep(0.5) + print(""" + + ____ _ _____ ____ _ _ _____ ____ + | _ \ / \|_ _/ ___| | | | ____| _ \ + | |_) / _ \ | || | | |_| | _| | | | | + | __/ ___ \| || |___| _ | |___| |_| | + |_| /_/ \_|_| \____|_| |_|_____|____/ + + """) + sleep(4) +except Exception as e: + sleep(0.5) + print("========= END OF LOG =========") + sleep(0.5) + print(""" + __________ ____ ____ ____ + / ____/ __ \/ __ \/ __ \/ __ \\ + / __/ / /_/ / /_/ / / / / /_/ / + / /___/ _, _/ _, _/ /_/ / _, _/ + /_____/_/ |_/_/ |_|\____/_/ |_| + + \n\n""" + str(e)) + os.system('pause') diff --git a/Notion Customization/Customization Remover.py b/Notion Customization/Customization Remover.py new file mode 100644 index 0000000..75427ad --- /dev/null +++ b/Notion Customization/Customization Remover.py @@ -0,0 +1,80 @@ +""" +# Step 1 +1.Locating notion app at ./%Username%/AppData/Local/Programs/Notion +2.Unpacking app.asar in new folder at./Notion/resources/app +3.Renaming file app.asar to app.asar.bak (because instead app won't use folder "app" to get all resources from it) +4.If app.asar already unpacked - it will try to locate folder "app" and skip to next step + +# Step 2 +1. Editing userscript file to replace "full_path_to_custom_style" with full path to ./custom_style.css +2. Adding userscript from main.user.js(should be in same folder with this .py file) to the ./app/renderer/preload.js +3. If there is already userscript - it will overwrite it. + +# Step 3 +1. Adding property "frame: false" to the place where application window is creating + +# Step 4 +1. Changes "window drag" area, to make window draggable + 1.1. You can change it by yourself, if you experiencing problems with dragging window or with clicking buttons on app topbar + Because this "draggable area" is creating on top of the other stuff, so if it will have button behind it - it won't be clickable. + You should change top,left,right properties. Now it's 2px on top, 390px on left and 420px on right; +""" +import os +from time import sleep +from shutil import copyfile +from shutil import rmtree +import re + +try: + sleepTime = 0.5 + sleep(sleepTime) + print("========= START OF LOG =========") + sleep(sleepTime) + LOCALAPPDATA = os.getenv('LOCALAPPDATA') + LOCALAPPDATA = LOCALAPPDATA.replace('\\', '/') + notionResourcesPath = LOCALAPPDATA + '/Programs/Notion/resources' + + if os.path.exists(notionResourcesPath + '/app'): + rmtree(notionResourcesPath + '/app') + print("Removing ""app"" folder") + sleep(sleepTime) + else: + print("There is no ""app"" folder at ./Notion/resources/app - Skipping this step") + sleep(sleepTime) + + if os.path.isfile(notionResourcesPath + '/app.asar.bak'): + renameSource = notionResourcesPath + '/app.asar.bak' + renameDestination = notionResourcesPath + '/app.asar' + os.rename(renameSource, renameDestination) + print("Renaming app.asar.bak to app.asar") + sleep(sleepTime) + else: + print("There is no ""app.asar.bak"" at ./Notion/resources/app.asar.bak - Skipping this step") + sleep(sleepTime) + + sleep(0.5) + print("========= LOG =========") + sleep(0.5) + print(""" + + ____ _____ __ __ _____ _______ ____ + | _ \| ____| \/ |/ _ \ \ / | ____| _ \ + | |_) | _| | |\/| | | | \ \ / /| _| | | | | + | _ <| |___| | | | |_| |\ V / | |___| |_| | + |_| \_|_____|_| |_|\___/ \_/ |_____|____/ + + """) + sleep(2) +except Exception as e: + sleep(0.5) + print("========= END OF LOG =========") + sleep(0.5) + print(""" + __________ ____ ____ ____ + / ____/ __ \/ __ \/ __ \/ __ \\ + / __/ / /_/ / /_/ / / / / /_/ / + / /___/ _, _/ _, _/ /_/ / _, _/ + /_____/_/ |_/_/ |_|\____/_/ |_| + + \n\n""" + str(e)) + os.system('pause') diff --git a/Notion Customization/resources/custom_style.css b/Notion Customization/resources/custom_style.css new file mode 100644 index 0000000..c65a7de --- /dev/null +++ b/Notion Customization/resources/custom_style.css @@ -0,0 +1,135 @@ +/* Window control buttons block */ +#window-buttons-area { + padding-left: 14px; +} +/* Light Theme style for window contoll buttons */ +.notion-light-theme .window-buttons { + background: rgb(255, 255, 255); + color: black; + border: 0; + margin: 0px 0px 0px 9px; + width: 32px; + line-height: 26px; + border-radius: 4px; + font-size: 16px; + transition-duration: 0.2s; + font-weight: bold; +} +.notion-light-theme .window-buttons:hover { + background: rgb(239, 239, 239); +} +/* Light Theme style for window contoll buttons */ + + +/* Dark Theme style for window contoll buttons */ +.notion-dark-theme .window-buttons { + background: rgb(47, 52, 55); + border: 0; + margin: 0px 0px 0px 9px; + width: 32px; + line-height: 26px; + border-radius: 4px; + font-size: 16px; + transition-duration: 0.2s; +} +.notion-dark-theme .window-buttons:hover { + background: rgb(71, 76, 80); +} +/* Dark Theme style for window contoll buttons */ + + + +/* To make cursor style as pointer when hover on scrollbar */ +.notion-scroller { + cursor: auto; +} +/* Scrollbar size */ +::-webkit-scrollbar { + width: 5px; /* To change vertical scrollbar width */ + height: 12px; /* To change horizontal scrollbar height */ +} +/* Element where vertical and horizontal scrollbars converge */ +::-webkit-scrollbar-corner{ + background-color: transparent; +} + +/* Light Theme style for Scrollbars */ +.notion-light-theme ::-webkit-scrollbar-thumb { + border-radius: 5px; + background-color: #afafaf; +} +.notion-light-theme ::-webkit-scrollbar-track { + border-radius: 5px; + background-color: #e4e4e4; +} +.notion-light-theme ::-webkit-scrollbar-thumb:hover{ + background: #969696; +} +/* Light Theme style for Scrollbars */ + + +/* Dark Theme style for Scrollbars */ +.notion-dark-theme ::-webkit-scrollbar-track { + border-radius: 5px; + background-color: #3d3d42; +} +.notion-dark-theme ::-webkit-scrollbar-thumb { + border-radius: 5px; + background-color: #5d5d5d; +} +.notion-dark-theme ::-webkit-scrollbar-thumb:hover{ + background: #868686; +} +/* Dark Theme style for Scrollbars */ + + + +/* Changing table padding to make it more wider */ +[style^="flex-shrink: 0; flex-grow: 1; width: 100%; max-width: 100%; display: flex; align-items: center; flex-direction: column; font-size: 16px; color: rgba(255, 255, 255, 0.9); padding: 0px 96px 30vh;"] .notion-table-view, +[class="notion-scroller"]>.notion-table-view { + padding-left: 35px !important; + padding-right: 15px !important; + min-width: 0% !important; +} +/* Changing the width of horizontal scroller, because of wider table */ +[style^="flex-shrink: 0; flex-grow: 1; width: 100%; max-width: 100%; display: flex; align-items: center; flex-direction: column; font-size: 16px; color: rgba(255, 255, 255, 0.9); padding: 0px 96px 30vh;"] .notion-selectable .notion-scroller.horizontal::-webkit-scrollbar-track { + margin-left: 10px; + margin-right: 10px; +} +/* Hide "+" button when you hover on table row, because of it's useless for me, and this buttons takes like 15px from the left side of table */ +[style^="flex-shrink: 0; flex-grow: 1; width: 100%; max-width: 100%; display: flex; align-items: center; flex-direction: column; font-size: 16px; color: rgba(255, 255, 255, 0.9); padding: 0px 96px 30vh;"] .notion-table-view [style^="opacity:"]>[role="button"], +[class="notion-scroller"]>.notion-table-view [style^="opacity:"]>[role="button"] { + display:none !important; +} + +/* Same as with table. Makes board view more wider */ +.notion-board-view { + padding-left: 10px !important; + padding-right: 10px !important; +} +/* Changing content block position, less height - higher content block */ +[style^="position: relative; width: 100%; display: flex; flex-direction: column; align-items: center; height: 30vh;"] { + height: 12vh !important; +} +/* Changing cover image height to match higher content block */ +[style^="position: relative; width: 100%; display: flex; flex-direction: column; align-items: center; height: 30vh;"] img { + height: 20vh !important; +} +/* Changing table columns width */ +[data-block-id^="PutYourIDHere"]>[style^="display: flex; position: absolute; background: rgb(47, 52, 55); z-index: 82; height: 33px; color: rgba(255, 255, 255, 0.6);"]>div:nth-child(1)>div:nth-child(10)>div:nth-child(1), +[data-block-id^="PutYourIDHere"]>[style^="position: relative; min-width: calc(100% - 192px);"]>[data-block-id]>div:nth-child(10), +[data-block-id^="PutYourIDHere"]>div:nth-child(5)>div:nth-child(10){ + width: 45px !important; +} +/* Hiding selection, because of changing columns width bugs selection inside table */ +[data-block-id^="PutYourIDHere"] [style^="position: absolute; top: 0px; left: 0px; pointer-events: none;"]:not(.notion-presence-container) { + display: none; +} + +/* Changing table header icons to make it smaller */ +[style^="display: flex; position: absolute; background: rgb(47, 52, 55); z-index: 82; height: 33px; color: rgba(255, 255, 255, 0.6);"] div:nth-child(1) svg { + height: 10px !important; + width: 10px !important; + margin-right: -4px; +} + diff --git a/Notion Customization/resources/icon.ico b/Notion Customization/resources/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b46f68cf8ad88d1dc489d49700ca4da9b7cc473f GIT binary patch literal 112696 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 div') == undefined) { + return; + } + var browserWindow = require('electron').remote.getCurrentWindow(); + var element = document.createElement("div"); + element.id = "window-buttons-area"; + var node = document.querySelector('div.notion-topbar > div'); + node.appendChild(element); + + node = document.querySelector("#window-buttons-area"); + + /* AlwaysOnTop Button */ + element = document.createElement("button"); + element.classList.add("window-buttons"); + element.innerHTML = "🠛"; + element.onclick = function () { + if(!browserWindow.isAlwaysOnTop()) { + browserWindow.setAlwaysOnTop(true); + this.innerHTML = "🠙"; + } else { + browserWindow.setAlwaysOnTop(false); + this.innerHTML = "🠛"; + } + }; + node.appendChild(element); + /* AlwaysOnTop Button */ + + /* Minimize Button */ + element = document.createElement("button"); + element.classList.add("window-buttons"); + element.innerHTML = "⚊"; + element.onclick = function () { browserWindow.minimize(); }; + node.appendChild(element); + /* Minimize Button */ + + /* Maximize Button */ + element = document.createElement("button"); + element.classList.add("window-buttons"); + element.innerHTML = "▢"; + element.onclick = function () { + if (!browserWindow.isMaximized()) { + browserWindow.maximize(); + } else { + browserWindow.unmaximize(); + } + }; + node.appendChild(element); + /* Maximize Button */ + + /* Close Button */ + const path = require("path") + element = document.createElement("button"); + element.classList.add("window-buttons"); + element.innerHTML = "⨉"; + element.onclick = function () { + const Store = require(path.join(__dirname,'../','store.js')); + const store = new Store({ + configName: "user-preferences", + defaults: { + CloseToTrayCheckbox: false + } + }); + var CloseToTrayCheckboxState = store.get("CloseToTrayCheckbox"); + if(CloseToTrayCheckboxState) { + browserWindow.hide(); + } else { + browserWindow.close(); + } + }; + node.appendChild(element); + /* Close Button */ + + window.clearInterval(buttonsIntervalId); + } + /* Window Control Buttons */ +} +require('electron').remote.getGlobal('setTimeout')(() => { userscript();}, 100); \ No newline at end of file diff --git a/Notion Customization/resources/store.js b/Notion Customization/resources/store.js new file mode 100644 index 0000000..3c5737e --- /dev/null +++ b/Notion Customization/resources/store.js @@ -0,0 +1,30 @@ +const electron = require('electron'); +const path = require('path'); +const fs = require('fs'); + +class Store { + constructor(opts) { + const userDataPath = __dirname + this.path = path.join(userDataPath, opts.configName + '.json'); + + this.data = parseDataFile(this.path, opts.defaults); + } + + get(key) { + return this.data[key]; + } + + set(key, val) { + this.data[key] = val; + fs.writeFileSync(this.path, JSON.stringify(this.data)); + } +} + +function parseDataFile(filePath, defaults) { + try { + return JSON.parse(fs.readFileSync(filePath)); + } catch(error) { + return defaults; + } +} +module.exports = Store; \ No newline at end of file