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 4c207e28d..125e6b7f4 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, nativeTheme } = require('electron');
const fontManager = require('./font-manager');
+require('./custom-css-loader');
const winState = require('./win-state');
const url = require('url');
@@ -24,10 +25,10 @@ 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/'
+ + 'Submit issue to: \nhttps://github.com/qishibo/AnotherRedisDesktopManager/',
});
process.exit();
@@ -50,6 +51,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
@@ -71,7 +73,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()}`);
@@ -121,19 +123,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 {
@@ -162,8 +170,8 @@ if (process.platform === 'darwin') {
{ role: 'hideothers' },
{ role: 'unhide' },
{ type: 'separator' },
- { role: 'quit' }
- ]
+ { role: 'quit' },
+ ],
},
{ role: 'editMenu' },
// { role: 'viewMenu' },
@@ -173,8 +181,8 @@ if (process.platform === 'darwin') {
...(
(APP_ENV === 'production') ? [] : [{ role: 'toggledevtools' }]
),
- { role: 'togglefullscreen' }
- ]
+ { role: 'togglefullscreen' },
+ ],
},
// { role: 'windowMenu' },
{
@@ -186,7 +194,7 @@ if (process.platform === 'darwin') {
{ role: 'front' },
{ type: 'separator' },
// { role: 'window' }
- ]
+ ],
},
{
role: 'help',
@@ -194,12 +202,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 a864b7675..0d4322c32 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -17,6 +17,7 @@
+
@@ -30,6 +31,23 @@ import Aside from '@/Aside';
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);
+ 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',
@@ -46,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;
@@ -62,8 +84,7 @@ export default {
}
}
- function mouseup(e)
- {
+ function mouseup(e) {
document.documentElement.removeEventListener('mousemove', mousemove);
document.documentElement.removeEventListener('mouseup', mouseup);
@@ -79,9 +100,45 @@ export default {
});
},
restoreSideBarWidth() {
- let sideWidth = localStorage.sideWidth;
+ const { sideWidth } = localStorage;
sideWidth && (this.sideWidth = sideWidth);
},
+ openHrefInBrowser() {
+ const { shell } = require('electron');
+
+ document.addEventListener('click', (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 || 1.0;
+
+ const { webFrame } = require('electron');
+ webFrame.setZoomFactor(zoomFactor);
+ },
+ loadCustomCss() {
+ const customCss = this.$storage.getCustomCss();
+ if (customCss) {
+ injectStylesheet(customCss);
+ }
+ },
},
mounted() {
setTimeout(() => {
@@ -99,6 +156,7 @@ export default {
html {
height: 100%;
}
+
body {
height: 100%;
padding: 8px;
@@ -113,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;
@@ -127,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*/
@@ -167,6 +234,7 @@ li .list-index {
margin-right: 10px;
min-width: 28px;
}
+
.dark-mode li .list-index {
color: #adacac;
}
@@ -174,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;
@@ -208,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;
@@ -228,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/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 {
diff --git a/src/components/ConnectionMenu.vue b/src/components/ConnectionMenu.vue
index 82e9a59a5..818165d14 100644
--- a/src/components/ConnectionMenu.vue
+++ b/src/components/ConnectionMenu.vue
@@ -346,7 +346,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;
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;
}
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/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 @@
+
+
+
+
+
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/i18n/langs/cn.js b/src/i18n/langs/cn.js
index 93fc3fd72..97f907c5b 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: '请输入文件路径',
custom_name: '自定义名称',
},
};
diff --git a/src/i18n/langs/de.js b/src/i18n/langs/de.js
index a3c7b1a73..0ed9e6b2a 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',
custom_name: 'Benutzerdefinierter Name',
},
};
diff --git a/src/i18n/langs/en.js b/src/i18n/langs/en.js
index 26024ccbd..c0aad3748 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',
custom_name: 'Custom Name',
},
};
diff --git a/src/i18n/langs/es.js b/src/i18n/langs/es.js
index 17dabd8e6..807820be4 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',
custom_name: 'Nombre personalizado',
},
};
diff --git a/src/i18n/langs/fr.js b/src/i18n/langs/fr.js
index 425b8ff14..9c560ffe6 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',
custom_name: 'Nom d\'usage',
},
};
diff --git a/src/i18n/langs/it.js b/src/i18n/langs/it.js
index 933a265af..714e0ebe3 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',
custom_name: 'Nome personalizzato',
},
};
diff --git a/src/i18n/langs/ko.js b/src/i18n/langs/ko.js
index 459364784..af07e7b24 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: '파일 경로를 입력해주세요',
custom_name: '맞춤 이름',
},
};
diff --git a/src/i18n/langs/pt.js b/src/i18n/langs/pt.js
index 630ecbf28..d85211352 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',
custom_name: 'Nome personalizado',
},
};
diff --git a/src/i18n/langs/ru.js b/src/i18n/langs/ru.js
index 83c743125..5be882a85 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: 'Пожалуйста, введите путь к файлу',
custom_name: 'Пользовательское имя',
},
};
diff --git a/src/i18n/langs/tr.js b/src/i18n/langs/tr.js
index 1d75cd0ed..f54c180b3 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',
custom_name: 'Özel Ad',
},
};
diff --git a/src/i18n/langs/tw.js b/src/i18n/langs/tw.js
index dc49e28a0..8f1ebf861 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: '请输入文件路径',
custom_name: '自訂名稱',
},
};
diff --git a/src/i18n/langs/ua.js b/src/i18n/langs/ua.js
index b0a58487f..dbdef6781 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: 'Введіть шлях до файлу',
custom_name: 'Спеціальна назва',
},
};
diff --git a/src/storage.js b/src/storage.js
index 0d3589c8a..476be707c 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) : [];