From aedab1737511b93d09778081a89a136b86cdd024 Mon Sep 17 00:00:00 2001 From: Aitchessbee Date: Wed, 13 Mar 2024 19:02:55 +0530 Subject: [PATCH 1/2] left sidebar: added ordering feature for server tabs, fixes #548 --- app/renderer/css/main.css | 4 ++++ app/renderer/js/main.ts | 19 ++++++++++++++++++- app/renderer/js/utils/domain-util.ts | 14 ++++++++++++++ package-lock.json | 14 +++++++++++++- package.json | 4 +++- 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/app/renderer/css/main.css b/app/renderer/css/main.css index 0898191f5..6b9b5aa50 100644 --- a/app/renderer/css/main.css +++ b/app/renderer/css/main.css @@ -419,6 +419,10 @@ webview.focus { left: -5px; } +.sortable-chosen .server-tooltip { + display: none; +} + #collapse-button { bottom: 30px; left: 20px; diff --git a/app/renderer/js/main.ts b/app/renderer/js/main.ts index 7b4abce90..ff0cdffe2 100644 --- a/app/renderer/js/main.ts +++ b/app/renderer/js/main.ts @@ -6,6 +6,7 @@ import url from "node:url"; import {Menu, app, dialog, session} from "@electron/remote"; import * as remote from "@electron/remote"; import * as Sentry from "@sentry/electron/renderer"; +import SortableJS from "sortablejs"; import type {Config} from "../../common/config-util.js"; import * as ConfigUtil from "../../common/config-util.js"; @@ -57,7 +58,7 @@ const dingSound = new Audio( export class ServerManagerView { $addServerButton: HTMLButtonElement; - $tabsContainer: Element; + $tabsContainer: HTMLElement; $reloadButton: HTMLButtonElement; $loadingIndicator: HTMLButtonElement; $settingsButton: HTMLButtonElement; @@ -81,6 +82,7 @@ export class ServerManagerView { tabIndex: number; presetOrgs: string[]; preferenceView?: PreferenceView; + sortableSidebar: SortableJS | null; constructor() { this.$addServerButton = document.querySelector("#add-tab")!; this.$tabsContainer = document.querySelector("#tabs-container")!; @@ -123,6 +125,7 @@ export class ServerManagerView { this.presetOrgs = []; this.functionalTabs = new Map(); this.tabIndex = 0; + this.sortableSidebar = null; } async init(): Promise { @@ -235,6 +238,20 @@ export class ServerManagerView { initSidebar(): void { const showSidebar = ConfigUtil.getConfigItem("showSidebar", true); this.toggleSidebar(showSidebar); + this.sortableSidebar = new SortableJS(this.$tabsContainer, { + animation: 150, + onEnd: (event: SortableJS.SortableEvent) => { + // Update the domain order in the database + DomainUtil.updateDomainOrder(event.oldIndex ?? 0, event.newIndex ?? 0); + + // Update the current active tab index + this.activeTabIndex = event.newIndex ?? 0; + ConfigUtil.setConfigItem("lastActiveTab", event.newIndex ?? 0); + + // Reload the app to give the tabs their new indexes + ipcRenderer.send("reload-full-app"); + }, + }); } // Remove the stale UA string from the disk if the app is not freshly diff --git a/app/renderer/js/utils/domain-util.ts b/app/renderer/js/utils/domain-util.ts index 465bb3b55..bdded99a4 100644 --- a/app/renderer/js/utils/domain-util.ts +++ b/app/renderer/js/utils/domain-util.ts @@ -72,6 +72,20 @@ export function updateDomain(index: number, server: ServerConf): void { db.push(`/domains[${index}]`, server, true); } +export function updateDomainOrder(oldIndex: number, newIndex: number) { + const domains = serverConfSchema + .array() + .parse(db.getObject("/domains")); + + const [movedDomain] = domains.splice(oldIndex, 1); + domains.splice(newIndex, 0, movedDomain); + + // Update each domain in the database with its new order + for (const [index, domain] of domains.entries()) { + updateDomain(index, domain); + } +} + export async function addDomain(server: { url: string; alias: string; diff --git a/package-lock.json b/package-lock.json index 80cd10cd0..fc714eb5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,9 @@ "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "gatemaker": "https://github.com/andersk/gatemaker/archive/d31890ae1cb293faabcb1e4e465c673458f6eed2.tar.gz" + "@types/sortablejs": "^1.15.8", + "gatemaker": "https://github.com/andersk/gatemaker/archive/d31890ae1cb293faabcb1e4e465c673458f6eed2.tar.gz", + "sortablejs": "^1.15.2" }, "devDependencies": { "@electron/remote": "^2.0.8", @@ -2207,6 +2209,11 @@ "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, + "node_modules/@types/sortablejs": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.8.tgz", + "integrity": "sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==" + }, "node_modules/@types/verror": { "version": "1.10.9", "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.9.tgz", @@ -9508,6 +9515,11 @@ "npm": ">= 3.0.0" } }, + "node_modules/sortablejs": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.2.tgz", + "integrity": "sha512-FJF5jgdfvoKn1MAKSdGs33bIqLi3LmsgVTliuX6iITj834F+JRQZN90Z93yql8h0K2t0RwDPBmxwlbZfDcxNZA==" + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", diff --git a/package.json b/package.json index 6076f3a4c..214150d65 100644 --- a/package.json +++ b/package.json @@ -143,7 +143,9 @@ "InstantMessaging" ], "dependencies": { - "gatemaker": "https://github.com/andersk/gatemaker/archive/d31890ae1cb293faabcb1e4e465c673458f6eed2.tar.gz" + "@types/sortablejs": "^1.15.8", + "gatemaker": "https://github.com/andersk/gatemaker/archive/d31890ae1cb293faabcb1e4e465c673458f6eed2.tar.gz", + "sortablejs": "^1.15.2" }, "devDependencies": { "@electron/remote": "^2.0.8", From 64e827ae443a6b845e01431a1f700f7a8a016380 Mon Sep 17 00:00:00 2001 From: Aitchessbee Date: Mon, 25 Mar 2024 00:51:27 +0530 Subject: [PATCH 2/2] fixed overflow, redundant db calls, package.json --- app/renderer/css/main.css | 2 +- app/renderer/js/main.ts | 24 ++++++++++++++++-------- app/renderer/js/utils/domain-util.ts | 28 +++++++++++++++++----------- package-lock.json | 6 +++--- package.json | 6 +++--- 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/app/renderer/css/main.css b/app/renderer/css/main.css index 6b9b5aa50..02cd873cb 100644 --- a/app/renderer/css/main.css +++ b/app/renderer/css/main.css @@ -45,7 +45,7 @@ body { #view-controls-container { height: calc(100% - 208px); scrollbar-gutter: stable both-edges; - overflow-y: hidden; + overflow: hidden; } #view-controls-container::-webkit-scrollbar { diff --git a/app/renderer/js/main.ts b/app/renderer/js/main.ts index ff0cdffe2..2c32a1ae6 100644 --- a/app/renderer/js/main.ts +++ b/app/renderer/js/main.ts @@ -82,7 +82,7 @@ export class ServerManagerView { tabIndex: number; presetOrgs: string[]; preferenceView?: PreferenceView; - sortableSidebar: SortableJS | null; + sortableSidebar?: SortableJS; constructor() { this.$addServerButton = document.querySelector("#add-tab")!; this.$tabsContainer = document.querySelector("#tabs-container")!; @@ -125,7 +125,6 @@ export class ServerManagerView { this.presetOrgs = []; this.functionalTabs = new Map(); this.tabIndex = 0; - this.sortableSidebar = null; } async init(): Promise { @@ -242,14 +241,23 @@ export class ServerManagerView { animation: 150, onEnd: (event: SortableJS.SortableEvent) => { // Update the domain order in the database - DomainUtil.updateDomainOrder(event.oldIndex ?? 0, event.newIndex ?? 0); + if ( + event.oldIndex !== null && + event.newIndex !== null && + event.oldIndex !== event.newIndex + ) { + DomainUtil.updateDomainOrder( + event.oldIndex ?? 0, + event.newIndex ?? 0, + ); - // Update the current active tab index - this.activeTabIndex = event.newIndex ?? 0; - ConfigUtil.setConfigItem("lastActiveTab", event.newIndex ?? 0); + // Update the current active tab index + this.activeTabIndex = event.newIndex ?? 0; + ConfigUtil.setConfigItem("lastActiveTab", event.newIndex ?? 0); - // Reload the app to give the tabs their new indexes - ipcRenderer.send("reload-full-app"); + // Reload the app to give the tabs their new indexes + ipcRenderer.send("reload-full-app"); + } }, }); } diff --git a/app/renderer/js/utils/domain-util.ts b/app/renderer/js/utils/domain-util.ts index bdded99a4..73a394045 100644 --- a/app/renderer/js/utils/domain-util.ts +++ b/app/renderer/js/utils/domain-util.ts @@ -72,17 +72,23 @@ export function updateDomain(index: number, server: ServerConf): void { db.push(`/domains[${index}]`, server, true); } -export function updateDomainOrder(oldIndex: number, newIndex: number) { - const domains = serverConfSchema - .array() - .parse(db.getObject("/domains")); - - const [movedDomain] = domains.splice(oldIndex, 1); - domains.splice(newIndex, 0, movedDomain); - - // Update each domain in the database with its new order - for (const [index, domain] of domains.entries()) { - updateDomain(index, domain); +export function updateDomainOrder(oldIndex: number, newIndex: number): void { + const domains = getDomains(); + + if ( + !( + oldIndex < 0 || + oldIndex >= domains.length || + newIndex < 0 || + newIndex >= domains.length + ) + ) { + const [movedDomain] = domains.splice(oldIndex, 1); + domains.splice(newIndex, 0, movedDomain); + + for (const [index, domain] of domains.entries()) { + updateDomain(index, domain); + } } } diff --git a/package-lock.json b/package-lock.json index fc714eb5a..14e219b9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,7 @@ "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@types/sortablejs": "^1.15.8", - "gatemaker": "https://github.com/andersk/gatemaker/archive/d31890ae1cb293faabcb1e4e465c673458f6eed2.tar.gz", - "sortablejs": "^1.15.2" + "gatemaker": "https://github.com/andersk/gatemaker/archive/d31890ae1cb293faabcb1e4e465c673458f6eed2.tar.gz" }, "devDependencies": { "@electron/remote": "^2.0.8", @@ -24,6 +22,7 @@ "@types/i18n": "^0.13.1", "@types/node": "~18.17.19", "@types/requestidlecallback": "^0.3.4", + "@types/sortablejs": "^1.15.8", "@types/yaireo__tagify": "^4.3.2", "@yaireo/tagify": "^4.5.0", "adm-zip": "^0.5.5", @@ -45,6 +44,7 @@ "prettier": "^3.0.3", "rimraf": "^5.0.0", "semver": "^7.3.5", + "sortablejs": "^1.15.2", "stylelint": "^16.1.0", "stylelint-config-standard": "^36.0.0", "tape": "^5.2.2", diff --git a/package.json b/package.json index 214150d65..37a18ab5d 100644 --- a/package.json +++ b/package.json @@ -143,9 +143,7 @@ "InstantMessaging" ], "dependencies": { - "@types/sortablejs": "^1.15.8", - "gatemaker": "https://github.com/andersk/gatemaker/archive/d31890ae1cb293faabcb1e4e465c673458f6eed2.tar.gz", - "sortablejs": "^1.15.2" + "gatemaker": "https://github.com/andersk/gatemaker/archive/d31890ae1cb293faabcb1e4e465c673458f6eed2.tar.gz" }, "devDependencies": { "@electron/remote": "^2.0.8", @@ -157,6 +155,7 @@ "@types/i18n": "^0.13.1", "@types/node": "~18.17.19", "@types/requestidlecallback": "^0.3.4", + "@types/sortablejs": "^1.15.8", "@types/yaireo__tagify": "^4.3.2", "@yaireo/tagify": "^4.5.0", "adm-zip": "^0.5.5", @@ -178,6 +177,7 @@ "prettier": "^3.0.3", "rimraf": "^5.0.0", "semver": "^7.3.5", + "sortablejs": "^1.15.2", "stylelint": "^16.1.0", "stylelint-config-standard": "^36.0.0", "tape": "^5.2.2",