friend and more update
This commit is contained in:
parent
e24afe2abe
commit
2502d8f977
13 changed files with 491 additions and 79 deletions
|
@ -40,6 +40,7 @@ jsc: {
|
|||
|
||||
gulp.task('watch', function () {
|
||||
gulp.watch('./src', gulp.series("default"));
|
||||
gulp.watch('./translations', gulp.series("default"));
|
||||
}, {debounceDelay: 10});
|
||||
|
||||
// Clean task to delete the dist directory
|
||||
|
|
|
@ -842,6 +842,10 @@ class Channel extends SnowFlake{
|
|||
if(this.voice&&localStorage.getItem("Voice enabled")){
|
||||
this.localuser.joinVoice(this);
|
||||
}
|
||||
(document.getElementById("typebox") as HTMLDivElement).contentEditable =""+this.canMessage;
|
||||
(document.getElementById("upload") as HTMLElement).style.visibility=this.canMessage?"visible":"hidden";
|
||||
(document.getElementById("typediv") as HTMLElement).style.visibility="visible";
|
||||
(document.getElementById("typebox") as HTMLDivElement).focus();
|
||||
await this.putmessages();
|
||||
await prom;
|
||||
if(id !== Channel.genid){
|
||||
|
@ -851,10 +855,7 @@ class Channel extends SnowFlake{
|
|||
|
||||
await this.buildmessages();
|
||||
//loading.classList.remove("loading");
|
||||
(document.getElementById("typebox") as HTMLDivElement).contentEditable =""+this.canMessage;
|
||||
(document.getElementById("upload") as HTMLElement).style.visibility=this.canMessage?"visible":"hidden";
|
||||
(document.getElementById("typediv") as HTMLElement).style.visibility="visible";
|
||||
(document.getElementById("typebox") as HTMLDivElement).focus();
|
||||
|
||||
}
|
||||
typingmap: Map<Member, number> = new Map();
|
||||
async typingStart(typing: startTypingjson): Promise<void>{
|
||||
|
@ -938,6 +939,7 @@ class Channel extends SnowFlake{
|
|||
}
|
||||
lastmessage: Message | undefined;
|
||||
async putmessages(){
|
||||
//TODO swap out with the WS op code
|
||||
if(this.allthewayup){
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -8,9 +8,11 @@ import{ Permissions }from"./permissions.js";
|
|||
import{ SnowFlake }from"./snowflake.js";
|
||||
import{ Contextmenu }from"./contextmenu.js";
|
||||
import { I18n } from "./i18n.js";
|
||||
import { Float, FormError } from "./settings.js";
|
||||
|
||||
class Direct extends Guild{
|
||||
declare channelids: { [key: string]: Group };
|
||||
channels: Group[];
|
||||
getUnixTime(): number{
|
||||
throw new Error("Do not call this for Direct, it does not make sense");
|
||||
}
|
||||
|
@ -26,7 +28,7 @@ class Direct extends Guild{
|
|||
this.roles = [];
|
||||
this.roleids = new Map();
|
||||
this.prevchannel = undefined;
|
||||
this.properties.name = "Direct Messages";
|
||||
this.properties.name = I18n.getTranslation("DMs.name");
|
||||
for(const thing of json){
|
||||
const temp = new Group(thing, this);
|
||||
this.channels.push(temp);
|
||||
|
@ -60,7 +62,7 @@ class Direct extends Guild{
|
|||
icon.classList.add("svgicon","svg-friends","space");
|
||||
freindDiv.append(icon);
|
||||
|
||||
freindDiv.append("Friends");
|
||||
freindDiv.append(I18n.getTranslation("friends.friends"));
|
||||
ddiv.append(freindDiv);
|
||||
freindDiv.onclick=()=>{
|
||||
this.loadChannel(null);
|
||||
|
@ -69,6 +71,217 @@ class Direct extends Guild{
|
|||
ddiv.append(build);
|
||||
return ddiv;
|
||||
}
|
||||
noChannel(addstate:boolean){
|
||||
if(addstate){
|
||||
history.pushState([this.id,undefined], "", "/channels/" + this.id);
|
||||
}
|
||||
this.localuser.pageTitle(I18n.getTranslation("friends.friendlist"));
|
||||
const channelTopic = document.getElementById("channelTopic") as HTMLSpanElement;
|
||||
channelTopic.removeAttribute("hidden");
|
||||
channelTopic.textContent="";
|
||||
|
||||
const loading = document.getElementById("loadingdiv") as HTMLDivElement;
|
||||
loading.classList.remove("loading");
|
||||
this.localuser.getSidePannel();
|
||||
|
||||
const messages = document.getElementById("channelw") as HTMLDivElement;
|
||||
for(const thing of Array.from(messages.getElementsByClassName("messagecontainer"))){
|
||||
thing.remove();
|
||||
}
|
||||
const container=document.createElement("div");
|
||||
container.classList.add("messagecontainer","flexttb","friendcontainer")
|
||||
|
||||
messages.append(container);
|
||||
const checkVoid=()=>{
|
||||
if(this.localuser.channelfocus!==undefined||this.localuser.lookingguild!==this){
|
||||
this.localuser.relationshipsUpdate=()=>{};
|
||||
}
|
||||
}
|
||||
function genuserstrip(user:User,icons:HTMLElement):HTMLElement{
|
||||
const div=document.createElement("div");
|
||||
div.classList.add("flexltr","liststyle");
|
||||
user.bind(div);
|
||||
div.append(user.buildpfp());
|
||||
|
||||
const userinfos=document.createElement("div");
|
||||
userinfos.classList.add("flexttb");
|
||||
const username=document.createElement("span");
|
||||
username.textContent=user.name;
|
||||
userinfos.append(username,user.getStatus());
|
||||
div.append(userinfos);
|
||||
User.contextmenu.bindContextmenu(div,user,undefined);
|
||||
userinfos.style.flexGrow="1";
|
||||
|
||||
div.append(icons);
|
||||
return div;
|
||||
}
|
||||
{
|
||||
//TODO update on users coming online
|
||||
const online=document.createElement("button");
|
||||
online.textContent=I18n.getTranslation("friends.online");
|
||||
channelTopic.append(online);
|
||||
const genOnline=()=>{
|
||||
this.localuser.relationshipsUpdate=genOnline;
|
||||
checkVoid();
|
||||
container.innerHTML="";
|
||||
container.append(I18n.getTranslation("friends.online:"));
|
||||
for(const user of this.localuser.inrelation){
|
||||
if(user.relationshipType===1&&user.online){
|
||||
const buttonc=document.createElement("div");
|
||||
const button1=document.createElement("span");
|
||||
button1.classList.add("svg-frmessage","svgicon");
|
||||
buttonc.append(button1);
|
||||
buttonc.classList.add("friendlyButton");
|
||||
buttonc.onclick=(e)=>{
|
||||
e.stopImmediatePropagation();
|
||||
user.opendm();
|
||||
}
|
||||
container.append(genuserstrip(user,buttonc));
|
||||
}
|
||||
}
|
||||
}
|
||||
online.onclick=genOnline;
|
||||
genOnline();
|
||||
}
|
||||
{
|
||||
const all=document.createElement("button");
|
||||
all.textContent=I18n.getTranslation("friends.all");
|
||||
const genAll=()=>{
|
||||
this.localuser.relationshipsUpdate=genAll;
|
||||
checkVoid();
|
||||
container.innerHTML="";
|
||||
container.append(I18n.getTranslation("friends.all:"));
|
||||
for(const user of this.localuser.inrelation){
|
||||
if(user.relationshipType===1){
|
||||
const buttonc=document.createElement("div");
|
||||
const button1=document.createElement("span");
|
||||
button1.classList.add("svg-frmessage","svgicon");
|
||||
buttonc.append(button1);
|
||||
buttonc.classList.add("friendlyButton");
|
||||
buttonc.onclick=(e)=>{
|
||||
e.stopImmediatePropagation();
|
||||
user.opendm();
|
||||
}
|
||||
container.append(genuserstrip(user,buttonc));
|
||||
}
|
||||
}
|
||||
}
|
||||
all.onclick=genAll;
|
||||
channelTopic.append(all);
|
||||
}
|
||||
{
|
||||
const pending=document.createElement("button");
|
||||
pending.textContent=I18n.getTranslation("friends.pending");
|
||||
const genPending=()=>{
|
||||
this.localuser.relationshipsUpdate=genPending;
|
||||
checkVoid();
|
||||
container.innerHTML="";
|
||||
container.append(I18n.getTranslation("friends.pending:"));
|
||||
for(const user of this.localuser.inrelation){
|
||||
if(user.relationshipType===3||user.relationshipType===4){
|
||||
const buttons=document.createElement("div");
|
||||
buttons.classList.add("flexltr");
|
||||
const buttonc=document.createElement("div");
|
||||
const button1=document.createElement("span");
|
||||
button1.classList.add("svgicon","svg-x");
|
||||
if(user.relationshipType===3){
|
||||
const buttonc=document.createElement("div");
|
||||
const button2=document.createElement("span");
|
||||
button2.classList.add("svgicon","svg-x");
|
||||
button2.classList.add("svg-addfriend");
|
||||
buttonc.append(button2);
|
||||
buttonc.classList.add("friendlyButton");
|
||||
buttonc.append(button2);
|
||||
buttons.append(buttonc);
|
||||
buttonc.onclick=(e)=>{
|
||||
e.stopImmediatePropagation();
|
||||
user.changeRelationship(1);
|
||||
outerDiv.remove();
|
||||
}
|
||||
}
|
||||
buttonc.append(button1);
|
||||
buttonc.classList.add("friendlyButton");
|
||||
buttonc.onclick=(e)=>{
|
||||
e.stopImmediatePropagation();
|
||||
user.changeRelationship(0);
|
||||
outerDiv.remove();
|
||||
}
|
||||
buttons.append(buttonc);
|
||||
const outerDiv=genuserstrip(user,buttons);
|
||||
container.append(outerDiv);
|
||||
}
|
||||
}
|
||||
}
|
||||
pending.onclick=genPending;
|
||||
channelTopic.append(pending);
|
||||
}
|
||||
{
|
||||
const blocked=document.createElement("button");
|
||||
blocked.textContent=I18n.getTranslation("friends.blocked");
|
||||
|
||||
const genBlocked=()=>{
|
||||
this.localuser.relationshipsUpdate=genBlocked;
|
||||
checkVoid();
|
||||
container.innerHTML="";
|
||||
container.append(I18n.getTranslation("friends.blockedusers"));
|
||||
for(const user of this.localuser.inrelation){
|
||||
if(user.relationshipType===2){
|
||||
const buttonc=document.createElement("div");
|
||||
const button1=document.createElement("span");
|
||||
button1.classList.add("svg-x","svgicon");
|
||||
buttonc.append(button1);
|
||||
buttonc.classList.add("friendlyButton");
|
||||
buttonc.onclick=(e)=>{
|
||||
user.changeRelationship(0);
|
||||
e.stopImmediatePropagation();
|
||||
outerDiv.remove();
|
||||
}
|
||||
const outerDiv=genuserstrip(user,buttonc);
|
||||
container.append(outerDiv);
|
||||
}
|
||||
}
|
||||
}
|
||||
blocked.onclick=genBlocked;
|
||||
channelTopic.append(blocked);
|
||||
}
|
||||
{
|
||||
const add=document.createElement("button");
|
||||
add.textContent=I18n.getTranslation("friends.addfriend");
|
||||
add.onclick=()=>{
|
||||
this.localuser.relationshipsUpdate=()=>{};
|
||||
container.innerHTML="";
|
||||
const float=new Float("");
|
||||
const options=float.options;
|
||||
const form=options.addForm("",(e:any)=>{
|
||||
console.log(e);
|
||||
if(e.code===404){
|
||||
throw new FormError(text,I18n.getTranslation("friends.notfound"));
|
||||
}else if(e.code===400){
|
||||
throw new FormError(text,e.message.split("Error: ")[1]);
|
||||
}else{
|
||||
const box=text.input.deref();
|
||||
if(!box)return;
|
||||
box.value="";
|
||||
}
|
||||
},{
|
||||
method:"POST",
|
||||
fetchURL:this.info.api+"/users/@me/relationships",
|
||||
headers:this.headers
|
||||
});
|
||||
const text=form.addTextInput(I18n.getTranslation("friends.addfriendpromt"),"username");
|
||||
form.addPreprocessor((obj:any)=>{
|
||||
const [username,discriminator]=obj.username.split("#");
|
||||
obj.username=username;
|
||||
obj.discriminator=discriminator;
|
||||
if(!discriminator){
|
||||
throw new FormError(text,I18n.getTranslation("friends.discnotfound"));
|
||||
}
|
||||
});
|
||||
container.append(float.generateHTML());
|
||||
}
|
||||
channelTopic.append(add);
|
||||
}
|
||||
}
|
||||
giveMember(_member: memberjson){
|
||||
console.error("not a real guild, can't give member object");
|
||||
}
|
||||
|
@ -202,6 +415,10 @@ class Group extends Channel{
|
|||
|
||||
loading.classList.add("loading");
|
||||
this.rendertyping();
|
||||
(document.getElementById("typebox") as HTMLDivElement).contentEditable ="" + true;
|
||||
(document.getElementById("upload") as HTMLElement).style.visibility="visible";
|
||||
(document.getElementById("typediv") as HTMLElement).style.visibility="visible";
|
||||
(document.getElementById("typebox") as HTMLDivElement).focus();
|
||||
await this.putmessages();
|
||||
await prom;
|
||||
this.localuser.getSidePannel();
|
||||
|
@ -209,10 +426,7 @@ class Group extends Channel{
|
|||
return;
|
||||
}
|
||||
this.buildmessages();
|
||||
(document.getElementById("typebox") as HTMLDivElement).contentEditable ="" + true;
|
||||
(document.getElementById("upload") as HTMLElement).style.visibility="visible";
|
||||
(document.getElementById("typediv") as HTMLElement).style.visibility="visible";
|
||||
(document.getElementById("typebox") as HTMLDivElement).focus();
|
||||
|
||||
}
|
||||
messageCreate(messagep: { d: messagejson }){
|
||||
const messagez = new Message(messagep.d, this);
|
||||
|
|
|
@ -626,7 +626,7 @@ class Guild extends SnowFlake{
|
|||
if(addstate){
|
||||
history.pushState([this.id,undefined], "", "/channels/" + this.id);
|
||||
}
|
||||
this.localuser.pageTitle("Weird spot");
|
||||
this.localuser.pageTitle(I18n.getTranslation("guild.emptytitle"));
|
||||
const channelTopic = document.getElementById("channelTopic") as HTMLSpanElement;
|
||||
channelTopic.setAttribute("hidden", "");
|
||||
|
||||
|
@ -640,7 +640,7 @@ class Guild extends SnowFlake{
|
|||
}
|
||||
const h1=document.createElement("h1");
|
||||
h1.classList.add("messagecontainer")
|
||||
h1.textContent="You're in a weird spot, this guild has no channels";
|
||||
h1.textContent=I18n.getTranslation("guild.emptytext");
|
||||
messages.append(h1);
|
||||
}
|
||||
loadGuild(){
|
||||
|
|
1
src/webpage/icons/addfriend.svg
Normal file
1
src/webpage/icons/addfriend.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 180"><g fill="red"><circle cx="71" cy="31.3" r="27.5"/><path d="M72.2 62.1A48.2 48.2 0 0 0 23.5 110l-.6 70h96.5l.3-32a13.5 13.5 0 0 1-12-13.2v-10.2H97.4A13.5 13.5 0 0 1 84 111.1a13.5 13.5 0 0 1 13.5-13.5h10.1V87.5a13.5 13.5 0 0 1 2.1-7 48.2 48.2 0 0 0-37.5-18.4z" overflow="visible"/><path stroke="red" stroke-linecap="round" stroke-linejoin="round" stroke-width="15" d="M121.1 87.5v47.3m23.7-23.7H97.5"/></g></svg>
|
After Width: | Height: | Size: 472 B |
1
src/webpage/icons/frmessage.svg
Normal file
1
src/webpage/icons/frmessage.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 180"><g fill="red"><circle cx="97.7" cy="97.7" r="82.3"/><path d="M0 180h90v-80Z"/></g></svg>
|
After Width: | Height: | Size: 150 B |
|
@ -59,7 +59,7 @@
|
|||
<span class="svgicon svg-category"></span>
|
||||
</label>
|
||||
<input type="checkbox" id="maintoggle">
|
||||
<span class="flexltr">
|
||||
<span class="flexltr" style="align-items: center;">
|
||||
<span id="channelname">Channel name</span>
|
||||
<span id="channelTopic" class="ellipsis" hidden>Channel topic</span>
|
||||
</span>
|
||||
|
|
|
@ -505,7 +505,25 @@ roleCreate | {
|
|||
op:9,
|
||||
d:boolean,
|
||||
s:number
|
||||
}|memberlistupdatejson|voiceupdate|voiceserverupdate;
|
||||
}|memberlistupdatejson|voiceupdate|voiceserverupdate|{
|
||||
op: 0,
|
||||
t: "RELATIONSHIP_ADD",
|
||||
d: {
|
||||
id: string,
|
||||
type: 0|1|2|3|4|5|6,
|
||||
user: userjson
|
||||
},
|
||||
s: number
|
||||
}|{
|
||||
op: 0,
|
||||
t: "RELATIONSHIP_REMOVE",
|
||||
d: {
|
||||
id: string,
|
||||
type: number,
|
||||
nickname: null
|
||||
},
|
||||
s: number
|
||||
};
|
||||
|
||||
|
||||
type memberChunk = {
|
||||
|
|
|
@ -124,12 +124,14 @@ class Localuser{
|
|||
const user = new User(thing.user, this);
|
||||
user.nickname = thing.nickname;
|
||||
user.relationshipType = thing.type;
|
||||
this.inrelation.add(user);
|
||||
}
|
||||
|
||||
this.pingEndpoint();
|
||||
this.userinfo.updateLocal();
|
||||
|
||||
}
|
||||
inrelation=new Set<User>();
|
||||
outoffocus(): void{
|
||||
const servers = document.getElementById("servers") as HTMLDivElement;
|
||||
servers.innerHTML = "";
|
||||
|
@ -365,6 +367,7 @@ class Localuser{
|
|||
});
|
||||
await promise;
|
||||
}
|
||||
relationshipsUpdate=()=>{};
|
||||
async handleEvent(temp: wsjson){
|
||||
console.debug(temp);
|
||||
if(temp.s)this.lastSequence = temp.s;
|
||||
|
@ -539,6 +542,23 @@ class Localuser{
|
|||
guild.memberupdate(temp.d)
|
||||
break
|
||||
}
|
||||
case "RELATIONSHIP_ADD":{
|
||||
const user = new User(temp.d.user, this);
|
||||
user.nickname = null;
|
||||
user.relationshipType = temp.d.type;
|
||||
this.inrelation.add(user);
|
||||
this.relationshipsUpdate();
|
||||
break;
|
||||
}
|
||||
case "RELATIONSHIP_REMOVE":{
|
||||
const user = this.userMap.get(temp.d.id);
|
||||
if(!user) return;
|
||||
user.nickname = null;
|
||||
user.relationshipType = 0;
|
||||
this.inrelation.delete(user);
|
||||
this.relationshipsUpdate();
|
||||
break;
|
||||
}
|
||||
default :{
|
||||
//@ts-ignore
|
||||
console.warn("Unhandled case "+temp.t,temp);
|
||||
|
|
|
@ -516,11 +516,27 @@ class HtmlArea implements OptionsElement<void>{
|
|||
}
|
||||
watchForChange(){}
|
||||
}
|
||||
/**
|
||||
* This is a simple wrapper class for Options to make it happy so it can be used outside of Settings.
|
||||
*/
|
||||
class Float{
|
||||
options:Options;
|
||||
/**
|
||||
* This is a simple wrapper class for Options to make it happy so it can be used outside of Settings.
|
||||
*/
|
||||
constructor(name:string, options={ ltr:false, noSubmit:false}){
|
||||
this.options=new Options(name,this,options)
|
||||
}
|
||||
changed=()=>{};
|
||||
generateHTML(){
|
||||
return this.options.generateHTML();
|
||||
}
|
||||
}
|
||||
class Options implements OptionsElement<void>{
|
||||
name: string;
|
||||
haschanged = false;
|
||||
readonly options: OptionsElement<any>[];
|
||||
readonly owner: Buttons | Options | Form;
|
||||
readonly owner: Buttons | Options | Form | Float;
|
||||
readonly ltr: boolean;
|
||||
value!: void;
|
||||
readonly html: WeakMap<OptionsElement<any>, WeakRef<HTMLDivElement>> = new WeakMap();
|
||||
|
@ -530,7 +546,7 @@ class Options implements OptionsElement<void>{
|
|||
);
|
||||
constructor(
|
||||
name: string,
|
||||
owner: Buttons | Options | Form,
|
||||
owner: Buttons | Options | Form | Float,
|
||||
{ ltr = false, noSubmit=false} = {}
|
||||
){
|
||||
this.name = name;
|
||||
|
@ -1145,38 +1161,84 @@ class Form implements OptionsElement<object>{
|
|||
}
|
||||
console.log("middle2");
|
||||
await Promise.allSettled(promises);
|
||||
try{
|
||||
this.preprocessor(build);
|
||||
}catch(e){
|
||||
if(e instanceof FormError){
|
||||
const elm = this.options.html.get(e.elem);
|
||||
if(elm){
|
||||
const html = elm.deref();
|
||||
if(html){
|
||||
this.makeError(html, e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(this.fetchURL !== ""){
|
||||
fetch(this.fetchURL, {
|
||||
method: this.method,
|
||||
body: JSON.stringify(build),
|
||||
headers: this.headers,
|
||||
})
|
||||
.then(_=>_.json())
|
||||
.then(_=>{
|
||||
return _.text()
|
||||
}).then(_=>{
|
||||
if(_==="") return {};
|
||||
return JSON.parse(_)
|
||||
})
|
||||
.then(json=>{
|
||||
if(json.errors && this.errors(json.errors))return;
|
||||
if(json.errors){
|
||||
if(this.errors(json)){
|
||||
return;
|
||||
}
|
||||
}
|
||||
try{
|
||||
this.onSubmit(json);
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
if(e instanceof FormError){
|
||||
const elm = this.options.html.get(e.elem);
|
||||
if(elm){
|
||||
const html = elm.deref();
|
||||
if(html){
|
||||
this.makeError(html, e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
}else{
|
||||
try{
|
||||
this.onSubmit(build);
|
||||
}catch(e){
|
||||
if(e instanceof FormError){
|
||||
const elm = this.options.html.get(e.elem);
|
||||
if(elm){
|
||||
const html = elm.deref();
|
||||
if(html){
|
||||
this.makeError(html, e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.warn("needs to be implemented");
|
||||
}
|
||||
errors(errors: {
|
||||
code: number;
|
||||
message: string;
|
||||
errors: { [key: string]: { _errors: { message: string; code: string } } };
|
||||
}){
|
||||
errors(errors: {code: number; message: string; errors: { [key: string]: { _errors: { message: string; code: string }[] } }}){
|
||||
if(!(errors instanceof Object)){
|
||||
return;
|
||||
}
|
||||
for(const error of Object.keys(errors)){
|
||||
for(const error of Object.keys(errors.errors)){
|
||||
const elm = this.names.get(error);
|
||||
if(elm){
|
||||
const ref = this.options.html.get(elm);
|
||||
if(ref && ref.deref()){
|
||||
const html = ref.deref() as HTMLDivElement;
|
||||
this.makeError(html, errors.errors[error]._errors.message);
|
||||
const errorMessage=errors.errors[error]._errors[0].message;
|
||||
this.makeError(html, errorMessage);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1253,4 +1315,4 @@ class Settings extends Buttons{
|
|||
}
|
||||
}
|
||||
|
||||
export{ Settings, OptionsElement, Buttons, Options,Form };
|
||||
export{ Settings, OptionsElement, Buttons, Options,Form,Float };
|
||||
|
|
|
@ -256,9 +256,15 @@ textarea {
|
|||
}
|
||||
.svg-friends{
|
||||
mask: url(/icons/friends.svg);
|
||||
width: 24px !important;!i;!;
|
||||
height: 24px !important;!i;!;
|
||||
margin-right: 0 !important;!i;!;
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
.svg-frmessage{
|
||||
mask: url(/icons/frmessage.svg);
|
||||
}
|
||||
.svg-addfriend{
|
||||
mask: url(/icons/addfriend.svg);
|
||||
}
|
||||
.svgicon {
|
||||
display: block;
|
||||
|
@ -833,6 +839,9 @@ span.instanceStatus {
|
|||
margin: auto 0 0 8px;
|
||||
font-size: .9em;
|
||||
color: var(--primary-text-soft);
|
||||
button{
|
||||
margin-right:.05in;
|
||||
}
|
||||
}
|
||||
#channelTopic[hidden] {
|
||||
display: none;
|
||||
|
@ -2045,7 +2054,18 @@ fieldset input[type="radio"] {
|
|||
margin: 6px 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.friendcontainer{
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: .2in;
|
||||
>div{
|
||||
background:#00000030;
|
||||
margin-bottom:.1in;
|
||||
padding:.06in .1in;
|
||||
border-radius:.1in;
|
||||
border: solid 1px var(--black);
|
||||
}
|
||||
}
|
||||
.fixedsearch{
|
||||
position: absolute;
|
||||
background: var(--primary-bg);
|
||||
|
@ -2064,6 +2084,35 @@ fieldset input[type="radio"] {
|
|||
}
|
||||
|
||||
}
|
||||
.suberror{
|
||||
animation: goout 6s forwards;
|
||||
}
|
||||
.suberrora{
|
||||
background:var(--channel-hover);
|
||||
border-radius:.1in;
|
||||
position:absolute;
|
||||
border:solid var(--primary-text) .02in;
|
||||
color:color-mix(in hsl,var(--yellow),var(--red));
|
||||
font-weight:bold;
|
||||
opacity:0;
|
||||
cursor:default;
|
||||
/* height: .4in; */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: space-evenly;
|
||||
padding: .075in;
|
||||
box-sizing: border-box;
|
||||
pointer-events: none;
|
||||
}
|
||||
@keyframes goout {
|
||||
0%,100%{
|
||||
opacity:0;
|
||||
}
|
||||
5%,90%{
|
||||
opacity:1;
|
||||
}
|
||||
}
|
||||
.friendsbutton{
|
||||
transition: background-color .2s;
|
||||
background-color: #00000050;
|
||||
|
@ -2072,3 +2121,16 @@ fieldset input[type="radio"] {
|
|||
.bigemoji{
|
||||
width:.6in;
|
||||
}
|
||||
.friendlyButton{
|
||||
padding: .07in;
|
||||
background: #00000045;
|
||||
transition:background .2s;
|
||||
border-radius: 1in;
|
||||
border: solid 1px var(--black);
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 0 .05in;
|
||||
}
|
||||
.friendlyButton:hover{
|
||||
background:black;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import{ presencejson, userjson }from"./jsontypes.js";
|
|||
import { Role } from "./role.js";
|
||||
import { Search } from "./search.js";
|
||||
import { I18n } from "./i18n.js";
|
||||
import { Direct } from "./direct.js";
|
||||
|
||||
class User extends SnowFlake{
|
||||
owner: Localuser;
|
||||
|
@ -15,7 +16,7 @@ class User extends SnowFlake{
|
|||
avatar!: string | null;
|
||||
username!: string;
|
||||
nickname: string | null = null;
|
||||
relationshipType: 0 | 1 | 2 | 3 | 4 = 0;
|
||||
relationshipType: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 0;
|
||||
bio!: MarkDown;
|
||||
discriminator!: string;
|
||||
pronouns!: string;
|
||||
|
@ -85,23 +86,26 @@ class User extends SnowFlake{
|
|||
this.setstatus("offline");
|
||||
}
|
||||
}
|
||||
|
||||
get online(){
|
||||
return (this.status)&&(this.status!="offline");
|
||||
}
|
||||
setstatus(status: string): void{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
async getStatus(): Promise<string>{
|
||||
getStatus(): string{
|
||||
return this.status || "offline";
|
||||
}
|
||||
|
||||
static contextmenu = new Contextmenu<User, Member | undefined>("User Menu");
|
||||
|
||||
static setUpContextMenu(): void{
|
||||
this.contextmenu.addbutton(()=>I18n.getTranslation("user.copyId"), function(this: User){
|
||||
navigator.clipboard.writeText(this.id);
|
||||
});
|
||||
this.contextmenu.addbutton(()=>I18n.getTranslation("user.message"), function(this: User){
|
||||
fetch(this.info.api + "/users/@me/channels", {
|
||||
async opendm(){
|
||||
for(const dm of (this.localuser.guildids.get("@me") as Direct).channels){
|
||||
if(dm.user.id===this.id){
|
||||
this.localuser.goToChannel(dm.id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
await fetch(this.info.api + "/users/@me/channels", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ recipients: [this.id] }),
|
||||
headers: this.localuser.headers,
|
||||
|
@ -110,6 +114,31 @@ class User extends SnowFlake{
|
|||
.then(json=>{
|
||||
this.localuser.goToChannel(json.id);
|
||||
});
|
||||
return;
|
||||
}
|
||||
async changeRelationship(type:0|1|2|3|4|5){
|
||||
if(type!==0){
|
||||
await fetch(`${this.info.api}/users/@me/relationships/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: this.owner.headers,
|
||||
body: JSON.stringify({
|
||||
type,
|
||||
}),
|
||||
});
|
||||
}else{
|
||||
await fetch(`${this.info.api}/users/@me/relationships/${this.id}`, {
|
||||
method: "DELETE",
|
||||
headers: this.owner.headers
|
||||
});
|
||||
}
|
||||
this.relationshipType=type;
|
||||
}
|
||||
static setUpContextMenu(): void{
|
||||
this.contextmenu.addbutton(()=>I18n.getTranslation("user.copyId"), function(this: User){
|
||||
navigator.clipboard.writeText(this.id);
|
||||
});
|
||||
this.contextmenu.addbutton(()=>I18n.getTranslation("user.message"), function(this: User){
|
||||
this.opendm();
|
||||
});
|
||||
this.contextmenu.addbutton(
|
||||
()=>I18n.getTranslation("user.block"),
|
||||
|
@ -133,13 +162,7 @@ class User extends SnowFlake{
|
|||
}
|
||||
);
|
||||
this.contextmenu.addbutton(()=>I18n.getTranslation("user.friendReq"), function(this: User){
|
||||
fetch(`${this.info.api}/users/@me/relationships/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: this.owner.headers,
|
||||
body: JSON.stringify({
|
||||
type: 1,
|
||||
}),
|
||||
});
|
||||
this.changeRelationship(1);
|
||||
});
|
||||
this.contextmenu.addbutton(
|
||||
()=>I18n.getTranslation("user.kick"),
|
||||
|
@ -370,15 +393,8 @@ class User extends SnowFlake{
|
|||
);
|
||||
}
|
||||
|
||||
block(): void{
|
||||
fetch(`${this.info.api}/users/@me/relationships/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: this.owner.headers,
|
||||
body: JSON.stringify({
|
||||
type: 2,
|
||||
}),
|
||||
});
|
||||
this.relationshipType = 2;
|
||||
async block(){
|
||||
await this.changeRelationship(2);
|
||||
const channel = this.localuser.channelfocus;
|
||||
if(channel){
|
||||
for(const message of channel.messages){
|
||||
|
@ -387,12 +403,8 @@ class User extends SnowFlake{
|
|||
}
|
||||
}
|
||||
|
||||
unblock(): void{
|
||||
fetch(`${this.info.api}/users/@me/relationships/${this.id}`, {
|
||||
method: "DELETE",
|
||||
headers: this.owner.headers,
|
||||
});
|
||||
this.relationshipType = 0;
|
||||
async unblock(){
|
||||
await this.changeRelationship(0);
|
||||
const channel = this.localuser.channelfocus;
|
||||
if(channel){
|
||||
for(const message of channel.messages){
|
||||
|
|
|
@ -229,7 +229,9 @@
|
|||
"noDelete":"Nevermind",
|
||||
"create":"Create guild",
|
||||
"loadingDiscovery":"Loading...",
|
||||
"disoveryTitle":"Guild discovery ($1) {{PLURAL:$1|entry|entries}}"
|
||||
"disoveryTitle":"Guild discovery ($1) {{PLURAL:$1|entry|entries}}",
|
||||
"emptytitle":"Weird spot",
|
||||
"emptytext":"You're in a weird spot, this guild has no channels"
|
||||
},
|
||||
"role":{
|
||||
"displaySettings":"Display settings",
|
||||
|
@ -345,11 +347,28 @@
|
|||
"joinUsing":"Join using invite",
|
||||
"inviteLinkCode":"Invite Link/Code"
|
||||
},
|
||||
"friends":{
|
||||
"blocked":"Blocked",
|
||||
"blockedusers":"Blocked Users:",
|
||||
"addfriend":"Add Friend",
|
||||
"addfriendpromt":"Add friends by username:",
|
||||
"notfound":"User not found",
|
||||
"discnotfound":"Discriminator not found",
|
||||
"pending":"Pending",
|
||||
"pending:":"Pending friend requests:",
|
||||
"all":"All",
|
||||
"all:":"All friends:",
|
||||
"online":"Online",
|
||||
"online:":"Online friends:",
|
||||
"friendlist":"Friend List",
|
||||
"friends":"Friends"
|
||||
},
|
||||
"replyingTo":"Replying to $1",
|
||||
"DMs":{
|
||||
"copyId":"Copy DM id",
|
||||
"markRead":"Mark as read",
|
||||
"close":"Close DM"
|
||||
"close":"Close DM",
|
||||
"name":"Dirrect Messages"
|
||||
},
|
||||
"user":{
|
||||
"copyId":"Copy user ID",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue