diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 4a97edc..6883d55 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -330,6 +330,7 @@ class Channel extends SnowFlake { this.readbottom.bind(this), ); } + last_pin_timestamp?: string; constructor(json: channeljson | -1, owner: Guild, id: string = json === -1 ? "" : json.id) { super(id); if (json === -1) { @@ -401,6 +402,61 @@ class Channel extends SnowFlake { get info() { return this.owner.info; } + pinnedMessages?: Message[]; + async pinnedClick(rect: DOMRect) { + const div = document.createElement("div"); + div.classList.add("flexttb", "pinnedMessages"); + div.style.top = rect.bottom + 20 + "px"; + div.style.right = window.innerWidth - rect.right + "px"; + document.body.append(div); + Contextmenu.keepOnScreen(div); + if (Contextmenu.currentmenu !== "") { + Contextmenu.currentmenu.remove(); + } + this.last_pin_timestamp = this.lastpin; + const l = (e: MouseEvent) => { + if (e.target instanceof HTMLElement && div.contains(e.target)) { + return; + } + div.remove(); + document.removeEventListener("click", l); + }; + document.addEventListener("mouseup", l); + if (!this.pinnedMessages) { + const pinnedM = (await ( + await fetch(`${this.info.api}/channels/${this.id}/pins`, {headers: this.headers}) + ).json()) as messagejson[]; + this.pinnedMessages = pinnedM.map((_) => { + if (this.messages.has(_.id)) { + return this.messages.get(_.id) as Message; + } else { + return new Message(_, this); + } + }); + } + const pinnedM = document.getElementById("pinnedMDiv"); + if (pinnedM) { + pinnedM.classList.remove("unreadPin"); + } + if (this.pinnedMessages.length === 0) { + const b = document.createElement("b"); + b.textContent = I18n.noPins(); + div.append(b); + return; + } + div.append( + ...this.pinnedMessages.map((_) => { + const html = _.buildhtml(undefined, true); + html.style.cursor = "pointer"; + html.onclick = async () => { + div.remove(); + await this.focus(_.id); + }; + Message.contextmenu.bindContextmenu(html, _); + return html; + }), + ); + } readStateInfo(json: readyjson["d"]["read_state"]["entries"][0]) { const next = this.messages.get(this.idToNext.get(this.lastreadmessageid as string) as string); this.lastreadmessageid = json.last_message_id; @@ -927,7 +983,19 @@ class Channel extends SnowFlake { html.classList.add("messagecontainer"); messages.append(html); } + unreadPins() { + if (!this.last_pin_timestamp && !this.lastpin) return false; + return this.last_pin_timestamp !== this.lastpin; + } async getHTML(addstate = true) { + const pinnedM = document.getElementById("pinnedMDiv"); + if (pinnedM) { + if (this.unreadPins()) { + pinnedM.classList.add("unreadPin"); + } else { + pinnedM.classList.remove("unreadPin"); + } + } const ghostMessages = document.getElementById("ghostMessages") as HTMLElement; ghostMessages.innerHTML = ""; for (const thing of this.fakeMessages) { diff --git a/src/webpage/direct.ts b/src/webpage/direct.ts index 797b24e..b7be973 100644 --- a/src/webpage/direct.ts +++ b/src/webpage/direct.ts @@ -429,6 +429,14 @@ class Group extends Channel { return div; } async getHTML(addstate = true) { + const pinnedM = document.getElementById("pinnedMDiv"); + if (pinnedM) { + if (this.unreadPins()) { + pinnedM.classList.add("unreadPin"); + } else { + pinnedM.classList.remove("unreadPin"); + } + } const ghostMessages = document.getElementById("ghostMessages") as HTMLElement; ghostMessages.innerHTML = ""; for (const thing of this.fakeMessages) { diff --git a/src/webpage/icons/pin.svg b/src/webpage/icons/pin.svg new file mode 100644 index 0000000..ea8e642 --- /dev/null +++ b/src/webpage/icons/pin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/webpage/index.html b/src/webpage/index.html index f15bb36..d07f3f3 100644 --- a/src/webpage/index.html +++ b/src/webpage/index.html @@ -74,6 +74,10 @@ Channel name +
+
+ +