improving context menus
This commit is contained in:
parent
ec08cdfde0
commit
3d06440053
10 changed files with 404 additions and 251 deletions
|
@ -73,56 +73,73 @@ class Channel extends SnowFlake {
|
||||||
this.mute_config = settings.mute_config;
|
this.mute_config = settings.mute_config;
|
||||||
}
|
}
|
||||||
static setupcontextmenu() {
|
static setupcontextmenu() {
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("channel.copyId"),
|
|
||||||
function (this: Channel) {
|
|
||||||
navigator.clipboard.writeText(this.id);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
this.contextmenu.addbutton(
|
|
||||||
() => I18n.getTranslation("channel.markRead"),
|
() => I18n.getTranslation("channel.markRead"),
|
||||||
function (this: Channel) {
|
function (this: Channel) {
|
||||||
this.readbottom();
|
this.readbottom();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.contextmenu.addbutton(
|
//TODO invite icon
|
||||||
() => I18n.getTranslation("channel.settings"),
|
this.contextmenu.addButton(
|
||||||
|
() => I18n.getTranslation("channel.makeInvite"),
|
||||||
function (this: Channel) {
|
function (this: Channel) {
|
||||||
this.generateSettings();
|
this.createInvite();
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function () {
|
visable: function () {
|
||||||
return this.hasPermission("MANAGE_CHANNELS");
|
return this.hasPermission("CREATE_INSTANT_INVITE") && this.type !== 4;
|
||||||
|
},
|
||||||
|
color: "blue",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
this.contextmenu.addSeperator();
|
||||||
this.contextmenu.addbutton(
|
//TODO notifcations icon
|
||||||
() => I18n.getTranslation("channel.delete"),
|
this.contextmenu.addButton(
|
||||||
function (this: Channel) {
|
|
||||||
this.deleteChannel();
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
function () {
|
|
||||||
return this.isAdmin();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.contextmenu.addbutton(
|
|
||||||
() => I18n.getTranslation("guild.notifications"),
|
() => I18n.getTranslation("guild.notifications"),
|
||||||
function () {
|
function () {
|
||||||
this.setnotifcation();
|
this.setnotifcation();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("channel.makeInvite"),
|
() => I18n.getTranslation("channel.settings"),
|
||||||
function (this: Channel) {
|
function (this: Channel) {
|
||||||
this.createInvite();
|
this.generateSettings();
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function () {
|
visable: function () {
|
||||||
return this.hasPermission("CREATE_INSTANT_INVITE") && this.type !== 4;
|
return this.hasPermission("MANAGE_CHANNELS");
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
css: "svg-settings",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
this.contextmenu.addButton(
|
||||||
|
() => I18n.getTranslation("channel.delete"),
|
||||||
|
function (this: Channel) {
|
||||||
|
this.deleteChannel();
|
||||||
|
},
|
||||||
|
{
|
||||||
|
visable: function () {
|
||||||
|
//TODO there is no way that this is correct
|
||||||
|
return this.isAdmin();
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
css: "svg-delete",
|
||||||
|
},
|
||||||
|
color: "red",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
this.contextmenu.addSeperator();
|
||||||
|
//TODO copy ID icon
|
||||||
|
this.contextmenu.addButton(
|
||||||
|
() => I18n.getTranslation("channel.copyId"),
|
||||||
|
function (this: Channel) {
|
||||||
|
navigator.clipboard.writeText(this.id);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,114 @@
|
||||||
import {iOS} from "./utils/utils.js";
|
import {mobile} from "./utils/utils.js";
|
||||||
|
type iconJson =
|
||||||
|
| {
|
||||||
|
src: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
css: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
html: HTMLElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface menuPart<x, y> {
|
||||||
|
makeContextHTML(obj1: x, obj2: y, menu: HTMLDivElement): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContextButton<x, y> implements menuPart<x, y> {
|
||||||
|
private text: string | (() => string);
|
||||||
|
private onClick: (this: x, arg: y, e: MouseEvent) => void;
|
||||||
|
private icon?: iconJson;
|
||||||
|
private visable?: (this: x, arg: y) => boolean;
|
||||||
|
private enabled?: (this: x, arg: y) => boolean;
|
||||||
|
//TODO there *will* be more colors
|
||||||
|
private color?: "red" | "blue";
|
||||||
|
constructor(
|
||||||
|
text: ContextButton<x, y>["text"],
|
||||||
|
onClick: ContextButton<x, y>["onClick"],
|
||||||
|
addProps: {
|
||||||
|
icon?: iconJson;
|
||||||
|
visable?: (this: x, arg: y) => boolean;
|
||||||
|
enabled?: (this: x, arg: y) => boolean;
|
||||||
|
color?: "red" | "blue";
|
||||||
|
} = {},
|
||||||
|
) {
|
||||||
|
this.text = text;
|
||||||
|
this.onClick = onClick;
|
||||||
|
this.icon = addProps.icon;
|
||||||
|
this.visable = addProps.visable;
|
||||||
|
this.enabled = addProps.enabled;
|
||||||
|
this.color = addProps.color;
|
||||||
|
}
|
||||||
|
isVisable(obj1: x, obj2: y): boolean {
|
||||||
|
if (!this.visable) return true;
|
||||||
|
return this.visable.call(obj1, obj2);
|
||||||
|
}
|
||||||
|
makeContextHTML(obj1: x, obj2: y, menu: HTMLDivElement) {
|
||||||
|
if (!this.isVisable(obj1, obj2)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const intext = document.createElement("button");
|
||||||
|
intext.classList.add("contextbutton");
|
||||||
|
intext.append(this.textContent);
|
||||||
|
|
||||||
|
intext.disabled = !!this.enabled && !this.enabled.call(obj1, obj2);
|
||||||
|
|
||||||
|
if (this.icon) {
|
||||||
|
if ("src" in this.icon) {
|
||||||
|
const icon = document.createElement("img");
|
||||||
|
icon.classList.add("svgicon");
|
||||||
|
icon.src = this.icon.src;
|
||||||
|
intext.append(icon);
|
||||||
|
} else if ("css" in this.icon) {
|
||||||
|
const icon = document.createElement("span");
|
||||||
|
icon.classList.add(this.icon.css, "svgicon");
|
||||||
|
switch (this.color) {
|
||||||
|
case "red":
|
||||||
|
icon.style.background = "var(--red)";
|
||||||
|
break;
|
||||||
|
case "blue":
|
||||||
|
icon.style.background = "var(--blue)";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
intext.append(icon);
|
||||||
|
} else {
|
||||||
|
intext.append(this.icon.html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (this.color) {
|
||||||
|
case "red":
|
||||||
|
intext.style.color = "var(--red)";
|
||||||
|
break;
|
||||||
|
case "blue":
|
||||||
|
intext.style.color = "var(--blue)";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
intext.onclick = (e) => {
|
||||||
|
menu.remove();
|
||||||
|
this.onClick.call(obj1, obj2, e);
|
||||||
|
};
|
||||||
|
|
||||||
|
menu.append(intext);
|
||||||
|
}
|
||||||
|
get textContent() {
|
||||||
|
if (this.text instanceof Function) {
|
||||||
|
return this.text();
|
||||||
|
}
|
||||||
|
return this.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Seperator<x, y> implements menuPart<x, y> {
|
||||||
|
makeContextHTML(_obj1: x, _obj2: y, menu: HTMLDivElement): void {
|
||||||
|
menu.append(document.createElement("hr"));
|
||||||
|
}
|
||||||
|
}
|
||||||
class Contextmenu<x, y> {
|
class Contextmenu<x, y> {
|
||||||
static currentmenu: HTMLElement | "";
|
static currentmenu: HTMLElement | "";
|
||||||
name: string;
|
name: string;
|
||||||
buttons: [
|
buttons: menuPart<x, y>[];
|
||||||
string | (() => string),
|
|
||||||
(this: x, arg: y, e: MouseEvent) => void,
|
|
||||||
string | null,
|
|
||||||
(this: x, arg: y) => boolean,
|
|
||||||
(this: x, arg: y) => boolean,
|
|
||||||
string,
|
|
||||||
][];
|
|
||||||
div!: HTMLDivElement;
|
div!: HTMLDivElement;
|
||||||
static setup() {
|
static setup() {
|
||||||
Contextmenu.currentmenu = "";
|
Contextmenu.currentmenu = "";
|
||||||
|
@ -27,56 +126,33 @@ class Contextmenu<x, y> {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.buttons = [];
|
this.buttons = [];
|
||||||
}
|
}
|
||||||
addbutton(
|
|
||||||
text: string | (() => string),
|
addButton(
|
||||||
onclick: (this: x, arg: y, e: MouseEvent) => void,
|
text: ContextButton<x, y>["text"],
|
||||||
img: null | string = null,
|
onClick: ContextButton<x, y>["onClick"],
|
||||||
shown: (this: x, arg: y) => boolean = (_) => true,
|
addProps: {
|
||||||
enabled: (this: x, arg: y) => boolean = (_) => true,
|
icon?: iconJson;
|
||||||
|
visable?: (this: x, arg: y) => boolean;
|
||||||
|
enabled?: (this: x, arg: y) => boolean;
|
||||||
|
color?: "red" | "blue";
|
||||||
|
} = {},
|
||||||
) {
|
) {
|
||||||
this.buttons.push([text, onclick, img, shown, enabled, "button"]);
|
this.buttons.push(new ContextButton(text, onClick, addProps));
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
addsubmenu(
|
addSeperator() {
|
||||||
text: string | (() => string),
|
this.buttons.push(new Seperator());
|
||||||
onclick: (this: x, arg: y, e: MouseEvent) => void,
|
|
||||||
img = null,
|
|
||||||
shown: (this: x, arg: y) => boolean = (_) => true,
|
|
||||||
enabled: (this: x, arg: y) => boolean = (_) => true,
|
|
||||||
) {
|
|
||||||
this.buttons.push([text, onclick, img, shown, enabled, "submenu"]);
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
private makemenu(x: number, y: number, addinfo: x, other: y) {
|
private makemenu(x: number, y: number, addinfo: x, other: y) {
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.classList.add("contextmenu", "flexttb");
|
div.classList.add("contextmenu", "flexttb");
|
||||||
|
|
||||||
let visibleButtons = 0;
|
for (const button of this.buttons) {
|
||||||
for (const thing of this.buttons) {
|
button.makeContextHTML(addinfo, other, div);
|
||||||
if (!thing[3].call(addinfo, other)) continue;
|
|
||||||
visibleButtons++;
|
|
||||||
|
|
||||||
const intext = document.createElement("button");
|
|
||||||
intext.disabled = !thing[4].call(addinfo, other);
|
|
||||||
intext.classList.add("contextbutton");
|
|
||||||
if (thing[0] instanceof Function) {
|
|
||||||
intext.textContent = thing[0]();
|
|
||||||
} else {
|
|
||||||
intext.textContent = thing[0];
|
|
||||||
}
|
|
||||||
console.log(thing);
|
|
||||||
if (thing[5] === "button" || thing[5] === "submenu") {
|
|
||||||
intext.onclick = (e) => {
|
|
||||||
div.remove();
|
|
||||||
thing[1].call(addinfo, other, e);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
div.appendChild(intext);
|
|
||||||
}
|
}
|
||||||
if (visibleButtons == 0) return;
|
//NOTE I don't know if this'll ever actually happen in reality
|
||||||
|
if (div.childNodes.length === 0) return;
|
||||||
|
|
||||||
if (Contextmenu.currentmenu != "") {
|
if (Contextmenu.currentmenu !== "") {
|
||||||
Contextmenu.currentmenu.remove();
|
Contextmenu.currentmenu.remove();
|
||||||
}
|
}
|
||||||
div.style.top = y + "px";
|
div.style.top = y + "px";
|
||||||
|
@ -100,7 +176,8 @@ class Contextmenu<x, y> {
|
||||||
this.makemenu(event.clientX, event.clientY, addinfo, other);
|
this.makemenu(event.clientX, event.clientY, addinfo, other);
|
||||||
};
|
};
|
||||||
obj.addEventListener("contextmenu", func);
|
obj.addEventListener("contextmenu", func);
|
||||||
if (iOS) {
|
//NOTE not sure if this code is correct, seems fine at least for now
|
||||||
|
if (mobile) {
|
||||||
let hold: NodeJS.Timeout | undefined;
|
let hold: NodeJS.Timeout | undefined;
|
||||||
let x!: number;
|
let x!: number;
|
||||||
let y!: number;
|
let y!: number;
|
||||||
|
|
|
@ -342,28 +342,28 @@ class Group extends Channel {
|
||||||
user: User;
|
user: User;
|
||||||
static contextmenu = new Contextmenu<Group, undefined>("channel menu");
|
static contextmenu = new Contextmenu<Group, undefined>("channel menu");
|
||||||
static setupcontextmenu() {
|
static setupcontextmenu() {
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("DMs.copyId"),
|
() => I18n.getTranslation("DMs.copyId"),
|
||||||
function (this: Group) {
|
function (this: Group) {
|
||||||
navigator.clipboard.writeText(this.id);
|
navigator.clipboard.writeText(this.id);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("DMs.markRead"),
|
() => I18n.getTranslation("DMs.markRead"),
|
||||||
function (this: Group) {
|
function (this: Group) {
|
||||||
this.readbottom();
|
this.readbottom();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("DMs.close"),
|
() => I18n.getTranslation("DMs.close"),
|
||||||
function (this: Group) {
|
function (this: Group) {
|
||||||
this.deleteChannel();
|
this.deleteChannel();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("user.copyId"),
|
() => I18n.getTranslation("user.copyId"),
|
||||||
function () {
|
function () {
|
||||||
navigator.clipboard.writeText(this.user.id);
|
navigator.clipboard.writeText(this.user.id);
|
||||||
|
|
|
@ -39,89 +39,96 @@ class Guild extends SnowFlake {
|
||||||
members = new Set<Member>();
|
members = new Set<Member>();
|
||||||
static contextmenu = new Contextmenu<Guild, undefined>("guild menu");
|
static contextmenu = new Contextmenu<Guild, undefined>("guild menu");
|
||||||
static setupcontextmenu() {
|
static setupcontextmenu() {
|
||||||
Guild.contextmenu.addbutton(
|
Guild.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("guild.copyId"),
|
|
||||||
function (this: Guild) {
|
|
||||||
navigator.clipboard.writeText(this.id);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
Guild.contextmenu.addbutton(
|
|
||||||
() => I18n.getTranslation("guild.markRead"),
|
|
||||||
function (this: Guild) {
|
|
||||||
this.markAsRead();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
Guild.contextmenu.addbutton(
|
|
||||||
() => I18n.getTranslation("guild.notifications"),
|
|
||||||
function (this: Guild) {
|
|
||||||
this.setnotifcation();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
this.contextmenu.addbutton(
|
|
||||||
() => I18n.getTranslation("user.editServerProfile"),
|
|
||||||
function () {
|
|
||||||
this.member.showEditProfile();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
Guild.contextmenu.addbutton(
|
|
||||||
() => I18n.getTranslation("guild.leave"),
|
|
||||||
function (this: Guild) {
|
|
||||||
this.confirmleave();
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
function (_) {
|
|
||||||
return this.properties.owner_id !== this.member.user.id;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
Guild.contextmenu.addbutton(
|
|
||||||
() => I18n.getTranslation("guild.delete"),
|
|
||||||
function (this: Guild) {
|
|
||||||
this.confirmDelete();
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
function (_) {
|
|
||||||
return this.properties.owner_id === this.member.user.id;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
Guild.contextmenu.addbutton(
|
|
||||||
() => I18n.getTranslation("guild.makeInvite"),
|
() => I18n.getTranslation("guild.makeInvite"),
|
||||||
function (this: Guild) {
|
function (this: Guild) {
|
||||||
const d = new Dialog("");
|
const d = new Dialog("");
|
||||||
this.makeInviteMenu(d.options);
|
this.makeInviteMenu(d.options);
|
||||||
d.show();
|
d.show();
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
(_) => true,
|
enabled: function () {
|
||||||
function () {
|
return this.member.hasPermission("CREATE_INSTANT_INVITE");
|
||||||
return this.member.hasPermission("CREATE_INSTANT_INVITE");
|
},
|
||||||
|
color: "blue",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Guild.contextmenu.addbutton(
|
Guild.contextmenu.addSeperator();
|
||||||
|
|
||||||
|
Guild.contextmenu.addButton(
|
||||||
|
() => I18n.getTranslation("guild.markRead"),
|
||||||
|
function (this: Guild) {
|
||||||
|
this.markAsRead();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Guild.contextmenu.addButton(
|
||||||
|
() => I18n.getTranslation("guild.notifications"),
|
||||||
|
function (this: Guild) {
|
||||||
|
this.setnotifcation();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
Guild.contextmenu.addSeperator();
|
||||||
|
this.contextmenu.addButton(
|
||||||
|
() => I18n.getTranslation("user.editServerProfile"),
|
||||||
|
function () {
|
||||||
|
this.member.showEditProfile();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
Guild.contextmenu.addSeperator();
|
||||||
|
|
||||||
|
Guild.contextmenu.addButton(
|
||||||
|
() => I18n.getTranslation("guild.leave"),
|
||||||
|
function (this: Guild) {
|
||||||
|
this.confirmleave();
|
||||||
|
},
|
||||||
|
{
|
||||||
|
visable: function (_) {
|
||||||
|
return this.properties.owner_id !== this.member.user.id;
|
||||||
|
},
|
||||||
|
color: "red",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Guild.contextmenu.addButton(
|
||||||
|
() => I18n.getTranslation("guild.delete"),
|
||||||
|
function (this: Guild) {
|
||||||
|
this.confirmDelete();
|
||||||
|
},
|
||||||
|
{
|
||||||
|
visable: function (_) {
|
||||||
|
return this.properties.owner_id === this.member.user.id;
|
||||||
|
},
|
||||||
|
color: "red",
|
||||||
|
icon: {
|
||||||
|
css: "svg-delete",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Guild.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("guild.settings"),
|
() => I18n.getTranslation("guild.settings"),
|
||||||
function (this: Guild) {
|
function (this: Guild) {
|
||||||
this.generateSettings();
|
this.generateSettings();
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function () {
|
visable: function () {
|
||||||
return this.member.hasPermission("MANAGE_GUILD");
|
return this.member.hasPermission("MANAGE_GUILD");
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
css: "svg-settings",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
/* -----things left for later-----
|
|
||||||
guild.contextmenu.addbutton("Leave Guild",function(){
|
|
||||||
console.log(this)
|
|
||||||
this.deleteChannel();
|
|
||||||
},null,_=>{return thisuser.isAdmin()})
|
|
||||||
|
|
||||||
guild.contextmenu.addbutton("Mute Guild",function(){
|
Guild.contextmenu.addSeperator();
|
||||||
editchannelf(this);
|
Guild.contextmenu.addButton(
|
||||||
},null,_=>{return thisuser.isAdmin()})
|
() => I18n.getTranslation("guild.copyId"),
|
||||||
*/
|
function (this: Guild) {
|
||||||
|
navigator.clipboard.writeText(this.id);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
//TODO mute guild button
|
||||||
}
|
}
|
||||||
generateSettings() {
|
generateSettings() {
|
||||||
const settings = new Settings(I18n.getTranslation("guild.settingsFor", this.properties.name));
|
const settings = new Settings(I18n.getTranslation("guild.settingsFor", this.properties.name));
|
||||||
|
|
|
@ -127,26 +127,24 @@ import {I18n} from "./i18n.js";
|
||||||
}
|
}
|
||||||
|
|
||||||
const menu = new Contextmenu<void, void>("create rightclick");
|
const menu = new Contextmenu<void, void>("create rightclick");
|
||||||
menu.addbutton(
|
menu.addButton(
|
||||||
I18n.getTranslation("channel.createChannel"),
|
I18n.getTranslation("channel.createChannel"),
|
||||||
() => {
|
() => {
|
||||||
if (thisUser.lookingguild) {
|
if (thisUser.lookingguild) {
|
||||||
thisUser.lookingguild.createchannels();
|
thisUser.lookingguild.createchannels();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
null,
|
{visable: () => thisUser.isAdmin()},
|
||||||
() => thisUser.isAdmin(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
menu.addbutton(
|
menu.addButton(
|
||||||
I18n.getTranslation("channel.createCatagory"),
|
I18n.getTranslation("channel.createCatagory"),
|
||||||
() => {
|
() => {
|
||||||
if (thisUser.lookingguild) {
|
if (thisUser.lookingguild) {
|
||||||
thisUser.lookingguild.createcategory();
|
thisUser.lookingguild.createcategory();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
null,
|
{visable: () => thisUser.isAdmin()},
|
||||||
() => thisUser.isAdmin(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
menu.bindContextmenu(document.getElementById("channels") as HTMLDivElement);
|
menu.bindContextmenu(document.getElementById("channels") as HTMLDivElement);
|
||||||
|
|
|
@ -57,50 +57,81 @@ class Message extends SnowFlake {
|
||||||
Message.setupcmenu();
|
Message.setupcmenu();
|
||||||
}
|
}
|
||||||
static setupcmenu() {
|
static setupcmenu() {
|
||||||
Message.contextmenu.addbutton(
|
Message.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("copyrawtext"),
|
|
||||||
function (this: Message) {
|
|
||||||
navigator.clipboard.writeText(this.content.rawString);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
Message.contextmenu.addbutton(
|
|
||||||
() => I18n.getTranslation("reply"),
|
() => I18n.getTranslation("reply"),
|
||||||
function (this: Message) {
|
function (this: Message) {
|
||||||
this.channel.setReplying(this);
|
this.channel.setReplying(this);
|
||||||
},
|
},
|
||||||
);
|
{
|
||||||
Message.contextmenu.addbutton(
|
icon: {
|
||||||
() => I18n.getTranslation("copymessageid"),
|
css: "svg-reply",
|
||||||
function (this: Message) {
|
},
|
||||||
navigator.clipboard.writeText(this.id);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Message.contextmenu.addsubmenu(
|
|
||||||
|
Message.contextmenu.addButton(
|
||||||
|
() => I18n.getTranslation("message.edit"),
|
||||||
|
function (this: Message) {
|
||||||
|
this.setEdit();
|
||||||
|
},
|
||||||
|
{
|
||||||
|
visable: function () {
|
||||||
|
return this.author.id === this.localuser.user.id;
|
||||||
|
},
|
||||||
|
|
||||||
|
icon: {
|
||||||
|
css: "svg-edit",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Message.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("message.reactionAdd"),
|
() => I18n.getTranslation("message.reactionAdd"),
|
||||||
function (this: Message, _, e: MouseEvent) {
|
function (this: Message, _, e: MouseEvent) {
|
||||||
Emoji.emojiPicker(e.x, e.y, this.localuser).then((_) => {
|
Emoji.emojiPicker(e.x, e.y, this.localuser).then((_) => {
|
||||||
this.reactionToggle(_);
|
this.reactionToggle(_);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: {
|
||||||
|
css: "svg-emoji",
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
Message.contextmenu.addbutton(
|
|
||||||
() => I18n.getTranslation("message.edit"),
|
Message.contextmenu.addSeperator();
|
||||||
|
Message.contextmenu.addButton(
|
||||||
|
() => I18n.getTranslation("copyrawtext"),
|
||||||
function (this: Message) {
|
function (this: Message) {
|
||||||
this.setEdit();
|
navigator.clipboard.writeText(this.content.rawString);
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function () {
|
icon: {
|
||||||
return this.author.id === this.localuser.user.id;
|
css: "svg-copy",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Message.contextmenu.addbutton(
|
Message.contextmenu.addButton(
|
||||||
|
() => I18n.getTranslation("copymessageid"),
|
||||||
|
function (this: Message) {
|
||||||
|
navigator.clipboard.writeText(this.id);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Message.contextmenu.addSeperator();
|
||||||
|
Message.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("message.delete"),
|
() => I18n.getTranslation("message.delete"),
|
||||||
function (this: Message) {
|
function (this: Message) {
|
||||||
this.confirmDelete();
|
this.confirmDelete();
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function () {
|
visable: function () {
|
||||||
return this.canDelete();
|
return this.canDelete();
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
css: "svg-delete",
|
||||||
|
},
|
||||||
|
color: "red",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,7 +236,7 @@ class RoleList extends Buttons {
|
||||||
static guildrolemenu = this.GuildRoleMenu();
|
static guildrolemenu = this.GuildRoleMenu();
|
||||||
private static ChannelRoleMenu() {
|
private static ChannelRoleMenu() {
|
||||||
const menu = new Contextmenu<RoleList, Role>("role settings");
|
const menu = new Contextmenu<RoleList, Role>("role settings");
|
||||||
menu.addbutton(
|
menu.addButton(
|
||||||
() => I18n.getTranslation("role.remove"),
|
() => I18n.getTranslation("role.remove"),
|
||||||
function (role) {
|
function (role) {
|
||||||
if (!this.channel) return;
|
if (!this.channel) return;
|
||||||
|
@ -246,13 +246,12 @@ class RoleList extends Buttons {
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
null,
|
|
||||||
);
|
);
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
private static GuildRoleMenu() {
|
private static GuildRoleMenu() {
|
||||||
const menu = new Contextmenu<RoleList, Role>("role settings");
|
const menu = new Contextmenu<RoleList, Role>("role settings");
|
||||||
menu.addbutton(
|
menu.addButton(
|
||||||
() => I18n.getTranslation("role.delete"),
|
() => I18n.getTranslation("role.delete"),
|
||||||
function (role) {
|
function (role) {
|
||||||
if (!confirm(I18n.getTranslation("role.confirmDelete"))) return;
|
if (!confirm(I18n.getTranslation("role.confirmDelete"))) return;
|
||||||
|
@ -262,7 +261,6 @@ class RoleList extends Buttons {
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
null,
|
|
||||||
);
|
);
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,6 +318,7 @@ textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: var(--primary-text-soft);
|
background: var(--primary-text-soft);
|
||||||
mask-repeat: no-repeat;
|
mask-repeat: no-repeat;
|
||||||
|
aspect-ratio: 1/1;
|
||||||
}
|
}
|
||||||
.selectarrow {
|
.selectarrow {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -1534,8 +1535,13 @@ img.bigembedimg {
|
||||||
background: var(--secondary-bg);
|
background: var(--secondary-bg);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-shadow: 0 0 8px var(--shadow);
|
box-shadow: 0 0 8px var(--shadow);
|
||||||
|
hr{
|
||||||
|
width:90%;
|
||||||
|
height: 1px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.contextbutton {
|
.contextbutton {
|
||||||
|
position: relative;
|
||||||
width: 180px;
|
width: 180px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
@ -1544,6 +1550,15 @@ img.bigembedimg {
|
||||||
color: var(--secondary-text);
|
color: var(--secondary-text);
|
||||||
border: none;
|
border: none;
|
||||||
transition: none;
|
transition: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
.svgicon {
|
||||||
|
height: 0.2in;
|
||||||
|
width: 0.2in;
|
||||||
|
position: absolute;
|
||||||
|
right: 6px;
|
||||||
|
top: 6px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.contextbutton:enabled:hover {
|
.contextbutton:enabled:hover {
|
||||||
background: var(--secondary-hover);
|
background: var(--secondary-hover);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
--red: #ff5555;
|
--red: #ff5555;
|
||||||
--yellow: #ffc159;
|
--yellow: #ffc159;
|
||||||
--green: #1c907b;
|
--green: #1c907b;
|
||||||
|
--blue: #779bff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Themes. See themes.txt */
|
/* Themes. See themes.txt */
|
||||||
|
|
|
@ -164,111 +164,118 @@ class User extends SnowFlake {
|
||||||
this.relationshipType = type;
|
this.relationshipType = type;
|
||||||
}
|
}
|
||||||
static setUpContextMenu(): void {
|
static setUpContextMenu(): void {
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("user.copyId"),
|
() => I18n.getTranslation("user.copyId"),
|
||||||
function (this: User) {
|
function (this: User) {
|
||||||
navigator.clipboard.writeText(this.id);
|
navigator.clipboard.writeText(this.id);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("user.message"),
|
() => I18n.getTranslation("user.message"),
|
||||||
function (this: User) {
|
function (this: User) {
|
||||||
this.opendm();
|
this.opendm();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("user.block"),
|
() => I18n.getTranslation("user.block"),
|
||||||
function (this: User) {
|
function (this: User) {
|
||||||
this.block();
|
this.block();
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function () {
|
visable: function () {
|
||||||
return this.relationshipType !== 2 && this.id !== this.localuser.user.id;
|
return this.relationshipType !== 2 && this.id !== this.localuser.user.id;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("user.unblock"),
|
() => I18n.getTranslation("user.unblock"),
|
||||||
function (this: User) {
|
function (this: User) {
|
||||||
this.unblock();
|
this.unblock();
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function () {
|
visable: function () {
|
||||||
return this.relationshipType === 2 && this.id !== this.localuser.user.id;
|
return this.relationshipType === 2 && this.id !== this.localuser.user.id;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("user.friendReq"),
|
() => I18n.getTranslation("user.friendReq"),
|
||||||
function (this: User) {
|
function (this: User) {
|
||||||
this.changeRelationship(1);
|
this.changeRelationship(1);
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function () {
|
visable: function () {
|
||||||
return (
|
return (
|
||||||
(this.relationshipType === 0 || this.relationshipType === 3) &&
|
(this.relationshipType === 0 || this.relationshipType === 3) &&
|
||||||
this.id !== this.localuser.user.id
|
this.id !== this.localuser.user.id
|
||||||
);
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("friends.removeFriend"),
|
() => I18n.getTranslation("friends.removeFriend"),
|
||||||
function (this: User) {
|
function (this: User) {
|
||||||
this.changeRelationship(0);
|
this.changeRelationship(0);
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function () {
|
visable: function () {
|
||||||
return this.relationshipType === 1 && this.id !== this.localuser.user.id;
|
return this.relationshipType === 1 && this.id !== this.localuser.user.id;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("user.kick"),
|
() => I18n.getTranslation("user.kick"),
|
||||||
function (this: User, member: Member | undefined) {
|
function (this: User, member: Member | undefined) {
|
||||||
member?.kick();
|
member?.kick();
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function (member) {
|
visable: function (member) {
|
||||||
if (!member) return false;
|
if (!member) return false;
|
||||||
const us = member.guild.member;
|
const us = member.guild.member;
|
||||||
if (member.id === us.id) {
|
if (member.id === us.id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (member.id === member.guild.properties.owner_id) {
|
if (member.id === member.guild.properties.owner_id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return us.hasPermission("KICK_MEMBERS") && this.id !== this.localuser.user.id;
|
return us.hasPermission("KICK_MEMBERS") && this.id !== this.localuser.user.id;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("user.editServerProfile"),
|
() => I18n.getTranslation("user.editServerProfile"),
|
||||||
function (this: User, member: Member | undefined) {
|
function (this: User, member: Member | undefined) {
|
||||||
if (!member) return;
|
if (!member) return;
|
||||||
member.showEditProfile();
|
member.showEditProfile();
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function (member) {
|
visable: function (member) {
|
||||||
return member?.id === this.localuser.user.id;
|
return member?.id === this.localuser.user.id;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("user.ban"),
|
() => I18n.getTranslation("user.ban"),
|
||||||
function (this: User, member: Member | undefined) {
|
function (this: User, member: Member | undefined) {
|
||||||
member?.ban();
|
member?.ban();
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
function (member) {
|
visable: function (member) {
|
||||||
if (!member) return false;
|
if (!member) return false;
|
||||||
const us = member.guild.member;
|
const us = member.guild.member;
|
||||||
if (member.id === us.id) {
|
if (member.id === us.id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (member.id === member.guild.properties.owner_id) {
|
if (member.id === member.guild.properties.owner_id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return us.hasPermission("BAN_MEMBERS") && this.id !== this.localuser.user.id;
|
return us.hasPermission("BAN_MEMBERS") && this.id !== this.localuser.user.id;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("user.addRole"),
|
() => I18n.getTranslation("user.addRole"),
|
||||||
async function (this: User, member: Member | undefined, e) {
|
async function (this: User, member: Member | undefined, e) {
|
||||||
if (member) {
|
if (member) {
|
||||||
|
@ -286,15 +293,16 @@ class User extends SnowFlake {
|
||||||
member.addRole(result);
|
member.addRole(result);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
(member) => {
|
visable: (member) => {
|
||||||
if (!member) return false;
|
if (!member) return false;
|
||||||
const us = member.guild.member;
|
const us = member.guild.member;
|
||||||
console.log(us.hasPermission("MANAGE_ROLES"));
|
console.log(us.hasPermission("MANAGE_ROLES"));
|
||||||
return us.hasPermission("MANAGE_ROLES") || false;
|
return us.hasPermission("MANAGE_ROLES") || false;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.contextmenu.addbutton(
|
this.contextmenu.addButton(
|
||||||
() => I18n.getTranslation("user.removeRole"),
|
() => I18n.getTranslation("user.removeRole"),
|
||||||
async function (this: User, member: Member | undefined, e) {
|
async function (this: User, member: Member | undefined, e) {
|
||||||
if (member) {
|
if (member) {
|
||||||
|
@ -312,12 +320,13 @@ class User extends SnowFlake {
|
||||||
member.removeRole(result);
|
member.removeRole(result);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
null,
|
{
|
||||||
(member) => {
|
visable: (member) => {
|
||||||
if (!member) return false;
|
if (!member) return false;
|
||||||
const us = member.guild.member;
|
const us = member.guild.member;
|
||||||
console.log(us.hasPermission("MANAGE_ROLES"));
|
console.log(us.hasPermission("MANAGE_ROLES"));
|
||||||
return us.hasPermission("MANAGE_ROLES") || false;
|
return us.hasPermission("MANAGE_ROLES") || false;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue