diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 98cccab..0331c69 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -633,17 +633,28 @@ class Channel extends SnowFlake { decoration.classList.add("hiddencat"); childrendiv.style.height = "0px"; } - decdiv.onclick = () => { - if (childrendiv.style.height !== "0px") { + const handleColapse = async (animate: boolean = true) => { + if (this.perminfo.collapsed) { decoration.classList.add("hiddencat"); - this.perminfo.collapsed = true; + childrendiv.style.height = childrendiv.scrollHeight + "px"; + await new Promise((res) => setTimeout(res, 0)); childrendiv.style.height = "0px"; } else { decoration.classList.remove("hiddencat"); - this.perminfo.collapsed = false; - childrendiv.style.height = childrendiv.scrollHeight + "px"; + if (childrendiv.style.height === "0px" && animate) { + childrendiv.style.height = childrendiv.scrollHeight + "px"; + } else { + childrendiv.style.removeProperty("height"); + } } }; + const observer = new MutationObserver(handleColapse.bind(this, false)); + observer.observe(childrendiv, {childList: true, subtree: true}); + + decdiv.onclick = () => { + this.perminfo.collapsed = !this.perminfo.collapsed; + handleColapse(); + }; } else { div.classList.add("channel"); this.unreads(); @@ -786,27 +797,42 @@ class Channel extends SnowFlake { } } - coatDropDiv(div: HTMLDivElement, container: HTMLElement | boolean = false) { + coatDropDiv(div: HTMLDivElement, container: HTMLElement | false = false) { div.addEventListener("dragenter", (event) => { console.log("enter"); event.preventDefault(); }); div.addEventListener("dragover", (event) => { + const height = div.getBoundingClientRect().height; + if (event.offsetY / height < 0.5) { + div.classList.add("dragTopView"); + div.classList.remove("dragBottomView"); + } else { + div.classList.remove("dragTopView"); + div.classList.add("dragBottomView"); + } event.preventDefault(); }); - + div.addEventListener("dragleave", () => { + div.classList.remove("dragTopView"); + div.classList.remove("dragBottomView"); + }); div.addEventListener("drop", (event) => { + div.classList.remove("dragTopView"); + div.classList.remove("dragBottomView"); const that = Channel.dragged[0]; if (!that) return; event.preventDefault(); - if (container && that.type !== 4) { + const height = div.getBoundingClientRect().height; + const before = event.offsetY / height < 0.5; + if (container && that.type !== 4 && !before) { that.move_id = this.id; if (that.parent) { that.parent.children.splice(that.parent.children.indexOf(that), 1); } that.parent = this; - (container as HTMLElement).prepend(Channel.dragged[1] as HTMLDivElement); + container.prepend(Channel.dragged[1] as HTMLDivElement); this.children.unshift(that); } else { console.log(this, Channel.dragged); @@ -830,23 +856,32 @@ class Channel extends SnowFlake { for (let i = 0; i < that.parent.children.length; i++) { build.push(that.parent.children[i]); if (that.parent.children[i] === thisy) { + if (before) build.pop(); build.push(that); + if (before) build.push(thisy); } } that.parent.children = build; + console.log(build); } else { const build: Channel[] = []; for (let i = 0; i < thisy.guild.headchannels.length; i++) { build.push(thisy.guild.headchannels[i]); if (thisy.guild.headchannels[i] === thisy) { + if (before) build.pop(); build.push(that); + if (before) build.push(thisy); } } thisy.guild.headchannels = build; } if (Channel.dragged[1]) { if (this === thisy && this.type !== 4) { - div.after(Channel.dragged[1]); + if (before) { + div.before(Channel.dragged[1]); + } else { + div.after(Channel.dragged[1]); + } } else { div = div.parentElement as HTMLDivElement; if (!div) return; @@ -855,11 +890,15 @@ class Channel extends SnowFlake { console.log(div); Channel.dragged[1].remove(); - div.after(Channel.dragged[1]); + if (before) { + div.before(Channel.dragged[1]); + } else { + div.after(Channel.dragged[1]); + } } } } - this.guild.calculateReorder(); + this.guild.calculateReorder(that.id); }); return div; diff --git a/src/webpage/guild.ts b/src/webpage/guild.ts index 627de72..28d47a9 100644 --- a/src/webpage/guild.ts +++ b/src/webpage/guild.ts @@ -1149,18 +1149,19 @@ class Guild extends SnowFlake { let build = ""; for (const thing of this.headchannels) { build += thing.name + ":" + thing.position + "\n"; + console.log(thing.children); for (const thingy of thing.children) { build += " " + thingy.name + ":" + thingy.position + "\n"; } } console.log(build); } - calculateReorder() { + calculateReorder(movedId?: string) { let position = -1; const build: { id: string; position: number | undefined; - parent_id: string | undefined; + parent_id: string | undefined | null; }[] = []; for (const thing of this.headchannels) { const thisthing: { @@ -1188,6 +1189,18 @@ class Guild extends SnowFlake { } } } + const find = build.find((_) => _.id === movedId); + const channel = this.channels.find((_) => _.id === movedId); + if (!find) { + if (channel) + build.push({ + id: channel.id, + position: channel.position, + parent_id: channel.parent?.id || null, + }); + } else { + if (channel) find.parent_id = channel.parent?.id || null; + } console.log(build); this.printServers(); if (build.length === 0) { @@ -1489,6 +1502,10 @@ class Guild extends SnowFlake { this.headchannels.push(thing); } } + for (const channel of this.channels) { + channel.children = channel.children.sort((a, b) => a.position - b.position); + } + this.channels = this.channels.sort((a, b) => a.position - b.position); this.printServers(); } } diff --git a/src/webpage/role.ts b/src/webpage/role.ts index 0fb3b99..194894d 100644 --- a/src/webpage/role.ts +++ b/src/webpage/role.ts @@ -274,6 +274,9 @@ class RoleList extends Buttons { headers: this.headers, }); }, + { + visable: (role) => role.id !== role.guild.id, + }, ); return menu; } @@ -296,6 +299,7 @@ class RoleList extends Buttons { buttonRoleMap = new WeakMap(); dragged?: HTMLButtonElement; buttonDragEvents(button: HTMLButtonElement, role: Role) { + const height = 35; this.buttonRoleMap.set(button, role); button.addEventListener("dragstart", (e) => { this.dragged = button; @@ -307,23 +311,38 @@ class RoleList extends Buttons { }); button.addEventListener("dragenter", (event) => { - console.log("enter"); event.preventDefault(); return true; }); button.addEventListener("dragover", (event) => { event.preventDefault(); + if (event.offsetY / height < 0.5) { + button.classList.add("dragTopView"); + button.classList.remove("dragBottomView"); + } else { + button.classList.remove("dragTopView"); + button.classList.add("dragBottomView"); + } return true; }); + button.addEventListener("dragleave", () => { + button.classList.remove("dragTopView"); + button.classList.remove("dragBottomView"); + }); - button.addEventListener("drop", (_) => { + button.addEventListener("drop", (event) => { const role2 = this.buttonRoleMap.get(this.dragged as HTMLButtonElement); - if (!role2) return; + if (!role2 || this.dragged === button) return; const index2 = this.guild.roles.indexOf(role2); this.guild.roles.splice(index2, 1); const index = this.guild.roles.indexOf(role); - this.guild.roles.splice(index + 1, 0, role2); + if (event.offsetY / height < 0.5) { + this.guild.roles.splice(index, 0, role2); + } else { + this.guild.roles.splice(index + 1, 0, role2); + } + this.guild.recalcRoles(); console.log(role); }); diff --git a/src/webpage/style.css b/src/webpage/style.css index 44a8ac8..2241239 100644 --- a/src/webpage/style.css +++ b/src/webpage/style.css @@ -1046,6 +1046,7 @@ span.instanceStatus { display: flex; flex-direction: column; margin-bottom: 2px; + position: relative; } .channelbutton { height: 2em; @@ -1939,6 +1940,8 @@ img.bigembedimg { background: var(--secondary-bg); border-radius: 4px; box-shadow: 0 0 8px var(--shadow); + z-index: 2; + hr { width: 90%; height: 1px; @@ -2424,6 +2427,7 @@ fieldset input[type="radio"] { color: var(--primary-text-soft); border: none; transition: background 0.1s; + position: relative; } .activeSetting { background: color-mix(in srgb, var(--secondary-bg) 60%, transparent); @@ -3052,6 +3056,26 @@ img.error::after { top: 0; left: 0; } +.dragTopView::after { + content: ""; + width: 100%; + height: 4px; + border-radius: 4px; + background: var(--primary-text-soft); + top: -1px; + left: 0px; + position: absolute; +} +.dragBottomView::after { + content: ""; + width: 100%; + height: 4px; + border-radius: 4px; + background: var(--primary-text-soft); + bottom: -3px; + left: 0px; + position: absolute; +} .gifBox { img { max-width: 196px;