diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 885e6c9..d366e6f 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -20,7 +20,7 @@ import { threadMember, threadMetadata, } from "./jsontypes.js"; -import {MarkDown} from "./markdown.js"; +import {MarkDown, saveCaretPosition} from "./markdown.js"; import {Member} from "./member.js"; import {Voice} from "./voice.js"; import {User} from "./user.js"; @@ -2225,9 +2225,12 @@ class Channel extends SnowFlake { const container = document.createElement("div"); container.classList.add("messagecontainer", "flexttb", "forumBody"); (document.getElementById("scrollWrap") as HTMLElement).append(container); + const superContainer = document.createElement("div"); + superContainer.classList.add("forumHead", "flexttb"); const headContainer = document.createElement("div"); - headContainer.classList.add("flexltr", "forumHead"); - container.append(headContainer); + superContainer.append(headContainer); + headContainer.classList.add("flexltr"); + container.append(superContainer); const icon = document.createElement("span"); icon.classList.add("svgicon", "svg-search", "forumIcon"); @@ -2239,6 +2242,90 @@ class Channel extends SnowFlake { headContainer.append(text); text.placeholder = I18n.forum.creorsear(); + const post = document.createElement("button"); + post.textContent = I18n.forum.newPost(); + post.classList.add("newPostForumButton"); + headContainer.append(post); + + post.onclick = () => { + const postF = async () => { + const res = (await ( + await fetch(this.info.api + "/channels/" + this.id + "/threads", { + method: "POST", + headers: this.headers, + body: JSON.stringify({ + name: text.value, + applied_tags: tagList, + message: { + content: md.rawString, + }, + }), + }) + ).json()) as channeljson; + this.localuser.goToChannel(res.id); + }; + post.onclick = postF; + post.textContent = I18n.forum.post(); + const box = document.createElement("div"); + box.classList.add("messageEditContainer"); + const area = document.createElement("div"); + const sb = document.createElement("div"); + sb.style.position = "absolute"; + sb.style.width = "100%"; + const search = document.createElement("div"); + search.classList.add("searchOptions", "flexttb"); + area.classList.add("editMessage"); + try { + area.contentEditable = "plaintext-only"; + } catch { + area.contentEditable = "true"; + } + const md = new MarkDown("", this, {keep: true}); + area.append(md.makeHTML()); + area.addEventListener("keyup", (event) => { + if (this.localuser.keyup(event)) return; + }); + area.addEventListener("keydown", (event) => { + this.localuser.keydown(event); + }); + md.giveBox(area, (str, pre) => { + this.localuser.search(search, md, str, pre); + }); + sb.append(search); + box.append(sb, area); + superContainer.append(box); + setTimeout(() => { + area.focus(); + const fun = saveCaretPosition(area, Infinity); + if (fun) fun(); + }); + box.oncontextmenu = (e) => { + e.stopImmediatePropagation(); + }; + + let tagList: string[] = []; + + const tags = document.createElement("div"); + tags.classList.add("forumTagSelect"); + for (const tag of this.availableTags.filter( + (tag) => !tag.moderated || this.hasPermission("MANAGE_THREADS"), + )) { + const html = tag.makeHTML(); + html.onclick = () => { + if (tagList.includes(tag.id)) { + tagList = tagList.filter((id) => id !== tag.id); + html.classList.remove("selected"); + } else { + tagList.push(tag.id); + tagList.sort(); + html.classList.add("selected"); + } + }; + tags.append(html); + } + superContainer.append(tags); + }; + const theadList = document.createElement("div"); theadList.classList.add("flexttb", "forumList"); container.append(theadList); diff --git a/src/webpage/jsontypes.ts b/src/webpage/jsontypes.ts index e656ec9..aeb40e8 100644 --- a/src/webpage/jsontypes.ts +++ b/src/webpage/jsontypes.ts @@ -860,7 +860,8 @@ type wsjson = | "GUILD_DELETE" | "GUILD_CREATE" | "MESSAGE_REACTION_REMOVE_ALL" - | "MESSAGE_REACTION_REMOVE_EMOJI"; + | "MESSAGE_REACTION_REMOVE_EMOJI" + | "THREAD_CREATE"; } | { op: 0; diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index 50abf03..844178d 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -788,6 +788,7 @@ class Localuser { } break; case "CHANNEL_CREATE": + case "THREAD_CREATE": if (this.initialized) { this.createChannel(temp.d); } diff --git a/src/webpage/style.css b/src/webpage/style.css index 4e3ee59..1bccef5 100644 --- a/src/webpage/style.css +++ b/src/webpage/style.css @@ -319,6 +319,7 @@ body { bottom: 0; width: calc(100% - 32px); box-sizing: border-box; + > span { transition: background 0.1s; margin-bottom: 0.025in; @@ -1105,10 +1106,48 @@ textarea { margin: 6px; box-sizing: border-box; border-radius: 4px; - display: flex; - align-items: center; flex: 0; - min-height: 48px; + min-height: fit-content; + height: max-content; + flex-shrink: 0; + /* overflow: clip; */ + + > .flexltr { + width: 100%; + align-items: center; + } + .editMessage { + margin-top: 6px; + } + .searchOptions { + top: 32px; + bottom: unset; + } + .forumTagSelect { + margin-top: 6px; + > * { + margin-left: 0px; + margin-right: 6px; + } + } +} +.newPostForumButton { + width: 100px; + height: 34px; + padding: 6px; + transition: + width 0.15s, + padding 0.15s; + overflow: clip; + text-overflow: clip; + white-space: nowrap; + text-align: center; +} +.forumHead:has(input:placeholder-shown) { + .newPostForumButton { + width: 0px; + padding: 0px; + } } .forumBody { height: 100%; @@ -1130,7 +1169,8 @@ textarea { flex-direction: row; flex-wrap: wrap; overflow-y: clip; - height: 26px; + min-height: fit-content; + > * { margin-left: 6px; } diff --git a/translations/en.json b/translations/en.json index a6bd6c9..4b8161f 100644 --- a/translations/en.json +++ b/translations/en.json @@ -147,6 +147,8 @@ "creorsear":"Create or search for post", "next":"Next", "back":"Back", + "newPost":"New Post", + "post":"Post", "sortOptions":{ "sortby":{ "title":"Sort By",