search updates

This commit is contained in:
MathMan05 2024-12-20 18:59:40 -06:00
parent 161181f8de
commit ffe21e6d6c
10 changed files with 185 additions and 43 deletions

View file

@ -16,6 +16,7 @@
"express": "^4.19.2",
"gulp-sourcemaps": "^2.6.5",
"gulp-swc": "^2.2.0",
"prettier": "^3.4.2",
"rimraf": "^6.0.1"
},
"devDependencies": {

View file

@ -777,6 +777,14 @@ class Channel extends SnowFlake{
return new Message(json[0], this);
}
}
async focus(id:string){
console.time()
console.log(await this.getmessage(id));
await this.getHTML();
console.timeEnd()
console.warn(id);
this.infinite.focus(id);
}
editLast(){
let message:Message|undefined=this.lastmessage;
while(message&&message.author!==this.localuser.user){
@ -1180,7 +1188,7 @@ class Channel extends SnowFlake{
}
async buildmessages(){
this.infinitefocus = false;
this.tryfocusinfinate();
await this.tryfocusinfinate();
}
infinitefocus = false;
async tryfocusinfinate(){
@ -1548,3 +1556,5 @@ class Channel extends SnowFlake{
}
Channel.setupcontextmenu();
export{ Channel };

View file

@ -60,6 +60,7 @@
<span id="channelname">Channel name</span>
<span id="channelTopic" class="ellipsis" hidden>Channel topic</span>
</span>
<div contenteditable="true" class="searchBox" id="searchBox"></div>
<label for="memberlisttoggle" id="memberlisttoggleicon">
<span class="svgicon svg-friends"></span>
</label>

View file

@ -204,7 +204,28 @@ import { I18n } from "./i18n.js";
if(event.key === "Enter" && !event.shiftKey) event.preventDefault();
});
markdown.giveBox(typebox);
{
const searchBox = document.getElementById("searchBox") as CustomHTMLDivElement;
const markdown = new MarkDown("", thisUser);
searchBox.markdown = markdown;
searchBox.addEventListener("keydown", event=>{
if(event.key === "Enter") {
event.preventDefault();
thisUser.mSearch(markdown.rawString)
};
});
markdown.giveBox(searchBox);
markdown.setCustomBox((e)=>{
const span=document.createElement("span");
span.textContent=e.replace("\n","");
return span;
});
}
const images: Blob[] = [];
const imagesHtml: HTMLElement[] = [];

View file

@ -37,7 +37,6 @@ offset: number
this.destroyFromID(thing[1]);
}
this.HTMLElements=[];
this.div=null;
}
constructor(
getIDFromOffset: InfiniteScroller["getIDFromOffset"],

View file

@ -5,7 +5,7 @@ import{ AVoice }from"./audio/voice.js";
import{ User }from"./user.js";
import{ getapiurls, SW }from"./utils/utils.js";
import { getBulkInfo, setTheme, Specialuser } from "./utils/utils.js";
import{channeljson,emojipjson,guildjson,mainuserjson,memberjson,memberlistupdatejson,messageCreateJson,presencejson,readyjson,startTypingjson,wsjson,}from"./jsontypes.js";
import{channeljson,emojipjson,guildjson,mainuserjson,memberjson,memberlistupdatejson,messageCreateJson,messagejson,presencejson,readyjson,startTypingjson,wsjson,}from"./jsontypes.js";
import{ Member }from"./member.js";
import{ Dialog, Form, FormError, Options, Settings }from"./settings.js";
import{ getTextNodeAtPosition, MarkDown }from"./markdown.js";
@ -15,6 +15,7 @@ import { VoiceFactory } from "./voice.js";
import { I18n, langmap } from "./i18n.js";
import { Emoji } from "./emoji.js";
import { Play } from "./audio/play.js";
import { Message } from "./message.js";
const wsCodesRetry = new Set([4000,4001,4002, 4003, 4005, 4007, 4008, 4009]);
@ -669,8 +670,10 @@ class Localuser{
return channel; // Add this line to return the 'channel' variable
}
async memberListUpdate(list:memberlistupdatejson|void){
if(this.searching)return;
const div=document.getElementById("sideDiv") as HTMLDivElement;
div.innerHTML="";
div.classList.remove("searchDiv");
const guild=this.lookingguild;
if(!guild) return;
const channel=this.channelfocus;
@ -832,6 +835,7 @@ class Localuser{
}
}
loadGuild(id: string,forceReload=false): Guild | undefined{
this.searching=false;
let guild = this.guildids.get(id);
if(!guild){
guild = this.guildids.get("@me");
@ -1968,6 +1972,49 @@ class Localuser{
}
box.innerHTML="";
}
searching=false;
mSearch(query:string){
const p=new URLSearchParams("?");
this.searching=true;
p.set("content",query.trim());
fetch(this.info.api+`/guilds/${this.lookingguild?.id}/messages/search/?`+p.toString(),{
headers:this.headers
}).then(_=>_.json()).then((json:{messages:[messagejson][],total_results:number})=>{
//FIXME total_results shall be ignored as it's known to be bad, spacebar bug.
const messages=json.messages.map(([m])=>{
const c=this.channelids.get(m.channel_id);
if(!c) return;
if(c.messages.get(m.id)){
return c.messages.get(m.id);
}
return new Message(m,c,true);
}).filter(_=>_!==undefined);
const sideDiv= document.getElementById("sideDiv");
if(!sideDiv)return;
sideDiv.innerHTML="";
sideDiv.classList.add("searchDiv");
let channel:Channel|undefined=undefined;
for(const message of messages){
if(channel!==message.channel){
channel=message.channel;
const h3=document.createElement("h3");
h3.textContent=channel.name;
h3.classList.add("channelSTitle")
sideDiv.append(h3);
}
const html=message.buildhtml(undefined,true);
html.addEventListener("click",async ()=>{
try{
await message.channel.focus(message.id);
}catch(e){
console.error(e);
}
})
sideDiv.append(html)
}
});
}
keydown:(event:KeyboardEvent)=>unknown=()=>{};
keyup:(event:KeyboardEvent)=>boolean=()=>false;
//---------- resolving members code -----------

View file

@ -300,11 +300,7 @@ class MarkDown{
}
}
if(
find === count &&
(count != 1 ||
txt[j + 1] === " " ||
txt[j + 1] === "\n" ||
txt[j + 1] === undefined)
find === count &&(count != 1 ||txt[j + 1] === " " ||txt[j + 1] === "\n" ||txt[j + 1] === undefined)
){
appendcurrent();
i = j;
@ -715,16 +711,37 @@ txt[j + 1] === undefined)
box.onkeyup(new KeyboardEvent("_"));
};
}
customBox?:[(arg1:string)=>HTMLElement,((arg1:HTMLElement)=>string)];
clearCustom(){
this.customBox=undefined;
}
setCustomBox(stringToHTML:(arg1:string)=>HTMLElement,HTMLToString=MarkDown.gatherBoxText.bind(MarkDown)){
this.customBox=[stringToHTML,HTMLToString];
}
boxupdate(offset=0){
const box=this.box.deref();
if(!box) return;
const restore = saveCaretPosition(box,offset);
let restore:undefined|(()=>void);
if(this.customBox){
restore= saveCaretPosition(box,offset,this.customBox[1]);
}else{
restore= saveCaretPosition(box,offset)
}
box.innerHTML = "";
box.append(this.makeHTML({ keep: true }));
if(this.customBox){
box.append(this.customBox[0](this.rawString));
}else{
box.append(this.makeHTML({ keep: true }));
}
if(restore){
restore();
const test=saveCaretPosition(box);
if(test) test();
if(this.customBox){
const test=saveCaretPosition(box,0,this.customBox[1]);
if(test) test();
}else{
const test=saveCaretPosition(box);
if(test) test();
}
}
this.onUpdate(text,formatted);
}
@ -816,7 +833,7 @@ txt[j + 1] === undefined)
//solution from https://stackoverflow.com/questions/4576694/saving-and-restoring-caret-position-for-contenteditable-div
let text = "";
let formatted=false;
function saveCaretPosition(context: HTMLElement,offset=0){
function saveCaretPosition(context: HTMLElement,offset=0,txtLengthFunc=MarkDown.gatherBoxText.bind(MarkDown)){
const selection = window.getSelection() as Selection;
if(!selection)return;
try{
@ -837,7 +854,7 @@ function saveCaretPosition(context: HTMLElement,offset=0){
i++;
}
if(base instanceof HTMLElement){
baseString=MarkDown.gatherBoxText(base)
baseString=txtLengthFunc(base)
}else{
baseString=base.textContent as string;
}
@ -855,7 +872,7 @@ function saveCaretPosition(context: HTMLElement,offset=0){
const children=[...context.childNodes];
if(children.length===1&&children[0] instanceof Text){
if(selection.containsNode(context,false)){
build+=MarkDown.gatherBoxText(context as HTMLElement);
build+=txtLengthFunc(context as HTMLElement);
}else if(selection.containsNode(context,true)){
if(context.contains(base)||context===base||base.contains(context)){
build+=baseString;
@ -871,7 +888,7 @@ function saveCaretPosition(context: HTMLElement,offset=0){
if(selection.containsNode(node,false)){
if(node instanceof HTMLElement){
build+=MarkDown.gatherBoxText(node);
build+=txtLengthFunc(node);
}else{
build+=node.textContent;
}
@ -892,10 +909,10 @@ function saveCaretPosition(context: HTMLElement,offset=0){
}
text=build;
let len=build.length+offset;
len=Math.min(len,MarkDown.gatherBoxText(context).length)
len=Math.min(len,txtLengthFunc(context).length)
return function restore(){
if(!selection)return;
const pos = getTextNodeAtPosition(context, len);
const pos = getTextNodeAtPosition(context, len,txtLengthFunc);
selection.removeAllRanges();
const range = new Range();
range.setStart(pos.node, pos.position);
@ -906,7 +923,7 @@ function saveCaretPosition(context: HTMLElement,offset=0){
}
}
function getTextNodeAtPosition(root: Node, index: number):{
function getTextNodeAtPosition(root: Node, index: number,txtLengthFunc=MarkDown.gatherBoxText.bind(MarkDown)):{
node: Node,
position: number,
}{
@ -931,7 +948,7 @@ function getTextNodeAtPosition(root: Node, index: number):{
lastElm=node;
let len:number
if(node instanceof HTMLElement){
len=MarkDown.gatherBoxText(node).length;
len=txtLengthFunc(node).length;
}else{
len=(node.textContent as string).length
}

View file

@ -101,12 +101,14 @@ class Message extends SnowFlake{
if(prev) prev.generateMessage();
this.generateMessage(undefined,false)
}
constructor(messagejson: messagejson, owner: Channel){
constructor(messagejson: messagejson, owner: Channel,dontStore=false){
super(messagejson.id);
this.owner = owner;
this.headers = this.owner.headers;
this.giveData(messagejson);
this.owner.messages.set(this.id, this);
if(!dontStore){
this.owner.messages.set(this.id, this);
}
}
reactionToggle(emoji: string | Emoji){
let remove = false;
@ -184,8 +186,11 @@ class Message extends SnowFlake{
}
if(this.div){
this.generateMessage();
return;
}
if(+this.id>+(this.channel.lastmessageid||"0")){
func();
}
func();
}
canDelete(){
return(
@ -338,15 +343,16 @@ class Message extends SnowFlake{
this.generateMessage();
}
}
generateMessage(premessage?: Message | undefined, ignoredblock = false){
if(!this.div)return;
generateMessage(premessage?: Message | undefined, ignoredblock = false,dupe:false|HTMLDivElement=false){
const div = dupe||this.div;
if(!div)return;
const editmode=this.channel.editing===this;
if(!premessage){
if(!premessage&&!dupe){
premessage = this.channel.messages.get(
this.channel.idToPrev.get(this.id) as string
);
}
const div = this.div;
for(const user of this.mentions){
if(user === this.localuser.user){
div.classList.add("mentioned");
@ -390,14 +396,10 @@ class Message extends SnowFlake{
build.classList.add("blocked", "topMessage");
const span = document.createElement("span");
let count = 1;
let next = this.channel.messages.get(
this.channel.idToNext.get(this.id) as string
);
let next = this.channel.messages.get(this.channel.idToNext.get(this.id) as string);
while(next?.author === this.author){
count++;
next = this.channel.messages.get(
this.channel.idToNext.get(next.id) as string
);
next = this.channel.messages.get(this.channel.idToNext.get(next.id) as string);
}
span.textContent = I18n.getTranslation("showBlockedMessages",count+"");
build.append(span);
@ -620,12 +622,14 @@ class Message extends SnowFlake{
text.append(time);
div.classList.add("topMessage");
}
const reactions = document.createElement("div");
reactions.classList.add("flexltr", "reactiondiv");
this.reactdiv = new WeakRef(reactions);
this.updateReactions();
div.append(reactions);
this.bindButtonEvent();
if(!dupe){
const reactions = document.createElement("div");
reactions.classList.add("flexltr", "reactiondiv");
this.reactdiv = new WeakRef(reactions);
this.updateReactions();
div.append(reactions);
this.bindButtonEvent();
}
return div;
}
bindButtonEvent(){
@ -829,7 +833,10 @@ class Message extends SnowFlake{
}
}
}
buildhtml(premessage?: Message | undefined): HTMLElement{
buildhtml(premessage?: Message | undefined,dupe=false): HTMLElement{
if(dupe){
return this.generateMessage(premessage,false,document.createElement("div")) as HTMLElement;
}
if(this.div){
console.error(`HTML for ${this.id} already exists, aborting`);
return this.div;

View file

@ -61,6 +61,10 @@ body {
flex-grow: 1;
min-height: 0;
}
.channelSTitle{
margin-top:.2in;
margin-bottom:0;
}
p, h1, h2, h3, pre, form {
margin: 0;
}
@ -957,6 +961,26 @@ span.instanceStatus {
display:flex;
flex-direction: row;
}
.searchBox:empty {
width:2in;
}
.searchBox {
white-space: nowrap;
height: .075in;
padding: 7px 10px 13px 10px;
background: var(--dock-bg);
border-radius: 4px;
/* overflow-y: auto; */
display:flex;
flex-direction: row;
width: 3in;
margin: 0 .1in;
overflow: hidden;
margin-left: auto;
flex-shrink: 0;
transition: width .2s;
}
.outerTypeBox > span::before {
content: "\feff";
}
@ -1385,7 +1409,21 @@ img.bigembedimg {
.acceptinvbutton:hover, .acceptinvbutton:disabled {
background: color-mix(in hsl, var(--green) 80%, var(--black));
}
#sideDiv.searchDiv{
width: 30vw;
.topMessage{
margin-top:2px;
margin-bottom:10px;
cursor:pointer;
padding:.05in;
border-radius:.075in;
background:#00000020;
}
.topMessage:hover{
background:#00000050;
}
}
/* Sidebar */
#sideDiv {
display: none;
@ -1396,6 +1434,7 @@ img.bigembedimg {
overflow-y: auto;
box-sizing: border-box;
}
.memberList {
padding-bottom: 16px;
color: var(--primary-text-soft);
@ -1416,8 +1455,9 @@ img.bigembedimg {
#memberlisttoggleicon {
display: block;
padding: 12px 0;
margin-left: auto;
margin-left: 0;
cursor: pointer;
flex-grow: 0;
}
#memberlisttoggleicon span {
height: 16px;

View file

@ -9,7 +9,6 @@ import { Role } from "./role.js";
import { Search } from "./search.js";
import { I18n } from "./i18n.js";
import { Direct } from "./direct.js";
import { Settings } from "./settings.js";
class User extends SnowFlake{
owner: Localuser;