search updates
This commit is contained in:
parent
161181f8de
commit
ffe21e6d6c
10 changed files with 185 additions and 43 deletions
|
@ -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": {
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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[] = [];
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ offset: number
|
|||
this.destroyFromID(thing[1]);
|
||||
}
|
||||
this.HTMLElements=[];
|
||||
this.div=null;
|
||||
}
|
||||
constructor(
|
||||
getIDFromOffset: InfiniteScroller["getIDFromOffset"],
|
||||
|
|
|
@ -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 -----------
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue