Forum changes

- Added 2 new svg icons
- Fixed visual styling bugs on Forum page involving overflowing containers
- Added current network name underneath "Forum" title
- Input in Forum.js now sends ws message to server with new post, which is then broadcasted through the ws
- Forum app now displays a list of posts for the current network showing the author, time, text, whether it's been edited, and whether it's yours
- ForumPanel.js .onClick() contains the ws calls for DELETE and PUT
- Fixed bug where Forum would not scroll to top upon a new post/onAppear
- Modified ws GET call in ForumPanel.js to reflect new format
- Added .onEvent() handlers inForumPanel.js for "new-post", "deleted-post", and "edited-post"
- Changed AppMenu People icon
-
This commit is contained in:
2026-02-08 22:44:19 -05:00
parent 3bf23daa7a
commit 770d3bb012
6 changed files with 187 additions and 37 deletions

View File

@@ -29,18 +29,24 @@ css(`
`)
class Forum extends Shadow {
selectedForum = "HY"
render() {
ZStack(() => {
VStack(() => {
h1("Forum")
.color("var(--quillred)")
.textAlign("center")
.marginBottom(0)
h3(global.currentNetwork.name)
.color("var(--quillred)")
.textAlign("center")
.margin(0)
ForumPanel()
input("Message", "70%")
.paddingVertical(0.75, em)
.paddingLeft(2, em)
.boxSizing("border-box")
.paddingHorizontal(2, em)
.color("var(--accent)")
.background("#fff1dd")
.marginBottom(5.5, em)
@@ -48,9 +54,17 @@ class Forum extends Shadow {
.borderRadius(100, px)
.fontFamily("Arial")
.fontSize(1, em)
.onKeyDown(function (e) {
.onKeyDown(async function(e) {
if (e.key === "Enter") {
window.Socket.send({app: "FORUM", operation: "SEND", msg: {forum: "HY", text: this.value }})
let msg = {
forum: global.currentNetwork.abbreviation,
text: this.value
}
await global.Socket.send({
app: "FORUM",
operation: "SEND",
msg: msg
})
this.value = ""
}
})
@@ -61,11 +75,14 @@ class Forum extends Shadow {
.height(100, pct)
.horizontalAlign("center")
.verticalAlign("end")
.minHeight(0)
})
.backgroundColor("var(--main)")
.boxSizing("border-box")
.paddingVertical(1, em)
.width(100, pct)
.height(100, pct)
.minHeight(0)
.flex("1 1 auto")
}

View File

@@ -1,19 +1,38 @@
import "../../components/LoadingCircle.js"
css(`
forumpanel- {
scrollbar-width: none;
-ms-overflow-style: none;
}
forumpanel-::-webkit-scrollbar {
display: none;
width: 0px;
height: 0px;
}
forumpanel-::-webkit-scrollbar-thumb {
background: transparent;
}
forumpanel-::-webkit-scrollbar-track {
background: transparent;
}
`)
class ForumPanel extends Shadow {
forums = [
"HY"
]
messages = []
isSending = false
render() {
VStack(() => {
if(this.messages.length > 0) {
let previousDate = null
for(let i=0; i<this.messages.length; i++) {
let message = this.messages[i]
const isMe = message.authorId === global.profile.id
const dateParts = this.parseDate(message.time);
const { date, time } = dateParts;
@@ -22,22 +41,64 @@ class ForumPanel extends Shadow {
p(date)
.textAlign("center")
.opacity(0.5)
.marginVertical(1, em)
.color("var(--divider)")
.opacity(0.6)
.fontWeight("bold")
.paddingTop(1, em)
.paddingBottom(0.5, em)
.color("var(--quillred)")
.borderTop(`1px solid var(--${i == 0 ? "transparent" : "divider"})`)
}
VStack(() => {
HStack(() => {
p(message.sentBy)
.fontWeight("bold")
.marginBottom(0.3, em)
h3(isMe ? "Me" : message.sentBy)
.color(isMe ? "var(--quillred)" : "var(--brown")
.margin(0)
p(util.formatTime(message.time))
.opacity(0.2)
.marginLeft(1, em)
h3(`${date} ${time}`)
.opacity(0.5)
.color("var(--brown)")
.margin(0)
.marginLeft(0.5, em)
.fontSize(1, em)
if (message.edited) {
p("(edited)")
.color("var(--brown)")
.letterSpacing(0.8, "px")
.opacity(0.8)
.fontWeight("bold")
.paddingLeft(0.25, em)
.fontSize(0.9, em)
}
})
.verticalAlign("center")
.marginBottom(0.1, em)
p(message.text)
.color("var(--accent)")
.borderLeft("1.5px solid var(--divider)")
.borderBottomLeftRadius("7.5px")
.paddingLeft(0.5, em)
.marginHorizontal(0.2, em)
.paddingVertical(0.2, em)
.boxSizing("border-box")
})
.marginBottom(0.05, em)
.onClick(async (finished, e) => {
if (finished) {
console.log(message.id)
let msg = {
forum: global.currentNetwork.abbreviation,
id: message.id,
text: "EDITED TEXT TEST!"
}
await global.Socket.send({
app: "FORUM",
operation: "PUT",
msg: msg
})
}
})
}
} else {
@@ -45,31 +106,68 @@ class ForumPanel extends Shadow {
}
})
.gap(1, em)
.fontSize(1.1, em)
.boxSizing("border-box")
.position("relative")
.overflow("scroll")
.height(100, pct)
.width(96, pct)
.paddingTop(5, em)
.flex("1 1 auto")
.minHeight(0)
.overflowY("auto")
.width(100, pct)
.paddingBottom(2, em)
.paddingLeft(4, pct)
.paddingHorizontal(4, pct)
.backgroundColor("var(--main)")
.onAppear(async () => {
requestAnimationFrame(() => {
this.scrollTop = this.scrollHeight
this.scrollTo({ top: 0, behavior: "smooth" });
});
let res = await global.Socket.send({app: "FORUM", operation: "GET", msg: {forum: "HY", number: 100}})
if(!res) console.error("failed to get messages")
if(res.msg.length > 0 && this.messages.length === 0) {
this.messages = res.msg
this.rerender()
}
window.addEventListener("new-post", (e) => {
this.messages = e.detail
if(e.detail.length !== this.messages || e.detail.last.time !== this.messages.last.time || e.detail.first.time !== this.messages.first.time) {
if (!this.isSending) {
this.isSending = true
let res = await global.Socket.send({
app: "FORUM",
operation: "GET",
msg: {
forum: global.currentNetwork.abbreviation,
by: "network",
authorId: -999 // default
}
})
if(!res) console.error("failed to get messages")
if(res.msg.length > 0 && this.messages.length === 0) {
this.messages = res.msg.reverse()
this.rerender()
}
})
this.isSending = false
}
})
.onEvent("new-post", this.onNewPost)
.onEvent("deleted-post", this.onDeletedPost)
.onEvent("edited-post", this.onEditedPost)
}
onNewPost = (e) => {
let newPost = e.detail
if (this.messages && !this.messages.some(post => post.id === newPost.id)) {
this.messages.unshift(newPost)
this.rerender()
}
}
onDeletedPost = (e) => {
let deletedId = e.detail
const i = this.messages.findIndex(post => post.id === deletedId)
if (i !== -1) this.messages.splice(i, 1);
this.rerender()
}
onEditedPost = (e) => {
let editedPost = e.detail
const i = this.messages.findIndex(post => post.id === editedPost.id)
if (i !== -1) {
this.messages.splice(i, 1)
this.messages.unshift(editedPost)
}
this.rerender()
}
parseDate(str) {
@@ -83,6 +181,14 @@ class ForumPanel extends Shadow {
return { date, time };
}
formatTime(str) {
const match = str.match(/-(\d+:\d+):\d+.*(am|pm)/i);
if (!match) return null;
const [_, hourMin, ampm] = match;
return hourMin + ampm.toLowerCase();
}
}
register(ForumPanel)