Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
d9a0350155
27 changed files with 615 additions and 441 deletions
|
@ -9,6 +9,7 @@ import { Localuser } from "./localuser.js";
|
|||
import { Permissions } from "./permissions.js";
|
||||
import { Settings, RoleList } from "./settings.js";
|
||||
import { Role } from "./role.js";
|
||||
import {InfiniteScroller} from "./infiniteScroller.js"
|
||||
Settings;
|
||||
declare global {
|
||||
interface NotificationOptions {
|
||||
|
@ -20,7 +21,6 @@ class Channel{
|
|||
type:number;
|
||||
owner:Guild;
|
||||
headers:Localuser["headers"];
|
||||
messages:Message[];
|
||||
name:string;
|
||||
id:string;
|
||||
parent_id:string;
|
||||
|
@ -43,6 +43,9 @@ class Channel{
|
|||
allthewayup:boolean;
|
||||
static contextmenu=new Contextmenu("channel menu");
|
||||
replyingto:Message;
|
||||
infinite:InfiniteScroller;
|
||||
idToPrev:{[key:string]:string}={};
|
||||
idToNext:{[key:string]:string}={};
|
||||
static setupcontextmenu(){
|
||||
this.contextmenu.addbutton("Copy channel id",function(){
|
||||
console.log(this)
|
||||
|
@ -82,16 +85,45 @@ class Channel{
|
|||
return order;
|
||||
})
|
||||
}
|
||||
setUpInfiniteScroller(){
|
||||
const ids:{[key:string]:Function}={};
|
||||
this.infinite=new InfiniteScroller(async function(id:string,offset:number){
|
||||
if(offset===1){
|
||||
if(this.idToPrev[id]){
|
||||
return this.idToPrev[id];
|
||||
}else{
|
||||
await this.grabmoremessages(id);
|
||||
return this.idToPrev[id];
|
||||
}
|
||||
}else{
|
||||
return this.idToNext[id];
|
||||
}
|
||||
}.bind(this),
|
||||
function(this:Channel,id:string){
|
||||
let res:Function;
|
||||
const promise=new Promise(_=>{res=_;}) as Promise<void>;
|
||||
const html=this.messageids[id].buildhtml(this.messageids[this.idToPrev[id]],promise);
|
||||
ids[id]=res;
|
||||
return html;
|
||||
}.bind(this),
|
||||
async function(id:string){
|
||||
ids[id]();
|
||||
delete ids[id];
|
||||
return true;
|
||||
}.bind(this),
|
||||
this.readbottom.bind(this)
|
||||
);
|
||||
}
|
||||
constructor(JSON,owner:Guild){
|
||||
|
||||
if(JSON===-1){
|
||||
return;
|
||||
}
|
||||
|
||||
this.editing;
|
||||
this.type=JSON.type;
|
||||
this.owner=owner;
|
||||
this.headers=this.owner.headers;
|
||||
this.messages=[];
|
||||
this.name=JSON.name;
|
||||
this.id=JSON.id;
|
||||
this.parent_id=JSON.parent_id;
|
||||
|
@ -113,6 +145,7 @@ class Channel{
|
|||
this.position=JSON.position;
|
||||
this.lastreadmessageid=null;
|
||||
this.lastmessageid=JSON.last_message_id;
|
||||
this.setUpInfiniteScroller();
|
||||
}
|
||||
isAdmin(){
|
||||
return this.guild.isAdmin();
|
||||
|
@ -495,7 +528,7 @@ class Channel{
|
|||
this.myhtml.classList.add("viewChannel")
|
||||
this.guild.prevchannel=this;
|
||||
this.localuser.channelfocus=this;
|
||||
const prom=Message.wipeChanel();
|
||||
const prom=this.infinite.delete();
|
||||
await this.putmessages();
|
||||
await prom;
|
||||
if(id!==Channel.genid){
|
||||
|
@ -509,7 +542,7 @@ class Channel{
|
|||
(document.getElementById("typebox") as HTMLInputElement).disabled=!this.canMessage;
|
||||
}
|
||||
async putmessages(){
|
||||
if(this.messages.length>=100||this.allthewayup){return};
|
||||
if(this.allthewayup){return};
|
||||
const j=await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?limit=100",{
|
||||
headers: this.headers,
|
||||
})
|
||||
|
@ -517,11 +550,16 @@ class Channel{
|
|||
if(response.length!==100){
|
||||
this.allthewayup=true;
|
||||
}
|
||||
let prev=undefined;
|
||||
for(const thing of response){
|
||||
const messager=new Message(thing,this)
|
||||
if(this.messageids[messager.id]===undefined){
|
||||
this.messageids[messager.id]=messager;
|
||||
this.messages.push(messager);
|
||||
const message=new Message(thing,this);
|
||||
if(prev){
|
||||
this.idToNext[message.id]=prev.id;
|
||||
this.idToPrev[prev.id]=message.id;
|
||||
}
|
||||
prev=message;
|
||||
if(this.messageids[message.id]===undefined){
|
||||
this.messageids[message.id]=message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -534,25 +572,23 @@ class Channel{
|
|||
}
|
||||
this.children=build;
|
||||
}
|
||||
async grabmoremessages(){
|
||||
if(this.messages.length===0||this.allthewayup){
|
||||
async grabmoremessages(id:string){
|
||||
if(this.allthewayup){
|
||||
return;
|
||||
}
|
||||
const out=this;
|
||||
|
||||
await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?before="+this.messages[this.messages.length-1].id+"&limit=100",{
|
||||
await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?before="+id+"&limit=100",{
|
||||
headers:this.headers
|
||||
}).then((j)=>{return j.json()}).then(response=>{
|
||||
//messages.innerHTML = '';
|
||||
//response.reverse()
|
||||
let next:Message;
|
||||
if(response.length===0){
|
||||
out.allthewayup=true;
|
||||
this.allthewayup=true;
|
||||
}
|
||||
let previd=id;
|
||||
for(const i in response){
|
||||
let messager:Message;
|
||||
if(!next){
|
||||
messager=new Message(response[i],this)
|
||||
messager=new Message(response[i],this);
|
||||
}else{
|
||||
messager=next;
|
||||
}
|
||||
|
@ -560,12 +596,13 @@ class Channel{
|
|||
next=new Message(response[+i+1],this);
|
||||
}else{
|
||||
next=undefined;
|
||||
console.log("ohno",+i+1)
|
||||
console.log("ohno",+i+1);
|
||||
}
|
||||
if(out.messageids[messager.id]==undefined){
|
||||
out.messageids[messager.id]=messager;
|
||||
out.buildmessage(messager,next);
|
||||
out.messages.push(messager);
|
||||
if(this.messageids[messager.id]===undefined){
|
||||
this.idToNext[messager.id]=previd;
|
||||
this.idToPrev[previd]=messager.id;
|
||||
previd=messager.id;
|
||||
this.messageids[messager.id]=messager;
|
||||
}else{
|
||||
console.log("How???")
|
||||
}
|
||||
|
@ -579,37 +616,9 @@ class Channel{
|
|||
document.getElementById("messages").prepend(built);
|
||||
}
|
||||
buildmessages(){
|
||||
for(const i in this.messages){
|
||||
const prev=this.messages[(+i)+1];
|
||||
const built=this.messages[i].buildhtml(prev);
|
||||
document.getElementById("messages").prepend(built);
|
||||
|
||||
if (prev) {
|
||||
const prevDate=new Date(prev.timestamp);
|
||||
const currentDate=new Date(this.messages[i].timestamp);
|
||||
|
||||
if (prevDate.toLocaleDateString() != currentDate.toLocaleDateString()) {
|
||||
const dateContainer=document.createElement("div");
|
||||
dateContainer.classList.add("replyflex");
|
||||
|
||||
const line=document.createElement("hr");
|
||||
line.classList.add("reply");
|
||||
dateContainer.appendChild(line);
|
||||
|
||||
const date=document.createElement("span");
|
||||
date.textContent=currentDate.toLocaleDateString(undefined, { weekday: "long", year: "numeric", month: "long", day: "numeric" });
|
||||
dateContainer.appendChild(date);
|
||||
|
||||
const line2=document.createElement("hr");
|
||||
line2.classList.add("reply");
|
||||
dateContainer.appendChild(line2);
|
||||
|
||||
document.getElementById("messages").prepend(dateContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
document.getElementById("messagecontainer").scrollTop = document.getElementById("messagecontainer").scrollHeight;
|
||||
|
||||
const messages=document.getElementById("channelw");
|
||||
messages.innerHTML="";
|
||||
messages.append(this.infinite.getDiv(this.lastmessageid));
|
||||
}
|
||||
updateChannel(JSON){
|
||||
this.type=JSON.type;
|
||||
|
@ -698,7 +707,10 @@ class Channel{
|
|||
messageCreate(messagep:any):void{
|
||||
if(!this.hasPermission("VIEW_CHANNEL")){return}
|
||||
const messagez=new Message(messagep.d,this);
|
||||
this.idToNext[this.lastmessageid]=messagez.id;
|
||||
this.idToPrev[messagez.id]=this.lastmessageid;
|
||||
this.lastmessageid=messagez.id;
|
||||
this.messageids[messagez.id]=messagez;
|
||||
if(messagez.author===this.localuser.user){
|
||||
this.lastreadmessageid=messagez.id;
|
||||
if(this.myhtml){
|
||||
|
@ -710,16 +722,7 @@ class Channel{
|
|||
}
|
||||
}
|
||||
this.guild.unreads();
|
||||
this.messages.unshift(messagez);
|
||||
const scrolly=document.getElementById("messagecontainer");
|
||||
this.messageids[messagez.id]=messagez;
|
||||
if(this.localuser.lookingguild.prevchannel===this){
|
||||
var shouldScroll=scrolly.scrollTop+scrolly.clientHeight>scrolly.scrollHeight-20;
|
||||
document.getElementById("messages").appendChild(messagez.buildhtml(this.messages[1]));
|
||||
}
|
||||
if(shouldScroll){
|
||||
scrolly.scrollTop = scrolly.scrollHeight;
|
||||
}
|
||||
this.infinite.addedBottom();
|
||||
if(messagez.author===this.localuser.user){
|
||||
return;
|
||||
}
|
||||
|
@ -731,6 +734,7 @@ class Channel{
|
|||
}else if(this.notification==="mentions"&&messagez.mentionsuser(this.localuser.user)){
|
||||
this.notify(messagez);
|
||||
}
|
||||
|
||||
}
|
||||
notititle(message:Message):string{
|
||||
return message.author.username+" > "+this.guild.properties.name+" > "+this.name;
|
||||
|
|
|
@ -67,7 +67,6 @@ class Group extends Channel{
|
|||
super(-1,owner);
|
||||
this.owner=owner;
|
||||
this.headers=this.guild.headers;
|
||||
this.messages=[];
|
||||
this.name=JSON.recipients[0]?.username;
|
||||
if(JSON.recipients[0]){
|
||||
this.user=new User(JSON.recipients[0],this.localuser);
|
||||
|
@ -85,6 +84,7 @@ class Group extends Channel{
|
|||
this.lastmessageid=JSON.last_message_id;
|
||||
this.lastmessageid??="0";
|
||||
this.mentions=0;
|
||||
this.setUpInfiniteScroller();
|
||||
}
|
||||
createguildHTML(){
|
||||
const div=document.createElement("div")
|
||||
|
@ -104,9 +104,9 @@ class Group extends Channel{
|
|||
if(this.guild!==this.localuser.lookingguild){
|
||||
this.guild.loadGuild();
|
||||
}
|
||||
const prom=Message.wipeChanel();
|
||||
this.guild.prevchannel=this;
|
||||
this.localuser.channelfocus=this;
|
||||
const prom=this.infinite.delete();
|
||||
await this.putmessages();
|
||||
await prom;
|
||||
if(id!==Channel.genid){
|
||||
|
@ -118,38 +118,28 @@ class Group extends Channel{
|
|||
}
|
||||
messageCreate(messagep){
|
||||
const messagez=new Message(messagep.d,this);
|
||||
this.idToNext[this.lastmessageid]=messagez.id;
|
||||
this.idToPrev[messagez.id]=this.lastmessageid;
|
||||
this.lastmessageid=messagez.id;
|
||||
this.messageids[messagez.id]=messagez;
|
||||
if(messagez.author===this.localuser.user){
|
||||
this.lastreadmessageid=messagez.id;
|
||||
}
|
||||
this.messages.unshift(messagez);
|
||||
const scrolly=document.getElementById("messagecontainer");
|
||||
this.messageids[messagez.id]=messagez;
|
||||
if(this.localuser.lookingguild.prevchannel===this){
|
||||
var shouldScroll=scrolly.scrollTop+scrolly.clientHeight>scrolly.scrollHeight-20;
|
||||
document.getElementById("messages").appendChild(messagez.buildhtml(this.messages[1]));
|
||||
}
|
||||
if(shouldScroll){
|
||||
scrolly.scrollTop = scrolly.scrollHeight;
|
||||
}
|
||||
console.log(document.getElementById("channels").children)
|
||||
if(this.localuser.lookingguild===this.guild){
|
||||
const channellist=document.getElementById("channels").children[0]
|
||||
for(const thing of channellist.children){
|
||||
if(thing["myinfo"]===this){
|
||||
channellist.prepend(thing);
|
||||
break;
|
||||
}
|
||||
if(this.myhtml){
|
||||
this.myhtml.classList.remove("cunread");
|
||||
}
|
||||
}else{
|
||||
if(this.myhtml){
|
||||
this.myhtml.classList.add("cunread");
|
||||
}
|
||||
}
|
||||
this.unreads();
|
||||
this.infinite.addedBottom();
|
||||
if(messagez.author===this.localuser.user){
|
||||
return;
|
||||
}
|
||||
if(this.localuser.lookingguild.prevchannel===this&&document.hasFocus()){
|
||||
return;
|
||||
}
|
||||
console.log(this.notification);
|
||||
if(this.notification==="all"){
|
||||
this.notify(messagez);
|
||||
}else if(this.notification==="mentions"&&messagez.mentionsuser(this.localuser.user)){
|
||||
|
@ -183,9 +173,9 @@ class Group extends Channel{
|
|||
console.log(this);
|
||||
div.append(buildpfp)
|
||||
sentdms.append(div);
|
||||
div.onclick=function(){
|
||||
this["noti"].guild.loadGuild();
|
||||
this["noti"].getHTML();
|
||||
div.onclick=_=>{
|
||||
this.guild.loadGuild();
|
||||
this.getHTML();
|
||||
}
|
||||
}else if(current){
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import {Fullscreen} from "./fullscreen.js";
|
||||
import {Message} from "./message.js";
|
||||
import {markdown} from "./markdown.js";
|
||||
|
||||
class Embed{
|
||||
type:string;
|
||||
owner:Message;
|
||||
|
@ -48,7 +50,7 @@ class Embed{
|
|||
authorline.append(img);
|
||||
}
|
||||
const a=document.createElement("a");
|
||||
a.innerText=this.json.author.name
|
||||
a.textContent=this.json.author.name
|
||||
if(this.json.author.url){
|
||||
a.href=this.json.author.url
|
||||
}
|
||||
|
@ -57,7 +59,7 @@ class Embed{
|
|||
embed.append(authorline);
|
||||
}
|
||||
const title=document.createElement("a");
|
||||
title.textContent=this.json.title;
|
||||
title.append(markdown(this.json.title));
|
||||
if(this.json.url){
|
||||
title.href=this.json.url;
|
||||
}
|
||||
|
@ -66,7 +68,7 @@ class Embed{
|
|||
|
||||
if(this.json.description){
|
||||
const p=document.createElement("p");
|
||||
p.textContent=this.json.description;
|
||||
p.append(markdown(this.json.description));
|
||||
embed.append(p);
|
||||
}
|
||||
|
||||
|
@ -77,9 +79,8 @@ class Embed{
|
|||
const b=document.createElement("b");
|
||||
b.textContent=thing.name;
|
||||
div.append(b);
|
||||
let p;
|
||||
p=document.createElement("p")
|
||||
p.textContent=thing.value;
|
||||
const p=document.createElement("p")
|
||||
p.append(markdown(thing.value));
|
||||
p.classList.add("embedp");
|
||||
div.append(p);
|
||||
|
||||
|
|
|
@ -34,8 +34,10 @@ class File{
|
|||
full.show();
|
||||
}
|
||||
img.src=src;
|
||||
img.height=this.height;
|
||||
img.width=this.width;
|
||||
if(this.width){
|
||||
img.height=this.height;
|
||||
img.width=this.width;
|
||||
}
|
||||
console.log(this.width,this.height)
|
||||
return img;
|
||||
}else if(this.content_type.startsWith('video/')){
|
||||
|
|
|
@ -59,7 +59,7 @@ class Fullscreen{
|
|||
const checkbox = document.createElement('input');
|
||||
div.appendChild(checkbox)
|
||||
const label=document.createElement("span");
|
||||
checkbox.value=array[2];
|
||||
checkbox.checked=array[2];
|
||||
label.textContent=array[1];
|
||||
div.appendChild(label);
|
||||
checkbox.addEventListener("change",array[3]);
|
||||
|
|
102
webpage/index.ts
102
webpage/index.ts
|
@ -3,7 +3,7 @@ import {Contextmenu} from "./contextmenu.js";
|
|||
import {mobile, getBulkUsers,setTheme, Specialuser} from "./login.js";
|
||||
|
||||
async function waitforload(){
|
||||
let res
|
||||
let res;
|
||||
new Promise(r=>{res=r});
|
||||
document.addEventListener("DOMContentLoaded", function(){
|
||||
res();
|
||||
|
@ -18,9 +18,6 @@ const users=getBulkUsers();
|
|||
if(!users.currentuser){
|
||||
window.location.href = '/login.html';
|
||||
}
|
||||
var info=users.users[users.currentuser].serverurls;
|
||||
let token=users.users[users.currentuser].token;
|
||||
let READY;
|
||||
|
||||
let thisuser=new Localuser(users.users[users.currentuser]);
|
||||
thisuser.initwebsocket().then(_=>{
|
||||
|
@ -117,11 +114,6 @@ thisuser.initwebsocket().then(_=>{
|
|||
menu.bind(document.getElementById("channels"))
|
||||
}
|
||||
|
||||
|
||||
function editchannelf(channel){channel.editChannel();}
|
||||
|
||||
|
||||
|
||||
const pasteimage=document.getElementById("pasteimage");
|
||||
let replyingto=null;
|
||||
async function enter(event){
|
||||
|
@ -163,17 +155,6 @@ console.log(typebox)
|
|||
typebox.onclick=console.log;
|
||||
|
||||
|
||||
|
||||
|
||||
let serverz=0;
|
||||
let serverid=[];
|
||||
|
||||
|
||||
|
||||
|
||||
let cchanel=0;
|
||||
|
||||
|
||||
function getguildinfo(){
|
||||
const path=window.location.pathname.split("/");
|
||||
const channel=path[3];
|
||||
|
@ -183,50 +164,7 @@ function getguildinfo(){
|
|||
|
||||
const images:Blob[]=[];
|
||||
const imageshtml=[];
|
||||
function createunknown(fname,fsize){
|
||||
const div=document.createElement("table");
|
||||
div.classList.add("unknownfile");
|
||||
const nametr=document.createElement("tr");
|
||||
div.append(nametr);
|
||||
const fileicon=document.createElement("td");
|
||||
nametr.append(fileicon);
|
||||
fileicon.append("🗎");
|
||||
fileicon.classList.add("fileicon");
|
||||
fileicon.rowSpan=2;
|
||||
const nametd=document.createElement("td");
|
||||
{
|
||||
nametd.textContent=fname;
|
||||
}
|
||||
|
||||
nametd.classList.add("filename");
|
||||
nametr.append(nametd);
|
||||
const sizetr=document.createElement("tr");
|
||||
const size=document.createElement("td");
|
||||
sizetr.append(size);
|
||||
size.textContent="Size:"+filesizehuman(fsize);
|
||||
size.classList.add("filesize");
|
||||
div.appendChild(sizetr)
|
||||
return div;
|
||||
}
|
||||
function filesizehuman(fsize){
|
||||
var i = fsize == 0 ? 0 : Math.floor(Math.log(fsize) / Math.log(1024));
|
||||
return +((fsize / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Terabytes'][i];
|
||||
}
|
||||
function createunknownfile(file){
|
||||
return createunknown(file.name,file.size)
|
||||
}
|
||||
function filetohtml(file){
|
||||
if (file.type.startsWith('image/')) {
|
||||
const img = document.createElement('img');
|
||||
const blob = URL.createObjectURL(file);
|
||||
img.src = blob;
|
||||
return img;
|
||||
}else{
|
||||
console.log(file.name);
|
||||
|
||||
return createunknownfile(file);
|
||||
}
|
||||
}
|
||||
import { File } from "./file.js";
|
||||
document.addEventListener('paste', async (e) => {
|
||||
Array.from(e.clipboardData.files).forEach(async (f) => {
|
||||
|
@ -245,26 +183,7 @@ function userSettings(){
|
|||
thisuser.usersettings.show();
|
||||
}
|
||||
document.getElementById("settings").onclick=userSettings;
|
||||
let triggered=false;
|
||||
document.getElementById("messagecontainer").addEventListener("scroll",(e)=>{
|
||||
const messagecontainer=document.getElementById("messagecontainer")
|
||||
if(messagecontainer.scrollTop<2000){
|
||||
if(!triggered){
|
||||
thisuser.lookingguild.prevchannel.grabmoremessages().then(()=>{
|
||||
triggered=false;
|
||||
if(messagecontainer.scrollTop===0){
|
||||
messagecontainer.scrollTop=1;
|
||||
}
|
||||
});
|
||||
}
|
||||
triggered=true;
|
||||
}else{
|
||||
if(Math.abs(messagecontainer.scrollHeight-messagecontainer.scrollTop-messagecontainer.clientHeight) < 3){
|
||||
thisuser.lookingguild.prevchannel.readbottom();
|
||||
}
|
||||
}
|
||||
//
|
||||
})
|
||||
|
||||
if(mobile){
|
||||
document.getElementById("channelw").onclick=function(){
|
||||
(document.getElementById("channels").parentNode as HTMLElement).classList.add("collapse");
|
||||
|
@ -278,20 +197,3 @@ if(mobile){
|
|||
document.getElementById("servers").classList.remove("collapse");
|
||||
}
|
||||
}
|
||||
/*
|
||||
{
|
||||
const messages=document.getElementById("messages");
|
||||
let height=messages.clientHeight;
|
||||
//
|
||||
const resizeObserver=new ResizeObserver(()=>{
|
||||
console.log(messages.scrollTop,messages.clientHeight-height-messages.scrollHeight);
|
||||
messages.scrollTop-=height-messages.scrollHeight;
|
||||
console.log(messages.scrollTop)
|
||||
//if(shouldsnap){
|
||||
// document.getElementById("messagecontainer").scrollTop = document.getElementById("messagecontainer").scrollHeight;
|
||||
//}
|
||||
height=messages.scrollHeight;
|
||||
})
|
||||
resizeObserver.observe(messages)
|
||||
}
|
||||
*/
|
||||
|
|
148
webpage/infiniteScroller.ts
Normal file
148
webpage/infiniteScroller.ts
Normal file
|
@ -0,0 +1,148 @@
|
|||
class InfiniteScroller{
|
||||
readonly getIDFromOffset:(ID:string,offset:number)=>Promise<string>;
|
||||
readonly getHTMLFromID:(ID:string)=>HTMLElement;
|
||||
readonly destroyFromID:(ID:string)=>Promise<boolean>;
|
||||
readonly reachesBottom:()=>void;
|
||||
private readonly minDist=3000;
|
||||
private readonly maxDist=8000;
|
||||
HTMLElements:[HTMLElement,string][]=[];
|
||||
div:HTMLDivElement;
|
||||
scroll:HTMLDivElement;
|
||||
constructor(getIDFromOffset:InfiniteScroller["getIDFromOffset"],getHTMLFromID:InfiniteScroller["getHTMLFromID"],destroyFromID:InfiniteScroller["destroyFromID"],reachesBottom:InfiniteScroller["reachesBottom"]=()=>{}){
|
||||
this.getIDFromOffset=getIDFromOffset;
|
||||
this.getHTMLFromID=getHTMLFromID;
|
||||
this.destroyFromID=destroyFromID;
|
||||
this.reachesBottom=reachesBottom;
|
||||
}
|
||||
interval:NodeJS.Timeout;
|
||||
getDiv(initialId:string,bottom=true):HTMLDivElement{
|
||||
const div=document.createElement("div");
|
||||
div.classList.add("messagecontainer");
|
||||
//div.classList.add("flexttb")
|
||||
const scroll=document.createElement("div");
|
||||
scroll.classList.add("flexttb","scroller")
|
||||
div.append(scroll);
|
||||
this.div=div;
|
||||
this.interval=setInterval(this.updatestuff.bind(this),100);
|
||||
|
||||
this.scroll=scroll;
|
||||
this.scroll.addEventListener("scroll",this.watchForChange.bind(this));
|
||||
new ResizeObserver(this.watchForChange.bind(this)).observe(div);
|
||||
new ResizeObserver(this.watchForChange.bind(this)).observe(scroll);
|
||||
|
||||
this.firstElement(initialId);
|
||||
this.updatestuff();
|
||||
this.watchForChange().then(_=>{
|
||||
this.scroll.scrollTop=this.scroll.scrollHeight;
|
||||
})
|
||||
return div;
|
||||
}
|
||||
scrollBottom:number;
|
||||
scrollTop:number;
|
||||
updatestuff(){
|
||||
this.scrollBottom = this.scroll.scrollHeight - this.scroll.scrollTop - this.scroll.clientHeight;
|
||||
this.scrollTop=this.scroll.scrollTop;
|
||||
if(this.scrollBottom){
|
||||
this.reachesBottom();
|
||||
}
|
||||
//this.watchForChange();
|
||||
}
|
||||
firstElement(id:string){
|
||||
const html=this.getHTMLFromID(id);
|
||||
this.scroll.append(html);
|
||||
this.HTMLElements.push([html,id]);
|
||||
}
|
||||
currrunning:boolean=false;
|
||||
async addedBottom(){
|
||||
this.updatestuff();
|
||||
const scrollBottom=this.scrollBottom;
|
||||
await this.watchForChange();
|
||||
if(scrollBottom<30){
|
||||
this.scroll.scrollTop=this.scroll.scrollHeight;
|
||||
}
|
||||
}
|
||||
async watchForChange():Promise<void>{
|
||||
if(this.currrunning){
|
||||
return;
|
||||
}else{
|
||||
this.currrunning=true;
|
||||
}
|
||||
let again=false;
|
||||
if(!this.div){this.currrunning=false;return}
|
||||
/*
|
||||
if(this.scrollTop===0){
|
||||
this.scrollTop=10;
|
||||
}
|
||||
*/
|
||||
if(this.scrollTop===0){
|
||||
this.scrollTop=1;
|
||||
this.scroll.scrollTop=1;
|
||||
}
|
||||
if(this.scrollTop<this.minDist){
|
||||
|
||||
|
||||
const previd=this.HTMLElements.at(0)[1];
|
||||
const nextid=await this.getIDFromOffset(previd,1);
|
||||
if(!nextid){
|
||||
|
||||
}else{
|
||||
again=true;
|
||||
const html=this.getHTMLFromID(nextid);
|
||||
this.scroll.prepend(html);
|
||||
this.HTMLElements.unshift([html,nextid]);
|
||||
this.scrollTop+=60;
|
||||
};
|
||||
}
|
||||
if(this.scrollTop>this.maxDist){
|
||||
|
||||
again=true;
|
||||
const html=this.HTMLElements.shift();
|
||||
await this.destroyFromID(html[1]);
|
||||
this.scrollTop-=60;
|
||||
}
|
||||
const scrollBottom = this.scrollBottom;
|
||||
if(scrollBottom<this.minDist){
|
||||
|
||||
|
||||
const previd=this.HTMLElements.at(-1)[1];
|
||||
const nextid=await this.getIDFromOffset(previd,-1);
|
||||
if(!nextid){
|
||||
}else{
|
||||
again=true;
|
||||
const html=this.getHTMLFromID(nextid);
|
||||
this.scroll.append(html);
|
||||
this.HTMLElements.push([html,nextid]);
|
||||
this.scrollBottom+=60;
|
||||
if(scrollBottom<30){
|
||||
this.scroll.scrollTop=this.scroll.scrollHeight;
|
||||
}
|
||||
};
|
||||
}
|
||||
if(scrollBottom>this.maxDist){
|
||||
|
||||
again=true;
|
||||
const html=this.HTMLElements.pop();
|
||||
await this.destroyFromID(html[1]);
|
||||
this.scrollBottom-=60;
|
||||
}
|
||||
|
||||
this.currrunning=false;
|
||||
if(again){
|
||||
await this.watchForChange();
|
||||
}
|
||||
this.currrunning=false;
|
||||
}
|
||||
async delete():Promise<void>{
|
||||
for(const thing of this.HTMLElements){
|
||||
await this.destroyFromID(thing[1]);
|
||||
}
|
||||
this.HTMLElements=[];
|
||||
clearInterval(this.interval);
|
||||
if(this.div){
|
||||
this.div.remove();
|
||||
}
|
||||
this.scroll=null;
|
||||
this.div=null;
|
||||
}
|
||||
}
|
||||
export {InfiniteScroller};
|
|
@ -91,7 +91,7 @@ class Localuser{
|
|||
outoffocus():void{
|
||||
document.getElementById("servers").textContent="";
|
||||
document.getElementById("channels").textContent="";
|
||||
document.getElementById("messages").textContent="";
|
||||
this.channelfocus.infinite.delete();
|
||||
this.lookingguild=null;
|
||||
this.channelfocus=null;
|
||||
}
|
||||
|
@ -154,22 +154,8 @@ class Localuser{
|
|||
returny();
|
||||
break;
|
||||
case "MESSAGE_UPDATE":
|
||||
if(this.initialized){
|
||||
if(this.channelfocus.id===temp.d.channel_id){
|
||||
const find=temp.d.id;
|
||||
const messagelist=document.getElementById("messages").children;
|
||||
for(const message of messagelist){
|
||||
const all = message["all"];
|
||||
if(all.id===find){
|
||||
all.content=temp.d.content;
|
||||
message["txt"].innerHTML=markdown(temp.d.content).innerHTML;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this.resolveChannelFromID(temp.d.channel_id).messages.find(e=>e.id===temp.d.channel_id).content=temp.d.content;
|
||||
}
|
||||
}
|
||||
const message=this.resolveChannelFromID(temp.d.channel_id).messageids[temp.d.id];
|
||||
message.giveData(temp.d);
|
||||
break;
|
||||
case "TYPING_START":
|
||||
if(this.initialized){
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
export {markdown};
|
||||
function markdown(text : string|string[],{keep=false,stdsize=false} = {}){
|
||||
let txt : string[];
|
||||
if((typeof txt)==="string"){
|
||||
if((typeof text)===(typeof "")){
|
||||
txt=(text as string).split("");
|
||||
}else{
|
||||
txt=(text as string[]);
|
||||
}
|
||||
if(txt===undefined){
|
||||
txt=[];
|
||||
}
|
||||
const span=document.createElement("span");
|
||||
let current=document.createElement("span");
|
||||
function appendcurrent(){
|
||||
|
@ -360,6 +363,43 @@ function markdown(text : string|string[],{keep=false,stdsize=false} = {}){
|
|||
}
|
||||
}
|
||||
|
||||
if (txt[i] === "<" && (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":"))) {
|
||||
let found=false;
|
||||
const build = txt[i + 1] === "a" ? ["<","a",":"] : ["<",":"];
|
||||
let j = i+build.length;
|
||||
for (; txt[j] !== void 0; j++) {
|
||||
build.push(txt[j]);
|
||||
|
||||
if (txt[j]===">") {
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
const parts=build.join("").match(/^<(a)?:\w+:(\d{10,30})>$/);
|
||||
if (parts && parts[2]) {
|
||||
appendcurrent();
|
||||
i=j;
|
||||
console.log(typeof txt,txt);
|
||||
const isEmojiOnly = txt.join("").trim()===build.join("").trim();
|
||||
|
||||
const emojiElem=document.createElement("img");
|
||||
emojiElem.classList.add("md-emoji");
|
||||
emojiElem.width=isEmojiOnly ? 48 : 22;
|
||||
emojiElem.height=isEmojiOnly ? 48 : 22;
|
||||
emojiElem.crossOrigin="anonymous";
|
||||
//emojiElem.src=this.info.cdn.toString() + "/emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32";
|
||||
//must uncomment later
|
||||
emojiElem.alt="";
|
||||
emojiElem.loading="lazy";
|
||||
span.appendChild(emojiElem);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current.textContent+=txt[i];
|
||||
}
|
||||
appendcurrent();
|
||||
|
|
|
@ -3,7 +3,6 @@ import {User} from "./user.js";
|
|||
import {Member} from "./member.js";
|
||||
import {markdown} from "./markdown.js";
|
||||
import {Embed} from "./embed.js";
|
||||
import {Fullscreen} from "./fullscreen.js";
|
||||
import { Channel } from "./channel.js";
|
||||
import {Localuser} from "./localuser.js";
|
||||
import { Role } from "./role.js";
|
||||
|
@ -57,6 +56,10 @@ class Message{
|
|||
constructor(messagejson,owner:Channel){
|
||||
this.owner=owner;
|
||||
this.headers=this.owner.headers;
|
||||
this.giveData(messagejson);
|
||||
|
||||
}
|
||||
giveData(messagejson){
|
||||
for(const thing of Object.keys(messagejson)){
|
||||
if(thing==="attachments"){
|
||||
this.attachments=[];
|
||||
|
@ -81,6 +84,9 @@ class Message{
|
|||
if(this.mentionsuser(this.localuser.user)){
|
||||
console.log(this);
|
||||
}
|
||||
if(this.div){
|
||||
this.generateMessage();
|
||||
}
|
||||
}
|
||||
canDelete(){
|
||||
return this.channel.hasPermission("MANAGE_MESSAGES")||this.author.id===this.localuser.user.id;
|
||||
|
@ -97,11 +103,12 @@ class Message{
|
|||
get info(){
|
||||
return this.owner.info;
|
||||
}
|
||||
messageevents(obj:HTMLDivElement){
|
||||
messageevents(obj:HTMLDivElement,del=Message.del){
|
||||
const func=Message.contextmenu.bind(obj,this);
|
||||
this.div=obj;
|
||||
Message.del.then(_=>{
|
||||
del.then(_=>{
|
||||
obj.removeEventListener("click",func);
|
||||
this.div.remove();
|
||||
this.div=null;
|
||||
})
|
||||
obj.classList.add("messagediv");
|
||||
|
@ -140,17 +147,19 @@ class Message{
|
|||
this.div.innerHTML="";
|
||||
this.div=null;
|
||||
}
|
||||
const index=this.channel.messages.indexOf(this);
|
||||
this.channel.messages.splice(this.channel.messages.indexOf(this),1);
|
||||
const prev=this.channel.idToPrev[this.id];
|
||||
const next=this.channel.idToNext[this.id];
|
||||
this.channel.idToNext[prev]=next;
|
||||
this.channel.idToPrev[next]=prev;
|
||||
delete this.channel.messageids[this.id];
|
||||
const regen=this.channel.messages[index-1]
|
||||
const regen=this.channel.messageids[prev]
|
||||
if(regen){
|
||||
regen.generateMessage();
|
||||
}
|
||||
}
|
||||
generateMessage(premessage:Message=null){
|
||||
if(!premessage){
|
||||
premessage=this.channel.messages[this.channel.messages.indexOf(this)+1];
|
||||
premessage=this.channel.messageids[this.channel.idToNext[this.id]];
|
||||
}
|
||||
const div=this.div;
|
||||
if(this===this.channel.replyingto){
|
||||
|
@ -209,8 +218,6 @@ class Message{
|
|||
});
|
||||
div.appendChild(replyline);
|
||||
}
|
||||
|
||||
this.messageevents(div);
|
||||
build.classList.add("message");
|
||||
div.appendChild(build);
|
||||
if({0:true,19:true}[this.type]||this.attachments.length!==0){
|
||||
|
@ -313,11 +320,13 @@ class Message{
|
|||
div["all"]=this;
|
||||
return(div)
|
||||
}
|
||||
buildhtml(premessage:Message){
|
||||
if(this.div){console.error(`HTML for ${this} already exists, aborting`);return;}
|
||||
buildhtml(premessage:Message,del:Promise<void>=Message.del){
|
||||
if(this.div){console.error(`HTML for ${this.id} already exists, aborting`);return;}
|
||||
//premessage??=messages.lastChild;
|
||||
const div=document.createElement("div");
|
||||
this.div=div;
|
||||
|
||||
this.messageevents(div,del);
|
||||
return this.generateMessage(premessage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,4 +58,4 @@ async function tosLogic(){
|
|||
}
|
||||
tosLogic();
|
||||
|
||||
checkInstance.alt=tosLogic;
|
||||
checkInstance["alt"]=tosLogic;
|
||||
|
|
|
@ -83,7 +83,7 @@ class PermissionToggle{
|
|||
|
||||
div.append(this.generateCheckbox());
|
||||
const p=document.createElement("p");
|
||||
p.innerText=this.rolejson.description;
|
||||
p.textContent=this.rolejson.description;
|
||||
div.appendChild(p);
|
||||
return div;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@ th {
|
|||
flex-direction: column;
|
||||
max-height: 20in;
|
||||
padding:.02in .2in;
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
}
|
||||
pre {
|
||||
background-color: var(--code-bg);
|
||||
|
@ -250,8 +252,8 @@ img {
|
|||
font-weight: normal;
|
||||
}
|
||||
|
||||
#messagecontainer {
|
||||
overflow-y: auto;
|
||||
.messagecontainer {
|
||||
overflow-y: hidden;
|
||||
display: flex;
|
||||
max-width: 100%;
|
||||
flex-shrink: 1;
|
||||
|
@ -561,18 +563,18 @@ hr {
|
|||
grid-column: 2;
|
||||
}
|
||||
.replytext pre {
|
||||
padding: 0 .05in;
|
||||
/* padding: 0 .05in; */
|
||||
color: var(--reply-text);
|
||||
overflow: hidden;
|
||||
/* overflow: hidden; */
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
max-width: fit-content;
|
||||
/* display: block; */
|
||||
/* flex-grow: 1; */
|
||||
flex: 1 1 auto;
|
||||
width: fit-content;
|
||||
/* width: fit-content; */
|
||||
min-width: 0;
|
||||
/* display: inline-block !important; */
|
||||
display: inline-block !important;
|
||||
width: 25vw;
|
||||
grid-column: 2;
|
||||
}
|
||||
|
@ -743,7 +745,7 @@ textarea {
|
|||
}
|
||||
|
||||
.servernamediv {
|
||||
/* width: 100%; */
|
||||
width: 99%;
|
||||
/* max-width: 100%; */
|
||||
}
|
||||
|
||||
|
@ -1199,6 +1201,7 @@ span {
|
|||
/* margin-bottom: 1in; */
|
||||
/* padding-bottom: .1in; */
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
.settingbuttons{
|
||||
padding-top:.075in;
|
||||
|
@ -1383,6 +1386,9 @@ span {
|
|||
overflow: hidden;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
flex-direction: row;
|
||||
flex-direction: column;
|
||||
max-height:100in;
|
||||
}
|
||||
.sizeupdown{
|
||||
height:4in;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue