This commit is contained in:
retoor 2025-05-15 19:32:40 +02:00
parent db6d6c0106
commit 25d109beed
5 changed files with 55 additions and 19 deletions

View File

@ -1,6 +1,6 @@
from snek.model.user import UserModel from snek.model.user import UserModel
from snek.system.model import BaseModel, ModelField from snek.system.model import BaseModel, ModelField
from datetime import datetime,timezone
class ChannelMessageModel(BaseModel): class ChannelMessageModel(BaseModel):
channel_uid = ModelField(name="channel_uid", required=True, kind=str) channel_uid = ModelField(name="channel_uid", required=True, kind=str)
@ -8,6 +8,9 @@ class ChannelMessageModel(BaseModel):
message = ModelField(name="message", required=True, kind=str) message = ModelField(name="message", required=True, kind=str)
html = ModelField(name="html", required=False, kind=str) html = ModelField(name="html", required=False, kind=str)
def get_seconds_since_last_update(self):
return int((datetime.now(timezone.utc) - datetime.fromisoformat(self["updated_at"])).total_seconds())
async def get_user(self) -> UserModel: async def get_user(self) -> UserModel:
return await self.app.services.user.get(uid=self["user_uid"]) return await self.app.services.user.get(uid=self["user_uid"])

View File

@ -151,7 +151,7 @@ footer {
} }
} }
.chat-messages > picture > img { .chat-messages picture img {
cursor: pointer; cursor: pointer;
} }
.chat-messages::-webkit-scrollbar { .chat-messages::-webkit-scrollbar {

View File

@ -10,7 +10,7 @@
constructor() { constructor() {
super(); super();
app.ws.addEventListener("update_message_text",(data)=>{ app.ws.addEventListener("update_message_text",(data)=>{
this.updateMessageText(data.data.message_uid,data.data.text) this.updateMessageText(data.data.uid,data.data)
}) })
app.ws.addEventListener("set_typing",(data)=>{ app.ws.addEventListener("set_typing",(data)=>{
this.triggerGlow(data.data.user_uid) this.triggerGlow(data.data.user_uid)
@ -19,14 +19,18 @@
this.items = []; this.items = [];
} }
updateMessageText(uid,text){ updateMessageText(uid,message){
const messageDiv = this.querySelector("div[data-uid=\""+uid+"\"]") const messageDiv = this.querySelector("div[data-uid=\""+uid+"\"]")
if(!messageDiv){ if(!messageDiv){
return return
} }
const receivedHtml = document.createElement("div")
receivedHtml.innerHTML = message.html
const html = receivedHtml.querySelector(".text").innerHTML
const textElement = messageDiv.querySelector(".text") const textElement = messageDiv.querySelector(".text")
textElement.innerText = text textElement.innerHTML = html
textElement.style.display = text == '' ? 'none' : 'block' textElement.style.display = message.text == '' ? 'none' : 'block'
} }
triggerGlow(uid) { triggerGlow(uid) {

View File

@ -47,7 +47,18 @@
if(textBox.liveType == undefined){ if(textBox.liveType == undefined){
textBox.liveType = false textBox.liveType = false
} }
let typeTimeout = null;
textBox.addEventListener('keydown',async (e) => { textBox.addEventListener('keydown',async (e) => {
if(typeTimeout){
clearTimeout(typeTimeout)
typeTimeout = null
}
if(e.target.liveType){
typeTimeout = setTimeout(()=>{
e.target.lastMessageUid = null
e.target.value = ''
},3000)
}
if(e.key === "ArrowUp"){ if(e.key === "ArrowUp"){
const value = findDivAboveText(e.target.value).querySelector('.text') const value = findDivAboveText(e.target.value).querySelector('.text')
e.target.value = value.textContent e.target.value = value.textContent
@ -102,7 +113,9 @@
}else{ }else{
if(textBox.liveType){ if(textBox.liveType){
if(e.target.value.endsWith("\n") || e.target.value.endsWith(" ")){
return
}
if(e.target.value[0] == "/"){ if(e.target.value[0] == "/"){
return return
} }
@ -116,8 +129,10 @@
return; return;
} }
app.rpc.updateMessageText(textBox.lastMessageUid, e.target.value) app.rpc.updateMessageText(textBox.lastMessageUid, e.target.value)
}else{
app.rpc.set_typing(channelUid)
} }
app.rpc.set_typing(channelUid)
} }
}); });
@ -294,6 +309,10 @@
} }
app.addEventListener("channel-message", (data) => { app.addEventListener("channel-message", (data) => {
let display = 'block';
if(!data.text || !data.text.trim()){
display = "none";
}
if (data.channel_uid !== channelUid) { if (data.channel_uid !== channelUid) {
if(!isMentionForSomeoneElse(data.message)){ if(!isMentionForSomeoneElse(data.message)){
channelSidebar.notify(data); channelSidebar.notify(data);
@ -316,6 +335,7 @@
const message = document.createElement("div"); const message = document.createElement("div");
message.innerHTML = data.html; message.innerHTML = data.html;
message.style.display = display
document.querySelector(".chat-messages").appendChild(message.firstChild); document.querySelector(".chat-messages").appendChild(message.firstChild);
updateLayout(doScrollDownBecauseLastMessageIsVisible); updateLayout(doScrollDownBecauseLastMessageIsVisible);
setTimeout(() => { setTimeout(() => {
@ -373,6 +393,9 @@
if(e.target.tagName != 'IMG') if(e.target.tagName != 'IMG')
return return
const img = e.target const img = e.target
if(e.target.classList.contains('avatar')){
return
}
const overlay = document.createElement('div'); const overlay = document.createElement('div');
overlay.style.position = 'fixed'; overlay.style.position = 'fixed';
overlay.style.top = 0; overlay.style.top = 0;

View File

@ -178,22 +178,28 @@ class RPCView(BaseView):
message = await self.services.channel_message.get(message_uid) message = await self.services.channel_message.get(message_uid)
if message["user_uid"] != self.user_uid: if message["user_uid"] != self.user_uid:
raise Exception("Not allowed") raise Exception("Not allowed")
await self.services.socket.broadcast(message["channel_uid"], {
"channel_uid": message["channel_uid"],
"event": "update_message_text",
"data": {
"message_uid": message_uid, if message.get_seconds_since_last_update() > 3:
"text": text return {"error": "Message too old","seconds_since_last_update": message.get_seconds_since_last_update(),"success": False}
}
}) message['message'] = text
message["message"] = text
if not text: if not text:
message['deleted_at'] = now() message['deleted_at'] = now()
else: else:
message['deleted_at'] = None message['deleted_at'] = None
await self.services.channel_message.save(message) await self.services.channel_message.save(message)
return True data = message.record
data['text'] = message["message"]
data['message_uid'] = message_uid
await self.services.socket.broadcast(message["channel_uid"], {
"channel_uid": message["channel_uid"],
"event": "update_message_text",
"data": message.record
})
return {"success": True}
async def send_message(self, channel_uid, message): async def send_message(self, channel_uid, message):
self._require_login() self._require_login()