From 425e22a2f3fff9d8b8780544fbf1a1b8ca478819 Mon Sep 17 00:00:00 2001 From: Jonas Gao Date: Tue, 27 Jun 2023 01:36:24 +0800 Subject: [PATCH 1/6] Support custom css --- pack/electron/custom-css-loader.js | 26 +++++++++++++++ pack/electron/electron-main.js | 3 +- src/App.vue | 52 ++++++++++++++++++++++++++++++ src/components/Setting.vue | 10 ++++++ src/customCssLoader.js | 20 ++++++++++++ src/storage.js | 3 ++ 6 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 pack/electron/custom-css-loader.js create mode 100644 src/customCssLoader.js diff --git a/pack/electron/custom-css-loader.js b/pack/electron/custom-css-loader.js new file mode 100644 index 000000000..3175c6297 --- /dev/null +++ b/pack/electron/custom-css-loader.js @@ -0,0 +1,26 @@ +const { ipcMain } = require('electron'); +const fs = require('fs'); + +ipcMain.on('load-custom-css', (event, arg) => { + fs.access(arg, fs.constants.R_OK, (err) => { + if (err) { + event.sender.send('loaded-custom-css', { + code: 'NOT_READABLE', + }); + } else { + fs.readFile(arg, 'utf-8', (readErr, data) => { + if (readErr) { + event.sender.send('loaded-custom-css', { + code: 'FAIL', + message: readErr.message, + }); + } else { + event.sender.send('loaded-custom-css', { + code: 'SUCCESS', + content: data.toString(), + }); + } + }); + } + }); +}); diff --git a/pack/electron/electron-main.js b/pack/electron/electron-main.js index e5e3bcf51..83105ee4c 100644 --- a/pack/electron/electron-main.js +++ b/pack/electron/electron-main.js @@ -1,6 +1,7 @@ // Modules to control application life and create native browser window const { app, BrowserWindow, Menu, ipcMain, dialog } = require('electron'); const fontManager = require('./font-manager'); +require('./custom-css-loader'); const winState = require('./win-state'); const url = require('url'); @@ -24,7 +25,7 @@ process.on('uncaughtException', (err, origin) => { dialog.showMessageBoxSync(mainWindow, { type: 'error', - title: 'Whoops! Uncaught Exception', + title: 'Whoops! Uncaught Exception', message: err.stack, detail: '\nDon\'t worry, I will fix it! 😎😎\n\n' + 'Submit issue to: \nhttps://github.com/qishibo/AnotherRedisDesktopManager/' diff --git a/src/App.vue b/src/App.vue index a864b7675..b89bb7f16 100644 --- a/src/App.vue +++ b/src/App.vue @@ -30,6 +30,22 @@ import Aside from '@/Aside'; import Tabs from '@/components/Tabs'; import UpdateCheck from '@/components/UpdateCheck'; import addon from './addon'; +import customCssLoader from './customCssLoader'; + +const injectStylesheet = (src) => { + customCssLoader.loadCustomCss(src); + customCssLoader.onCustomCssLoaded((content) => { + let styleElement = document.getElementById('custom-css'); + if (!styleElement) { + styleElement = document.createElement('style'); + styleElement.id = 'custom-css'; + document.head.append(styleElement); + } + styleElement.innerHTML = content; + }, (code, message) => { + alert(message || code); + }); +}; export default { name: 'App', @@ -82,6 +98,42 @@ export default { let sideWidth = localStorage.sideWidth; sideWidth && (this.sideWidth = sideWidth); }, + openHrefInBrowser() { + const shell = require('electron').shell; + + document.addEventListener('click', function (event) { + const ele = event.target; + + if (ele && (ele.nodeName.toLowerCase() === 'a') && ele.href.startsWith('http')) { + event.preventDefault(); + shell.openExternal(ele.href); + } + }); + }, + reloadSettings() { + this.initFont(); + this.initZoom(); + this.loadCustomCss(); + }, + initFont() { + const fontFamily = this.$storage.getFontFamily(); + document.body.style.fontFamily = fontFamily; + // tell monaco editor + this.$bus.$emit('fontInited', fontFamily); + }, + initZoom() { + let zoomFactor = this.$storage.getSetting('zoomFactor'); + zoomFactor = zoomFactor ? zoomFactor : 1.0; + + const {webFrame} = require('electron'); + webFrame.setZoomFactor(zoomFactor); + }, + loadCustomCss() { + const customCss = this.$storage.getCustomCss(); + if (customCss) { + injectStylesheet(customCss); + } + }, }, mounted() { setTimeout(() => { diff --git a/src/components/Setting.vue b/src/components/Setting.vue index f53c6318d..e102be1c5 100644 --- a/src/components/Setting.vue +++ b/src/components/Setting.vue @@ -60,6 +60,15 @@ + + + + + + @@ -162,6 +171,7 @@ export default { zoomFactor: 1.0, keysPageSize: 500, showLoadAllKeys: false, + customCss: '', }, importConnectionVisible: false, connectionFileContent: '', diff --git a/src/customCssLoader.js b/src/customCssLoader.js new file mode 100644 index 000000000..eee994c6e --- /dev/null +++ b/src/customCssLoader.js @@ -0,0 +1,20 @@ +import { ipcRenderer } from 'electron'; + +export default { + loadCustomCss(src) { + ipcRenderer.send('load-custom-css', src); + }, + onCustomCssLoaded(callback, failCallback) { + ipcRenderer.on('loaded-custom-css', (event, result) => { + const { code, message, content } = result; + switch (code) { + case 'SUCCESS': + callback(content); + break; + default: + failCallback(code, message); + break; + } + }); + }, +}; diff --git a/src/storage.js b/src/storage.js index 64b616b1e..247ed0ec0 100644 --- a/src/storage.js +++ b/src/storage.js @@ -27,6 +27,9 @@ export default { return fontFamily.map(line => {return `"${line}"`}).join(','); }, + getCustomCss() { + return this.getSetting('customCss') || ''; + }, getCustomFormatter(name = '') { let formatters = localStorage.getItem('customFormatters'); formatters = formatters ? JSON.parse(formatters) : []; From 5a9c67b093596130d11ea47f162e268389d51d9a Mon Sep 17 00:00:00 2001 From: Jonas Gao Date: Tue, 27 Jun 2023 01:36:35 +0800 Subject: [PATCH 2/6] Translate custom css --- src/i18n/langs/cn.js | 2 ++ src/i18n/langs/de.js | 2 ++ src/i18n/langs/en.js | 2 ++ src/i18n/langs/es.js | 2 ++ src/i18n/langs/fr.js | 2 ++ src/i18n/langs/it.js | 2 ++ src/i18n/langs/ko.js | 2 ++ src/i18n/langs/pt.js | 2 ++ src/i18n/langs/ru.js | 2 ++ src/i18n/langs/tr.js | 2 ++ src/i18n/langs/tw.js | 2 ++ src/i18n/langs/ua.js | 2 ++ 12 files changed, 24 insertions(+) diff --git a/src/i18n/langs/cn.js b/src/i18n/langs/cn.js index 54972fd11..c3cf48f29 100644 --- a/src/i18n/langs/cn.js +++ b/src/i18n/langs/cn.js @@ -167,6 +167,8 @@ const cn = { close_other: '关闭其他标签', slow_log: '慢查询', load_current_folder: '只加载该文件夹', + custom_css: '自定义样式', + custom_css_placeholder: '请输入文件路径', }, }; diff --git a/src/i18n/langs/de.js b/src/i18n/langs/de.js index ea36f1507..39cb26144 100644 --- a/src/i18n/langs/de.js +++ b/src/i18n/langs/de.js @@ -167,6 +167,8 @@ const de = { close_other: 'Schließen Sie andere Registerkarten', slow_log: 'Langsame Abfrage', load_current_folder: 'Nur aktuellen Ordner laden', + custom_css: 'Benutzerdefinierter Stil', + custom_css_placeholder: 'Bitte geben Sie den Dateipfad ein', }, }; diff --git a/src/i18n/langs/en.js b/src/i18n/langs/en.js index d7b6abf9c..d9e4e5480 100644 --- a/src/i18n/langs/en.js +++ b/src/i18n/langs/en.js @@ -167,6 +167,8 @@ const en = { close_other: 'Close Other Tabs', slow_log: 'Slow Query', load_current_folder: 'Only Load Current Folder', + custom_css: 'Custom CSS', + custom_css_placeholder: 'Please enter file path', }, }; diff --git a/src/i18n/langs/es.js b/src/i18n/langs/es.js index 0f343421e..8570994ab 100644 --- a/src/i18n/langs/es.js +++ b/src/i18n/langs/es.js @@ -167,6 +167,8 @@ const es = { close_other: 'Cerrar otras pestañas', slow_log: 'Consulta lenta', load_current_folder: 'Cargar solo la carpeta actual', + custom_css: 'Estilo personalizado', + custom_css_placeholder: 'Por favor ingrese la ruta del archivo', }, }; diff --git a/src/i18n/langs/fr.js b/src/i18n/langs/fr.js index 30fe69c66..1bc8620b1 100644 --- a/src/i18n/langs/fr.js +++ b/src/i18n/langs/fr.js @@ -167,6 +167,8 @@ const fr = { close_other: 'Fermer les autres onglets', slow_log: 'Requête lente', load_current_folder: 'Charger uniquement le dossier actuel', + custom_css: 'Style personnalisé', + custom_css_placeholder: 'Veuillez entrer le chemin du fichier', }, }; diff --git a/src/i18n/langs/it.js b/src/i18n/langs/it.js index 47b1e2d41..51d37be8e 100644 --- a/src/i18n/langs/it.js +++ b/src/i18n/langs/it.js @@ -167,6 +167,8 @@ const it = { close_other: 'Chiudi altre schede', slow_log: 'Interrogazione lenta', load_current_folder: 'Carica solo la cartella corrente', + custom_css: 'Stile personalizzato', + custom_css_placeholder: 'Inserisci il percorso del file', }, }; diff --git a/src/i18n/langs/ko.js b/src/i18n/langs/ko.js index 2b6a01190..9ee874d37 100644 --- a/src/i18n/langs/ko.js +++ b/src/i18n/langs/ko.js @@ -167,6 +167,8 @@ const ko = { close_other: '다른 탭 닫기', slow_log: '저성능 쿼리', load_current_folder: '현재 폴더만 로드', + custom_css: '맞춤 스타일', + custom_css_placeholder: '파일 경로를 입력해주세요', }, }; diff --git a/src/i18n/langs/pt.js b/src/i18n/langs/pt.js index 6580d4a4a..8d78ae95a 100644 --- a/src/i18n/langs/pt.js +++ b/src/i18n/langs/pt.js @@ -167,6 +167,8 @@ const pt = { close_other: 'Fechar outras guias', slow_log: 'Consulta lenta', load_current_folder: 'Carregar apenas a pasta atual', + custom_css: 'Estilo personalizado', + custom_css_placeholder: 'Por favor insira o caminho do arquivo', }, }; diff --git a/src/i18n/langs/ru.js b/src/i18n/langs/ru.js index 027b6c27c..fd15d4328 100644 --- a/src/i18n/langs/ru.js +++ b/src/i18n/langs/ru.js @@ -167,6 +167,8 @@ const ru = { close_other: 'Закрыть другие вкладки', slow_log: 'Медленный запрос', load_current_folder: 'Загружать только текущую папку', + custom_css: 'Пользовательский стиль', + custom_css_placeholder: 'Пожалуйста, введите путь к файлу', }, }; diff --git a/src/i18n/langs/tr.js b/src/i18n/langs/tr.js index bbca9180f..d1fed8d01 100644 --- a/src/i18n/langs/tr.js +++ b/src/i18n/langs/tr.js @@ -167,6 +167,8 @@ const tr = { close_other: 'Diğer Sekmeleri Kapat', slow_log: 'Yavaş Sorgu', load_current_folder: 'Yalnızca Geçerli Klasörü Yükle', + custom_css: 'Özel stil', + custom_css_placeholder: 'Lütfen dosya yolunu girin', }, }; diff --git a/src/i18n/langs/tw.js b/src/i18n/langs/tw.js index 46a836120..ba22457ac 100644 --- a/src/i18n/langs/tw.js +++ b/src/i18n/langs/tw.js @@ -167,6 +167,8 @@ const tw = { close_other: '關閉其他標籤', slow_log: '慢查詢', load_current_folder: '僅載入目前資料夾', + custom_css: '自定義樣式', + custom_css_placeholder: '请输入文件路径', }, }; diff --git a/src/i18n/langs/ua.js b/src/i18n/langs/ua.js index c55f84e3e..e3c2dedd4 100644 --- a/src/i18n/langs/ua.js +++ b/src/i18n/langs/ua.js @@ -167,6 +167,8 @@ const ua = { close_other: 'Закрийте інші вкладки', slow_log: 'Повільний запит', load_current_folder: 'Завантажувати лише поточну папку', + custom_css: 'Індивідуальний стиль', + custom_css_placeholder: 'Введіть шлях до файлу', }, }; From cd6211b6db86a0380a758b862a7e2ba25f208f5a Mon Sep 17 00:00:00 2001 From: Jonas Gao Date: Mon, 21 Aug 2023 11:21:14 +0800 Subject: [PATCH 3/6] Tune Aside style --- src/Aside.vue | 77 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/src/Aside.vue b/src/Aside.vue index 8555065f1..d3c44a54f 100644 --- a/src/Aside.vue +++ b/src/Aside.vue @@ -3,11 +3,30 @@
- - + +
- {{ $t('message.new_connection') }} + + {{ $t('message.new_connection') }} +
@@ -45,7 +64,14 @@ export default { data() { return {}; }, - components: { Connections, NewConnectionDialog, Setting, CommandLog, HotKeys, CustomFormatter }, + components: { + Connections, + NewConnectionDialog, + Setting, + CommandLog, + HotKeys, + CustomFormatter, + }, methods: { editConnectionFinished() { this.$refs.connections.initConnections(); @@ -82,25 +108,28 @@ export default { From 22bdd4673b9d12e632b704e8326157d2f2981381 Mon Sep 17 00:00:00 2001 From: Jonas Gao Date: Mon, 21 Aug 2023 11:22:23 +0800 Subject: [PATCH 4/6] Tune ConnectionWrapper right padding --- src/components/ConnectionWrapper.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ConnectionWrapper.vue b/src/components/ConnectionWrapper.vue index d4c9bf8fc..b07a30dea 100644 --- a/src/components/ConnectionWrapper.vue +++ b/src/components/ConnectionWrapper.vue @@ -222,7 +222,7 @@ export default { } document.querySelector('.connections-list').scrollTo({ - top: scrollTop, + top: scrollTop, behavior: 'smooth', }); }, 320); @@ -242,7 +242,7 @@ export default { /*menu ul*/ .connection-menu { margin-bottom: 8px; - padding-right: 6px; + padding-right: 8px; border-right: 0; } From 4ffb7029293e7773660ad022ad2f7e428c74188f Mon Sep 17 00:00:00 2001 From: Jonas Gao Date: Mon, 21 Aug 2023 12:55:45 +0800 Subject: [PATCH 5/6] Tune ConnectionMenu name style --- src/components/ConnectionMenu.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ConnectionMenu.vue b/src/components/ConnectionMenu.vue index 3d18a767e..b24b560ea 100644 --- a/src/components/ConnectionMenu.vue +++ b/src/components/ConnectionMenu.vue @@ -342,7 +342,7 @@ export default { .connection-menu .connection-name { margin-right: 115px; - padding-right: 6px; + padding-left: 5px; word-break: keep-all; white-space: nowrap; overflow: hidden; From 715a0b10e79c14d36aef2f13f46c9911b6473bea Mon Sep 17 00:00:00 2001 From: Jonas Gao Date: Thu, 24 Aug 2023 13:33:24 +0800 Subject: [PATCH 6/6] Custom window title bar --- pack/electron/electron-main.js | 47 +++++++++----- src/App.vue | 49 +++++++++++---- src/components/TitleBar.vue | 110 +++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 29 deletions(-) create mode 100644 src/components/TitleBar.vue diff --git a/pack/electron/electron-main.js b/pack/electron/electron-main.js index 83105ee4c..27872516e 100644 --- a/pack/electron/electron-main.js +++ b/pack/electron/electron-main.js @@ -1,5 +1,11 @@ // Modules to control application life and create native browser window -const { app, BrowserWindow, Menu, ipcMain, dialog } = require('electron'); +const { + app, + BrowserWindow, + Menu, + ipcMain, + dialog, +} = require('electron'); const fontManager = require('./font-manager'); require('./custom-css-loader'); const winState = require('./win-state'); @@ -28,7 +34,7 @@ process.on('uncaughtException', (err, origin) => { title: 'Whoops! Uncaught Exception', message: err.stack, detail: '\nDon\'t worry, I will fix it! 😎😎\n\n' - + 'Submit issue to: \nhttps://github.com/qishibo/AnotherRedisDesktopManager/' + + 'Submit issue to: \nhttps://github.com/qishibo/AnotherRedisDesktopManager/', }); process.exit(); @@ -51,6 +57,7 @@ function createWindow() { height: lastWinStage.height, icon: `${__dirname}/icons/icon.png`, autoHideMenuBar: true, + frame: false, webPreferences: { nodeIntegration: true, // add this to keep 'remote' module avaiable. Tips: it will be removed in electron 14 @@ -72,7 +79,7 @@ function createWindow() { protocol: 'file', slashes: true, pathname: path.join(__dirname, 'index.html'), - query: {version: app.getVersion()}, + query: { version: app.getVersion() }, })); } else { mainWindow.loadURL(`http://localhost:9988/?version=${app.getVersion()}`); @@ -122,19 +129,25 @@ app.on('activate', () => { }); // hide window -ipcMain.on('hideWindow',function() { +ipcMain.on('hideWindow', () => { mainWindow && mainWindow.hide(); }); // minimize window -ipcMain.on('minimizeWindow',function() { +ipcMain.on('minimizeWindow', () => { mainWindow && mainWindow.minimize(); }); // toggle maximize -ipcMain.on('toggleMaximize',function() { +ipcMain.on('toggleMaximize', () => { if (mainWindow) { mainWindow.isMaximized() ? mainWindow.restore() : mainWindow.maximize(); } }); +// close window +ipcMain.on('closeApp', () => { + if (mainWindow) { + mainWindow.close(); + } +}); ipcMain.handle('getMainArgs', (event, arg) => { return { @@ -158,8 +171,8 @@ if (process.platform === 'darwin') { { role: 'hideothers' }, { role: 'unhide' }, { type: 'separator' }, - { role: 'quit' } - ] + { role: 'quit' }, + ], }, { role: 'editMenu' }, // { role: 'viewMenu' }, @@ -169,8 +182,8 @@ if (process.platform === 'darwin') { ...( (APP_ENV === 'production') ? [] : [{ role: 'toggledevtools' }] ), - { role: 'togglefullscreen' } - ] + { role: 'togglefullscreen' }, + ], }, // { role: 'windowMenu' }, { @@ -182,7 +195,7 @@ if (process.platform === 'darwin') { { role: 'front' }, { type: 'separator' }, // { role: 'window' } - ] + ], }, { role: 'help', @@ -190,12 +203,12 @@ if (process.platform === 'darwin') { { label: 'Learn More', click: async () => { - const { shell } = require('electron') - await shell.openExternal('https://github.com/qishibo/AnotherRedisDesktopManager') - } - } - ] - } + const { shell } = require('electron'); + await shell.openExternal('https://github.com/qishibo/AnotherRedisDesktopManager'); + }, + }, + ], + }, ]; menu = Menu.buildFromTemplate(template); diff --git a/src/App.vue b/src/App.vue index b89bb7f16..0d4322c32 100644 --- a/src/App.vue +++ b/src/App.vue @@ -17,6 +17,7 @@ + @@ -31,6 +32,7 @@ import Tabs from '@/components/Tabs'; import UpdateCheck from '@/components/UpdateCheck'; import addon from './addon'; import customCssLoader from './customCssLoader'; +import TitleBar from '@/components/TitleBar'; const injectStylesheet = (src) => { customCssLoader.loadCustomCss(src); @@ -62,14 +64,18 @@ export default { // restore side bar width this.restoreSideBarWidth(); }, - components: {Aside, Tabs, UpdateCheck}, + components: { + TitleBar, + Aside, + Tabs, + UpdateCheck, + }, methods: { bindSideBarDrag() { const that = this; const dragPointer = document.getElementById('drag-resize-pointer'); - function mousemove(e) - { + function mousemove(e) { const mouseX = e.x; const dragSideWidth = mouseX - 17; @@ -78,8 +84,7 @@ export default { } } - function mouseup(e) - { + function mouseup(e) { document.documentElement.removeEventListener('mousemove', mousemove); document.documentElement.removeEventListener('mouseup', mouseup); @@ -95,13 +100,13 @@ export default { }); }, restoreSideBarWidth() { - let sideWidth = localStorage.sideWidth; + const { sideWidth } = localStorage; sideWidth && (this.sideWidth = sideWidth); }, openHrefInBrowser() { - const shell = require('electron').shell; + const { shell } = require('electron'); - document.addEventListener('click', function (event) { + document.addEventListener('click', (event) => { const ele = event.target; if (ele && (ele.nodeName.toLowerCase() === 'a') && ele.href.startsWith('http')) { @@ -123,9 +128,9 @@ export default { }, initZoom() { let zoomFactor = this.$storage.getSetting('zoomFactor'); - zoomFactor = zoomFactor ? zoomFactor : 1.0; + zoomFactor = zoomFactor || 1.0; - const {webFrame} = require('electron'); + const { webFrame } = require('electron'); webFrame.setZoomFactor(zoomFactor); }, loadCustomCss() { @@ -151,6 +156,7 @@ export default { html { height: 100%; } + body { height: 100%; padding: 8px; @@ -165,11 +171,11 @@ body { button, input, textarea, .vjs__tree { font-family: inherit !important; } + a { color: #8e8d8d; } - /*fix el-select bottom scroll bar*/ .el-scrollbar__wrap { overflow-x: hidden; @@ -179,36 +185,45 @@ a { ::-webkit-scrollbar { width: 9px; } + /*track*/ ::-webkit-scrollbar-track { background: #eaeaea; border-radius: 4px; } + .dark-mode ::-webkit-scrollbar-track { background: #425057; } + /*track hover*/ ::-webkit-scrollbar-track:hover { background: #e0e0dd; } + .dark-mode ::-webkit-scrollbar-track:hover { background: #495961; } + /*thumb*/ ::-webkit-scrollbar-thumb { border-radius: 8px; background: #c1c1c1; } + .dark-mode ::-webkit-scrollbar-thumb { background: #5a6f7a; } + /*thumb hover*/ ::-webkit-scrollbar-thumb:hover { background: #7f7f7f; } + .dark-mode ::-webkit-scrollbar-thumb:hover { background: #6a838f; } + /*scrollbar style end*/ /*list index*/ @@ -219,6 +234,7 @@ li .list-index { margin-right: 10px; min-width: 28px; } + .dark-mode li .list-index { color: #adacac; } @@ -226,21 +242,25 @@ li .list-index { .wrap-container { height: 100%; } + .aside-drag-container { position: relative; user-select: none; /*max-width: 50%;*/ } + .aside-connection { height: 100%; width: 100% !important; border-right: 1px solid #e4e0e0; overflow: hidden; } + /*fix right container imdraggable*/ .right-main-container { width: 10%; } + .right-main-container .main-tabs-container { overflow-y: hidden; padding-top: 0px; @@ -260,12 +280,14 @@ li .list-index { right: -12px; top: 0px; } + #drag-resize-pointer { position: fixed; height: 100%; width: 10px; cursor: col-resize; } + #drag-resize-pointer::after { content: ""; display: inline-block; @@ -280,12 +302,15 @@ li .list-index { bottom: 0; margin: auto; } + .dark-mode #drag-resize-pointer::after { border-left: 1px solid #b9b8b8; border-right: 1px solid #b9b8b8; } @keyframes rotate { - to{ transform: rotate(360deg); } + to { + transform: rotate(360deg); + } } diff --git a/src/components/TitleBar.vue b/src/components/TitleBar.vue new file mode 100644 index 000000000..a63479806 --- /dev/null +++ b/src/components/TitleBar.vue @@ -0,0 +1,110 @@ + + +