Added the ability to add custom context menus
parent
c42d890c7f
commit
40ca24f075
|
@ -397,6 +397,57 @@ function main() {
|
|||
}
|
||||
}
|
||||
|
||||
$(document).on('contextmenu', event => {
|
||||
if(event.isDefaultPrevented())
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
contextmenu.spawn_context_menu(event.pageX, event.pageY, {
|
||||
name: 'Test item 1',
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
callback: () => console.log("Test 1 item clicked!"),
|
||||
|
||||
disabled: true
|
||||
}, {
|
||||
name: 'Test item 2',
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
callback: () => console.log("Test 2 item clicked!")
|
||||
}, {
|
||||
name: 'Test item 3',
|
||||
type: contextmenu.MenuEntryType.SUB_MENU,
|
||||
callback: () => console.log("Test 3 item clicked!"),
|
||||
sub_menu: [
|
||||
{
|
||||
name: 'Test sub item 1',
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
callback: () => console.log("Test sub 1 item clicked!")
|
||||
}, {
|
||||
name: 'Test sub item 2',
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
callback: () => console.log("Test sub 2 item clicked!")
|
||||
}, {
|
||||
name: 'Test sub item 4',
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
callback: () => console.log("Test sub 3 item clicked!")
|
||||
}
|
||||
]
|
||||
},
|
||||
contextmenu.Entry.HR(),
|
||||
{
|
||||
name: 'Test item 4',
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
callback: () => console.log("Test 4 item clicked!")
|
||||
}, {
|
||||
name: 'Test item 5',
|
||||
type: contextmenu.MenuEntryType.CHECKBOX,
|
||||
callback: () => console.log("Test 5 item clicked!")
|
||||
}, {
|
||||
name: 'Test item 5',
|
||||
type: contextmenu.MenuEntryType.CHECKBOX,
|
||||
callback: () => console.log("Test 5 item clicked!"),
|
||||
checkbox_checked: true
|
||||
}, contextmenu.Entry.CLOSE(() => console.log("Menu closed!")))
|
||||
})
|
||||
}
|
||||
|
||||
const task_teaweb_starter: loader.Task = {
|
||||
|
|
|
@ -452,58 +452,60 @@ class ChannelEntry {
|
|||
}
|
||||
|
||||
let trigger_close = true;
|
||||
spawn_context_menu(x, y, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
|
||||
const bold = text => contextmenu.get_provider().html_format_enabled() ? "<b>" + text + "</b>" : text;
|
||||
contextmenu.spawn_context_menu(x, y, {
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Show channel info"),
|
||||
callback: () => {
|
||||
trigger_close = false;
|
||||
this.channelTree.client.select_info.open_popover()
|
||||
},
|
||||
icon: "client-about",
|
||||
icon_class: "client-about",
|
||||
visible: this.channelTree.client.select_info.is_popover()
|
||||
}, {
|
||||
type: MenuEntryType.HR,
|
||||
type: contextmenu.MenuEntryType.HR,
|
||||
visible: this.channelTree.client.select_info.is_popover(),
|
||||
name: ''
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-channel_switch",
|
||||
name: tr("<b>Switch to channel</b>"),
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-channel_switch",
|
||||
name: bold(tr("Switch to channel")),
|
||||
callback: () => this.joinChannel()
|
||||
},
|
||||
...(() => {
|
||||
const local_client = this.channelTree.client.getClient();
|
||||
if (!local_client || local_client.currentChannel() !== this)
|
||||
return [
|
||||
MenuEntry.HR(),
|
||||
contextmenu.Entry.HR(),
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon: "client-subscribe_to_channel",
|
||||
name: tr("<b>Subscribe to channel</b>"),
|
||||
name: bold(tr("Subscribe to channel")),
|
||||
callback: () => this.subscribe(),
|
||||
visible: !this.flag_subscribed
|
||||
},
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon: "client-channel_unsubscribed",
|
||||
name: tr("<b>Unsubscribe from channel</b>"),
|
||||
name: bold(tr("Unsubscribe from channel")),
|
||||
callback: () => this.unsubscribe(),
|
||||
visible: this.flag_subscribed
|
||||
},
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon: "client-subscribe_mode",
|
||||
name: tr("<b>Use inherited subscribe mode</b>"),
|
||||
name: bold(tr("Use inherited subscribe mode")),
|
||||
callback: () => this.unsubscribe(true),
|
||||
visible: this.subscribe_mode != ChannelSubscribeMode.INHERITED
|
||||
}
|
||||
];
|
||||
return [];
|
||||
})(),
|
||||
MenuEntry.HR(),
|
||||
contextmenu.Entry.HR(),
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-channel_edit",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-channel_edit",
|
||||
name: tr("Edit channel"),
|
||||
invalidPermission: !channelModify,
|
||||
callback: () => {
|
||||
|
@ -536,8 +538,8 @@ class ChannelEntry {
|
|||
}
|
||||
},
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-channel_delete",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-channel_delete",
|
||||
name: tr("Delete channel"),
|
||||
invalidPermission: !flagDelete,
|
||||
callback: () => {
|
||||
|
@ -546,10 +548,10 @@ class ChannelEntry {
|
|||
})
|
||||
}
|
||||
},
|
||||
MenuEntry.HR(),
|
||||
contextmenu.Entry.HR(),
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-addon-collection",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-addon-collection",
|
||||
name: tr("Create music bot"),
|
||||
callback: () => {
|
||||
this.channelTree.client.serverConnection.send_command("musicbotcreate", {cid: this.channelId}).then(() => {
|
||||
|
@ -563,21 +565,21 @@ class ChannelEntry {
|
|||
});
|
||||
}
|
||||
},
|
||||
MenuEntry.HR(),
|
||||
contextmenu.Entry.HR(),
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-channel_create_sub",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-channel_create_sub",
|
||||
name: tr("Create sub channel"),
|
||||
invalidPermission: !(channelCreate && this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_CHILD).granted(1)),
|
||||
callback: () => this.channelTree.spawnCreateChannel(this)
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-channel_create",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-channel_create",
|
||||
name: tr("Create channel"),
|
||||
invalidPermission: !channelCreate,
|
||||
callback: () => this.channelTree.spawnCreateChannel()
|
||||
},
|
||||
MenuEntry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||
contextmenu.Entry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -169,20 +169,15 @@ class ClientEntry {
|
|||
});
|
||||
}
|
||||
|
||||
protected assignment_context() : ContextMenuEntry[] {
|
||||
let server_groups: ContextMenuEntry[] = [];
|
||||
protected assignment_context() : contextmenu.MenuEntry[] {
|
||||
let server_groups: contextmenu.MenuEntry[] = [];
|
||||
for(let group of this.channelTree.client.groups.serverGroups.sort(GroupManager.sorter())) {
|
||||
if(group.type != GroupType.NORMAL) continue;
|
||||
|
||||
let entry: ContextMenuEntry = {} as any;
|
||||
|
||||
{
|
||||
let tag = $.spawn("label").addClass("checkbox");
|
||||
$.spawn("input").attr("type", "checkbox").prop("checked", this.groupAssigned(group)).appendTo(tag);
|
||||
$.spawn("span").addClass("checkmark").appendTo(tag);
|
||||
entry.icon = tag;
|
||||
}
|
||||
let entry: contextmenu.MenuEntry = {} as any;
|
||||
|
||||
//TODO: May add the server group icon?
|
||||
entry.checkbox_checked = this.groupAssigned(group);
|
||||
entry.name = group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]";
|
||||
if(this.groupAssigned(group)) {
|
||||
entry.callback = () => {
|
||||
|
@ -201,21 +196,19 @@ class ClientEntry {
|
|||
};
|
||||
entry.disabled = !this.channelTree.client.permissions.neededPermission(PermissionType.I_GROUP_MEMBER_REMOVE_POWER).granted(group.requiredMemberAddPower);
|
||||
}
|
||||
entry.type = MenuEntryType.ENTRY;
|
||||
entry.type = contextmenu.MenuEntryType.CHECKBOX;
|
||||
|
||||
server_groups.push(entry);
|
||||
}
|
||||
|
||||
let channel_groups: ContextMenuEntry[] = [];
|
||||
let channel_groups: contextmenu.MenuEntry[] = [];
|
||||
for(let group of this.channelTree.client.groups.channelGroups.sort(GroupManager.sorter())) {
|
||||
if(group.type != GroupType.NORMAL) continue;
|
||||
|
||||
let entry: ContextMenuEntry = {} as any;
|
||||
{
|
||||
let tag = $.spawn("label").addClass("checkbox");
|
||||
$.spawn("input").attr("type", "checkbox").prop("checked", this.assignedChannelGroup() == group.id).appendTo(tag);
|
||||
$.spawn("span").addClass("checkmark").appendTo(tag);
|
||||
entry.icon = tag;
|
||||
}
|
||||
let entry: contextmenu.MenuEntry = {} as any;
|
||||
|
||||
//TODO: May add the channel group icon?
|
||||
entry.checkbox_checked = this.assignedChannelGroup() == group.id;
|
||||
entry.name = group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]";
|
||||
entry.callback = () => {
|
||||
this.channelTree.client.serverConnection.send_command("setclientchannelgroup", {
|
||||
|
@ -225,17 +218,17 @@ class ClientEntry {
|
|||
});
|
||||
};
|
||||
entry.disabled = !this.channelTree.client.permissions.neededPermission(PermissionType.I_GROUP_MEMBER_ADD_POWER).granted(group.requiredMemberRemovePower);
|
||||
entry.type = MenuEntryType.ENTRY;
|
||||
entry.type = contextmenu.MenuEntryType.CHECKBOX;
|
||||
channel_groups.push(entry);
|
||||
}
|
||||
|
||||
return [{
|
||||
type: MenuEntryType.SUB_MENU,
|
||||
icon: "client-permission_server_groups",
|
||||
type: contextmenu.MenuEntryType.SUB_MENU,
|
||||
icon_class: "client-permission_server_groups",
|
||||
name: tr("Set server group"),
|
||||
sub_menu: [
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon: "client-permission_server_groups",
|
||||
name: "Server groups dialog",
|
||||
callback: () => {
|
||||
|
@ -253,19 +246,19 @@ class ClientEntry {
|
|||
});
|
||||
}
|
||||
},
|
||||
MenuEntry.HR(),
|
||||
contextmenu.Entry.HR(),
|
||||
...server_groups
|
||||
]
|
||||
},{
|
||||
type: MenuEntryType.SUB_MENU,
|
||||
icon: "client-permission_channel",
|
||||
type: contextmenu.MenuEntryType.SUB_MENU,
|
||||
icon_class: "client-permission_channel",
|
||||
name: tr("Set channel group"),
|
||||
sub_menu: [
|
||||
...channel_groups
|
||||
]
|
||||
},{
|
||||
type: MenuEntryType.SUB_MENU,
|
||||
icon: "client-permission_client",
|
||||
type: contextmenu.MenuEntryType.SUB_MENU,
|
||||
icon_class: "client-permission_client",
|
||||
name: tr("Permissions"),
|
||||
disabled: true,
|
||||
sub_menu: [ ]
|
||||
|
@ -274,31 +267,33 @@ class ClientEntry {
|
|||
|
||||
showContextMenu(x: number, y: number, on_close: () => void = undefined) {
|
||||
let trigger_close = true;
|
||||
spawn_context_menu(x, y,
|
||||
contextmenu.spawn_context_menu(x, y,
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Show client info"),
|
||||
callback: () => {
|
||||
trigger_close = false;
|
||||
this.channelTree.client.select_info.open_popover()
|
||||
},
|
||||
icon: "client-about",
|
||||
icon_class: "client-about",
|
||||
visible: this.channelTree.client.select_info.is_popover()
|
||||
}, {
|
||||
type: MenuEntryType.HR,
|
||||
type: contextmenu.MenuEntryType.HR,
|
||||
visible: this.channelTree.client.select_info.is_popover(),
|
||||
name: ''
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-change_nickname",
|
||||
name: tr("<b>Open text chat</b>"),
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-change_nickname",
|
||||
name: (contextmenu.get_provider().html_format_enabled() ? "<b>" : "") +
|
||||
tr("Open text chat") +
|
||||
(contextmenu.get_provider().html_format_enabled() ? "</b>" : ""),
|
||||
callback: () => {
|
||||
this.channelTree.client.chat.activeChat = this.chat(true);
|
||||
this.channelTree.client.chat.focus();
|
||||
}
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-poke",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-poke",
|
||||
name: tr("Poke client"),
|
||||
callback: () => {
|
||||
createInputModal(tr("Poke client"), tr("Poke message:<br>"), text => true, result => {
|
||||
|
@ -314,8 +309,8 @@ class ClientEntry {
|
|||
}, { width: 400, maxLength: 512 }).open();
|
||||
}
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-edit",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-edit",
|
||||
name: tr("Change description"),
|
||||
callback: () => {
|
||||
createInputModal(tr("Change client description"), tr("New description:<br>"), text => true, result => {
|
||||
|
@ -331,11 +326,11 @@ class ClientEntry {
|
|||
}, { width: 400, maxLength: 1024 }).open();
|
||||
}
|
||||
},
|
||||
MenuEntry.HR(),
|
||||
contextmenu.Entry.HR(),
|
||||
...this.assignment_context(),
|
||||
MenuEntry.HR(), {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-move_client_to_own_channel",
|
||||
contextmenu.Entry.HR(), {
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-move_client_to_own_channel",
|
||||
name: tr("Move client to your channel"),
|
||||
callback: () => {
|
||||
this.channelTree.client.serverConnection.send_command("clientmove", {
|
||||
|
@ -344,8 +339,8 @@ class ClientEntry {
|
|||
});
|
||||
}
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-kick_channel",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-kick_channel",
|
||||
name: tr("Kick client from channel"),
|
||||
callback: () => {
|
||||
createInputModal(tr("Kick client from channel"), tr("Kick reason:<br>"), text => true, result => {
|
||||
|
@ -362,8 +357,8 @@ class ClientEntry {
|
|||
}, { width: 400, maxLength: 255 }).open();
|
||||
}
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-kick_server",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-kick_server",
|
||||
name: tr("Kick client fom server"),
|
||||
callback: () => {
|
||||
createInputModal(tr("Kick client from server"), tr("Kick reason:<br>"), text => true, result => {
|
||||
|
@ -380,8 +375,8 @@ class ClientEntry {
|
|||
}, { width: 400, maxLength: 255 }).open();
|
||||
}
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-ban_client",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-ban_client",
|
||||
name: tr("Ban client"),
|
||||
invalidPermission: !this.channelTree.client.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).granted(1),
|
||||
callback: () => {
|
||||
|
@ -398,7 +393,7 @@ class ClientEntry {
|
|||
});
|
||||
}
|
||||
},
|
||||
MenuEntry.HR(),
|
||||
contextmenu.Entry.HR(),
|
||||
/*
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
|
@ -418,8 +413,8 @@ class ClientEntry {
|
|||
MenuEntry.HR(),
|
||||
*/
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-volume",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-volume",
|
||||
name: tr("Change Volume"),
|
||||
callback: () => {
|
||||
Modals.spawnChangeVolume(this._audio_handle.get_volume(), volume => {
|
||||
|
@ -430,7 +425,7 @@ class ClientEntry {
|
|||
});
|
||||
}
|
||||
},
|
||||
MenuEntry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||
contextmenu.Entry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -839,15 +834,18 @@ class LocalClientEntry extends ClientEntry {
|
|||
showContextMenu(x: number, y: number, on_close: () => void = undefined): void {
|
||||
const _self = this;
|
||||
|
||||
spawn_context_menu(x, y,
|
||||
contextmenu.spawn_context_menu(x, y,
|
||||
{
|
||||
name: tr("<b>Change name</b>"),
|
||||
icon: "client-change_nickname",
|
||||
|
||||
name: (contextmenu.get_provider().html_format_enabled() ? "<b>" : "") +
|
||||
tr("Change name") +
|
||||
(contextmenu.get_provider().html_format_enabled() ? "</b>" : ""),
|
||||
icon_class: "client-change_nickname",
|
||||
callback: () =>_self.openRename(),
|
||||
type: MenuEntryType.ENTRY
|
||||
type: contextmenu.MenuEntryType.ENTRY
|
||||
}, {
|
||||
name: tr("Change description"),
|
||||
icon: "client-edit",
|
||||
icon_class: "client-edit",
|
||||
callback: () => {
|
||||
createInputModal(tr("Change own description"), tr("New description:<br>"), text => true, result => {
|
||||
if(result) {
|
||||
|
@ -860,11 +858,11 @@ class LocalClientEntry extends ClientEntry {
|
|||
}
|
||||
}, { width: 400, maxLength: 1024 }).open();
|
||||
},
|
||||
type: MenuEntryType.ENTRY
|
||||
type: contextmenu.MenuEntryType.ENTRY
|
||||
},
|
||||
MenuEntry.HR(),
|
||||
contextmenu.Entry.HR(),
|
||||
...this.assignment_context(),
|
||||
MenuEntry.CLOSE(on_close)
|
||||
contextmenu.Entry.CLOSE(on_close)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -968,23 +966,23 @@ class MusicClientEntry extends ClientEntry {
|
|||
|
||||
showContextMenu(x: number, y: number, on_close: () => void = undefined): void {
|
||||
let trigger_close = true;
|
||||
spawn_context_menu(x, y,
|
||||
contextmenu.spawn_context_menu(x, y,
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Show bot info"),
|
||||
callback: () => {
|
||||
trigger_close = false;
|
||||
this.channelTree.client.select_info.open_popover()
|
||||
},
|
||||
icon: "client-about",
|
||||
icon_class: "client-about",
|
||||
visible: this.channelTree.client.select_info.is_popover()
|
||||
}, {
|
||||
type: MenuEntryType.HR,
|
||||
type: contextmenu.MenuEntryType.HR,
|
||||
visible: this.channelTree.client.select_info.is_popover(),
|
||||
name: ''
|
||||
}, {
|
||||
name: tr("<b>Change bot name</b>"),
|
||||
icon: "client-change_nickname",
|
||||
icon_class: "client-change_nickname",
|
||||
disabled: false,
|
||||
callback: () => {
|
||||
createInputModal(tr("Change music bots nickname"), tr("New nickname:<br>"), text => text.length >= 3 && text.length <= 31, result => {
|
||||
|
@ -997,10 +995,10 @@ class MusicClientEntry extends ClientEntry {
|
|||
}
|
||||
}, { width: 400, maxLength: 255 }).open();
|
||||
},
|
||||
type: MenuEntryType.ENTRY
|
||||
type: contextmenu.MenuEntryType.ENTRY
|
||||
}, {
|
||||
name: tr("Change bot description"),
|
||||
icon: "client-edit",
|
||||
icon_class: "client-edit",
|
||||
disabled: false,
|
||||
callback: () => {
|
||||
createInputModal(tr("Change music bots description"), tr("New description:<br>"), text => true, result => {
|
||||
|
@ -1013,7 +1011,7 @@ class MusicClientEntry extends ClientEntry {
|
|||
}
|
||||
}, { width: 400, maxLength: 255 }).open();
|
||||
},
|
||||
type: MenuEntryType.ENTRY
|
||||
type: contextmenu.MenuEntryType.ENTRY
|
||||
},
|
||||
/*
|
||||
{
|
||||
|
@ -1026,7 +1024,7 @@ class MusicClientEntry extends ClientEntry {
|
|||
*/
|
||||
{
|
||||
name: tr("Open bot's playlist"),
|
||||
icon: "client-edit",
|
||||
icon_class: "client-edit",
|
||||
disabled: false,
|
||||
callback: () => {
|
||||
this.channelTree.client.serverConnection.command_helper.request_playlist_list().then(lists => {
|
||||
|
@ -1041,11 +1039,11 @@ class MusicClientEntry extends ClientEntry {
|
|||
createErrorModal(tr("Failed to query playlist."), tr("Failed to query playlist info.")).open();
|
||||
});
|
||||
},
|
||||
type: MenuEntryType.ENTRY
|
||||
type: contextmenu.MenuEntryType.ENTRY
|
||||
},
|
||||
{
|
||||
name: tr("Quick url replay"),
|
||||
icon: "client-edit",
|
||||
icon_class: "client-edit",
|
||||
disabled: false,
|
||||
callback: () => {
|
||||
createInputModal(tr("Please enter the URL"), tr("URL:"), text => true, result => {
|
||||
|
@ -1064,13 +1062,13 @@ class MusicClientEntry extends ClientEntry {
|
|||
}
|
||||
}, { width: 400, maxLength: 255 }).open();
|
||||
},
|
||||
type: MenuEntryType.ENTRY
|
||||
type: contextmenu.MenuEntryType.ENTRY
|
||||
},
|
||||
MenuEntry.HR(),
|
||||
contextmenu.Entry.HR(),
|
||||
...super.assignment_context(),
|
||||
MenuEntry.HR(),{
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-move_client_to_own_channel",
|
||||
contextmenu.Entry.HR(),{
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-move_client_to_own_channel",
|
||||
name: tr("Move client to your channel"),
|
||||
callback: () => {
|
||||
this.channelTree.client.serverConnection.send_command("clientmove", {
|
||||
|
@ -1079,8 +1077,8 @@ class MusicClientEntry extends ClientEntry {
|
|||
});
|
||||
}
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-kick_channel",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-kick_channel",
|
||||
name: tr("Kick client from channel"),
|
||||
callback: () => {
|
||||
createInputModal(tr("Kick client from channel"), tr("Kick reason:<br>"), text => true, result => {
|
||||
|
@ -1095,10 +1093,10 @@ class MusicClientEntry extends ClientEntry {
|
|||
}, { width: 400, maxLength: 255 }).open();
|
||||
}
|
||||
},
|
||||
MenuEntry.HR(),
|
||||
contextmenu.Entry.HR(),
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-volume",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-volume",
|
||||
name: tr("Change local volume"),
|
||||
callback: () => {
|
||||
Modals.spawnChangeVolume(this._audio_handle.get_volume(), volume => {
|
||||
|
@ -1110,8 +1108,8 @@ class MusicClientEntry extends ClientEntry {
|
|||
}
|
||||
},
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-volume",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-volume",
|
||||
name: tr("Change remote volume"),
|
||||
callback: () => {
|
||||
let max_volume = this.channelTree.client.permissions.neededPermission(PermissionType.I_CLIENT_MUSIC_CREATE_MODIFY_MAX_VOLUME).value;
|
||||
|
@ -1132,10 +1130,10 @@ class MusicClientEntry extends ClientEntry {
|
|||
});
|
||||
}
|
||||
},
|
||||
MenuEntry.HR(),
|
||||
contextmenu.Entry.HR(),
|
||||
{
|
||||
name: tr("Delete bot"),
|
||||
icon: "client-delete",
|
||||
icon_class: "client-delete",
|
||||
disabled: false,
|
||||
callback: () => {
|
||||
const tag = $.spawn("div").append(MessageHelper.formatMessage(tr("Do you really want to delete {0}"), this.createChatTag(false)));
|
||||
|
@ -1147,9 +1145,9 @@ class MusicClientEntry extends ClientEntry {
|
|||
}
|
||||
});
|
||||
},
|
||||
type: MenuEntryType.ENTRY
|
||||
type: contextmenu.MenuEntryType.ENTRY
|
||||
},
|
||||
MenuEntry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||
contextmenu.Entry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
let context_menu: JQuery;
|
||||
namespace contextmenu {
|
||||
export interface MenuEntry {
|
||||
callback?: () => void;
|
||||
type: MenuEntryType;
|
||||
name: (() => string) | string;
|
||||
icon_class?: string;
|
||||
icon_path?: string;
|
||||
disabled?: boolean;
|
||||
visible?: boolean;
|
||||
|
||||
$(document).bind("click", function (e) {
|
||||
let menu = context_menu || (context_menu = $(".context-menu"));
|
||||
checkbox_checked?: boolean;
|
||||
|
||||
if(!menu.is(":visible")) return;
|
||||
|
||||
if ($(e.target).parents(".context-menu").length == 0) {
|
||||
despawn_context_menu();
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
let contextMenuCloseFn = undefined;
|
||||
function despawn_context_menu() {
|
||||
let menu = context_menu || (context_menu = $(".context-menu"));
|
||||
|
||||
if(!menu.is(":visible")) return;
|
||||
menu.animate({opacity: 0}, 100, () => menu.css("display", "none"));
|
||||
if(contextMenuCloseFn) contextMenuCloseFn();
|
||||
invalidPermission?: boolean;
|
||||
sub_menu?: MenuEntry[];
|
||||
}
|
||||
|
||||
enum MenuEntryType {
|
||||
export enum MenuEntryType {
|
||||
CLOSE,
|
||||
ENTRY,
|
||||
CHECKBOX,
|
||||
HR,
|
||||
SUB_MENU
|
||||
}
|
||||
|
||||
class MenuEntry {
|
||||
export class Entry {
|
||||
static HR() {
|
||||
return {
|
||||
callback: () => {},
|
||||
|
@ -47,50 +42,124 @@ class MenuEntry {
|
|||
}
|
||||
}
|
||||
|
||||
interface ContextMenuEntry {
|
||||
callback?: () => void;
|
||||
type: MenuEntryType;
|
||||
name: (() => string) | string;
|
||||
icon?: (() => string) | string | JQuery;
|
||||
disabled?: boolean;
|
||||
visible?: boolean;
|
||||
export interface ContextMenuProvider {
|
||||
despawn_context_menu();
|
||||
spawn_context_menu(x: number, y: number, ...entries: MenuEntry[]);
|
||||
|
||||
invalidPermission?: boolean;
|
||||
sub_menu?: ContextMenuEntry[];
|
||||
initialize();
|
||||
finalize();
|
||||
|
||||
html_format_enabled() : boolean;
|
||||
}
|
||||
|
||||
function generate_tag(entry: ContextMenuEntry) : JQuery {
|
||||
if(entry.type == MenuEntryType.HR) {
|
||||
let provider: ContextMenuProvider;
|
||||
export function spawn_context_menu(x: number, y: number, ...entries: MenuEntry[]) {
|
||||
if(!provider) {
|
||||
console.error(tr("Failed to spawn context menu! Missing provider!"));
|
||||
return;
|
||||
}
|
||||
|
||||
provider.spawn_context_menu(x, y, ...entries);
|
||||
}
|
||||
|
||||
export function despawn_context_menu() {
|
||||
if(!provider)
|
||||
return;
|
||||
|
||||
provider.despawn_context_menu();
|
||||
}
|
||||
|
||||
export function get_provider() : ContextMenuProvider { return provider; }
|
||||
export function set_provider(_provider: ContextMenuProvider) {
|
||||
provider = _provider;
|
||||
provider.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
class HTMLContextMenuProvider implements contextmenu.ContextMenuProvider {
|
||||
private _global_click_listener: (event) => any;
|
||||
private _context_menu: JQuery;
|
||||
private _close_callbacks: (() => any)[] = [];
|
||||
|
||||
despawn_context_menu() {
|
||||
let menu = this._context_menu || (this._context_menu = $(".context-menu"));
|
||||
|
||||
if(!menu.is(":visible"))
|
||||
return;
|
||||
|
||||
menu.animate({opacity: 0}, 100, () => menu.css("display", "none"));
|
||||
for(const callback of this._close_callbacks)
|
||||
callback();
|
||||
this._close_callbacks = [];
|
||||
}
|
||||
|
||||
finalize() {
|
||||
$(document).unbind('click', this._global_click_listener);
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this._global_click_listener = this.on_global_click.bind(this);
|
||||
$(document).bind('click', this._global_click_listener);
|
||||
}
|
||||
|
||||
private on_global_click(event) {
|
||||
let menu = this._context_menu || (this._context_menu = $(".context-menu"));
|
||||
|
||||
if(!menu.is(":visible")) return;
|
||||
|
||||
if ($(event.target).parents(".context-menu").length == 0) {
|
||||
this.despawn_context_menu();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private generate_tag(entry: contextmenu.MenuEntry) : JQuery {
|
||||
if(entry.type == contextmenu.MenuEntryType.HR) {
|
||||
return $.spawn("hr");
|
||||
} else if(entry.type == MenuEntryType.ENTRY) {
|
||||
console.log(entry.icon);
|
||||
let icon = $.isFunction(entry.icon) ? entry.icon() : entry.icon;
|
||||
if(typeof(icon) === "string") {
|
||||
} else if(entry.type == contextmenu.MenuEntryType.ENTRY) {
|
||||
let icon = entry.icon_class;
|
||||
if(!icon || icon.length == 0) icon = "icon_empty";
|
||||
else icon = "icon " + icon;
|
||||
}
|
||||
|
||||
let tag = $.spawn("div").addClass("entry");
|
||||
tag.append(typeof(icon) === "string" ? $.spawn("div").addClass(icon) : icon);
|
||||
tag.append($.spawn("div").addClass(icon));
|
||||
tag.append($.spawn("div").html($.isFunction(entry.name) ? entry.name() : entry.name));
|
||||
|
||||
if(entry.disabled || entry.invalidPermission) tag.addClass("disabled");
|
||||
else {
|
||||
tag.click(function () {
|
||||
if($.isFunction(entry.callback)) entry.callback();
|
||||
despawn_context_menu();
|
||||
tag.click( () => {
|
||||
if($.isFunction(entry.callback))
|
||||
entry.callback();
|
||||
this.despawn_context_menu();
|
||||
});
|
||||
}
|
||||
return tag;
|
||||
} else if(entry.type == MenuEntryType.SUB_MENU) {
|
||||
let icon = $.isFunction(entry.icon) ? entry.icon() : entry.icon;
|
||||
if(typeof(icon) === "string") {
|
||||
} else if(entry.type == contextmenu.MenuEntryType.CHECKBOX) {
|
||||
let checkbox = $.spawn("label").addClass("checkbox");
|
||||
$.spawn("input").attr("type", "checkbox").prop("checked", !!entry.checkbox_checked).appendTo(checkbox);
|
||||
$.spawn("span").addClass("checkmark").appendTo(checkbox);
|
||||
|
||||
let tag = $.spawn("div").addClass("entry");
|
||||
tag.append(checkbox);
|
||||
tag.append($.spawn("div").html($.isFunction(entry.name) ? entry.name() : entry.name));
|
||||
|
||||
if(entry.disabled || entry.invalidPermission)
|
||||
tag.addClass("disabled");
|
||||
else {
|
||||
tag.click( () => {
|
||||
if($.isFunction(entry.callback))
|
||||
entry.callback();
|
||||
this.despawn_context_menu();
|
||||
});
|
||||
}
|
||||
return tag;
|
||||
} else if(entry.type == contextmenu.MenuEntryType.SUB_MENU) {
|
||||
let icon = entry.icon_class;
|
||||
if(!icon || icon.length == 0) icon = "icon_empty";
|
||||
else icon = "icon " + icon;
|
||||
}
|
||||
|
||||
let tag = $.spawn("div").addClass("entry").addClass("sub-container");
|
||||
tag.append(typeof(icon) === "string" ? $.spawn("div").addClass(icon) : icon);
|
||||
tag.append($.spawn("div").addClass(icon));
|
||||
tag.append($.spawn("div").html($.isFunction(entry.name) ? entry.name() : entry.name));
|
||||
|
||||
tag.append($.spawn("div").addClass("arrow right"));
|
||||
|
@ -101,7 +170,7 @@ function generate_tag(entry: ContextMenuEntry) : JQuery {
|
|||
for(const e of entry.sub_menu) {
|
||||
if(typeof(entry.visible) === 'boolean' && !entry.visible)
|
||||
continue;
|
||||
menu.append(generate_tag(e));
|
||||
menu.append(this.generate_tag(e));
|
||||
}
|
||||
menu.appendTo(tag);
|
||||
}
|
||||
|
@ -110,21 +179,21 @@ function generate_tag(entry: ContextMenuEntry) : JQuery {
|
|||
return $.spawn("div").text("undefined");
|
||||
}
|
||||
|
||||
function spawn_context_menu(x, y, ...entries: ContextMenuEntry[]) {
|
||||
let menu_tag = context_menu || (context_menu = $(".context-menu"));
|
||||
spawn_context_menu(x: number, y: number, ...entries: contextmenu.MenuEntry[]) {
|
||||
let menu_tag = this._context_menu || (this._context_menu = $(".context-menu"));
|
||||
menu_tag.finish().empty().css("opacity", "0");
|
||||
|
||||
const menu_container = $.spawn("div").addClass("context-menu-container");
|
||||
contextMenuCloseFn = undefined;
|
||||
this._close_callbacks = [];
|
||||
|
||||
for(const entry of entries){
|
||||
if(typeof(entry.visible) === 'boolean' && !entry.visible)
|
||||
continue;
|
||||
|
||||
if(entry.type == MenuEntryType.CLOSE) {
|
||||
contextMenuCloseFn = entry.callback;
|
||||
if(entry.type == contextmenu.MenuEntryType.CLOSE) {
|
||||
this._close_callbacks.push(entry.callback);
|
||||
} else
|
||||
menu_container.append(generate_tag(entry));
|
||||
menu_container.append(this.generate_tag(entry));
|
||||
}
|
||||
|
||||
menu_tag.append(menu_container);
|
||||
|
@ -140,3 +209,12 @@ function spawn_context_menu(x, y, ...entries: ContextMenuEntry[]) {
|
|||
"left": x + "px"
|
||||
});
|
||||
}
|
||||
|
||||
html_format_enabled(): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Improve
|
||||
if(!window.require)
|
||||
contextmenu.set_provider(new HTMLContextMenuProvider());
|
|
@ -541,17 +541,17 @@ class ControlBar {
|
|||
return;
|
||||
event.preventDefault();
|
||||
|
||||
spawn_context_menu(event.pageX, event.pageY, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
contextmenu.spawn_context_menu(event.pageX, event.pageY, {
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Connect"),
|
||||
icon: 'client-connect',
|
||||
icon_class: 'client-connect',
|
||||
callback: () => bookmark_connect(false)
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Connect in a new tab"),
|
||||
icon: 'client-connect',
|
||||
icon_class: 'client-connect',
|
||||
callback: () => bookmark_connect(true)
|
||||
}, MenuEntry.CLOSE(() => {
|
||||
}, contextmenu.Entry.CLOSE(() => {
|
||||
setTimeout(() => {
|
||||
this.htmlTag.find(".btn_bookmark.button-dropdown").removeClass("force-show")
|
||||
}, 250);
|
||||
|
|
|
@ -455,7 +455,7 @@ class ChannelInfoManager extends InfoManager<ChannelEntry> {
|
|||
properties["channel_name"] = channel.generate_tag(false);
|
||||
properties["channel_type"] = ChannelType.normalize(channel.channelType());
|
||||
properties["channel_clients"] = channel.channelTree.clientsByChannel(channel).length;
|
||||
properties["channel_subscribed"] = true; //TODO
|
||||
properties["channel_subscribed"] = channel.flag_subscribed;
|
||||
properties["server_encryption"] = channel.channelTree.server.properties.virtualserver_codec_encryption_mode;
|
||||
|
||||
for(let key in channel.properties)
|
||||
|
@ -465,16 +465,15 @@ class ChannelInfoManager extends InfoManager<ChannelEntry> {
|
|||
properties["bbcode_channel_description"] = tag_channel_description;
|
||||
|
||||
channel.getChannelDescription().then(description => {
|
||||
let result = XBBCODE.process({
|
||||
text: description,
|
||||
escapeHtml: true,
|
||||
addInLineBreaks: true
|
||||
});
|
||||
const result = xbbcode.parse(description, {});
|
||||
/*
|
||||
if(result.error) {
|
||||
console.log("BBCode parse error: %o", result.errorQueue);
|
||||
}
|
||||
*/
|
||||
|
||||
tag_channel_description.html(result.html)
|
||||
tag_channel_description.empty()
|
||||
.append($.spawn("div").html(result.build_html()).contents())
|
||||
.css("overflow-y", "auto")
|
||||
.css("flex-grow", "1");
|
||||
});
|
||||
|
|
|
@ -245,10 +245,10 @@ class ChatEntry {
|
|||
tag.on("contextmenu", (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
let actions: ContextMenuEntry[] = [];
|
||||
let actions: contextmenu.MenuEntry[] = [];
|
||||
actions.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "",
|
||||
name: tr("Clear"),
|
||||
callback: () => {
|
||||
this.history = [];
|
||||
|
@ -257,23 +257,23 @@ class ChatEntry {
|
|||
});
|
||||
if(this.flag_closeable) {
|
||||
actions.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-tab_close_button",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-tab_close_button",
|
||||
name: tr("Close"),
|
||||
callback: () => this.handle.deleteChat(this)
|
||||
});
|
||||
}
|
||||
|
||||
actions.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-tab_close_button",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-tab_close_button",
|
||||
name: tr("Close all private tabs"),
|
||||
callback: () => {
|
||||
//TODO Implement this?
|
||||
},
|
||||
visible: false
|
||||
});
|
||||
spawn_context_menu(e.pageX, e.pageY, ...actions);
|
||||
contextmenu.spawn_context_menu(e.pageX, e.pageY, ...actions);
|
||||
});
|
||||
|
||||
tag_close.click(() => {
|
||||
|
|
|
@ -181,24 +181,20 @@ namespace unused {
|
|||
if(event.isDefaultPrevented()) return;
|
||||
event.preventDefault();
|
||||
|
||||
spawn_context_menu(event.pageX, event.pageY, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
contextmenu.spawn_context_menu(event.pageX, event.pageY, {
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Expend group"),
|
||||
callback: () => update_collapse_status(true, false)
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Expend all"),
|
||||
callback: () => update_collapse_status(true, true)
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Collapse group"),
|
||||
callback: () => update_collapse_status(false, false)
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Collapse all"),
|
||||
callback: () => update_collapse_status(false, true)
|
||||
});
|
||||
|
|
|
@ -130,14 +130,12 @@ namespace Modals {
|
|||
if(event.isDefaultPrevented()) return;
|
||||
event.preventDefault();
|
||||
|
||||
spawn_context_menu(event.pageX, event.pageY, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
contextmenu.spawn_context_menu(event.pageX, event.pageY, {
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Expend all"),
|
||||
callback: () => this.entry_editor.expend_all()
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Collapse all"),
|
||||
callback: () => this.entry_editor.collapse_all()
|
||||
});
|
||||
|
@ -221,18 +219,16 @@ namespace Modals {
|
|||
};
|
||||
|
||||
entry.on_context_menu = (x, y) => {
|
||||
let entries: ContextMenuEntry[] = [];
|
||||
let entries: contextmenu.MenuEntry[] = [];
|
||||
if(typeof(entry.value) === "undefined") {
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Add permission"),
|
||||
callback: () => entry.trigger_value_assign()
|
||||
});
|
||||
} else {
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Remove permission"),
|
||||
callback: () => {
|
||||
entry.value = undefined;
|
||||
|
@ -243,15 +239,13 @@ namespace Modals {
|
|||
|
||||
if(typeof(entry.granted) === "undefined") {
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Add grant permission"),
|
||||
callback: () => entry.trigger_grant_assign()
|
||||
});
|
||||
} else {
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Remove grant permission"),
|
||||
callback: () => {
|
||||
entry.granted = undefined;
|
||||
|
@ -259,23 +253,20 @@ namespace Modals {
|
|||
}
|
||||
});
|
||||
}
|
||||
entries.push(MenuEntry.HR());
|
||||
entries.push(contextmenu.Entry.HR());
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Expend all"),
|
||||
callback: () => this.entry_editor.expend_all()
|
||||
});
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Collapse all"),
|
||||
callback: () => this.entry_editor.collapse_all()
|
||||
});
|
||||
entries.push(MenuEntry.HR());
|
||||
entries.push(contextmenu.Entry.HR());
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Show permission description"),
|
||||
callback: () => {
|
||||
createInfoModal(
|
||||
|
@ -285,15 +276,14 @@ namespace Modals {
|
|||
}
|
||||
});
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Copy permission name"),
|
||||
callback: () => {
|
||||
copy_to_clipboard(permission.name);
|
||||
}
|
||||
});
|
||||
|
||||
spawn_context_menu(x, y, ...entries);
|
||||
contextmenu.spawn_context_menu(x, y, ...entries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1220,10 +1210,10 @@ namespace Modals {
|
|||
return;
|
||||
|
||||
event.preventDefault();
|
||||
spawn_context_menu(event.pageX, event.pageY, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
contextmenu.spawn_context_menu(event.pageX, event.pageY, {
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Remove client"),
|
||||
icon: 'client-delete',
|
||||
icon_class: 'client-delete',
|
||||
callback: () => {
|
||||
connection.serverConnection.send_command("servergroupdelclient", {
|
||||
sgid: current_group.id,
|
||||
|
@ -1233,9 +1223,9 @@ namespace Modals {
|
|||
});
|
||||
}
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Copy unique id"),
|
||||
icon: 'client-copy',
|
||||
icon_class: 'client-copy',
|
||||
callback: () => copy_to_clipboard(client.client_unique_identifier)
|
||||
})
|
||||
});
|
||||
|
|
|
@ -136,22 +136,22 @@ class ServerEntry {
|
|||
|
||||
spawnContextMenu(x: number, y: number, on_close: () => void = () => {}) {
|
||||
let trigger_close = true;
|
||||
spawn_context_menu(x, y, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
contextmenu.spawn_context_menu(x, y, {
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Show server info"),
|
||||
callback: () => {
|
||||
trigger_close = false;
|
||||
this.channelTree.client.select_info.open_popover()
|
||||
},
|
||||
icon: "client-about",
|
||||
icon_class: "client-about",
|
||||
visible: this.channelTree.client.select_info.is_popover()
|
||||
}, {
|
||||
type: MenuEntryType.HR,
|
||||
type: contextmenu.MenuEntryType.HR,
|
||||
visible: this.channelTree.client.select_info.is_popover(),
|
||||
name: ''
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-virtualserver_edit",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-virtualserver_edit",
|
||||
name: tr("Edit"),
|
||||
callback: () => {
|
||||
Modals.createServerModal(this, properties => {
|
||||
|
@ -164,22 +164,22 @@ class ServerEntry {
|
|||
});
|
||||
}
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-iconviewer",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-iconviewer",
|
||||
name: tr("View icons"),
|
||||
callback: () => Modals.spawnIconSelect(this.channelTree.client)
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: 'client-iconsview',
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: 'client-iconsview',
|
||||
name: tr("View avatars"),
|
||||
callback: () => Modals.spawnAvatarList(this.channelTree.client)
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-invite_buddy",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-invite_buddy",
|
||||
name: tr("Invite buddy"),
|
||||
callback: () => Modals.spawnInviteEditor(this.channelTree.client)
|
||||
},
|
||||
MenuEntry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||
contextmenu.Entry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -90,15 +90,15 @@ class ChannelTree {
|
|||
this.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_SEMI_PERMANENT).granted(1) ||
|
||||
this.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_PERMANENT).granted(1);
|
||||
|
||||
spawn_context_menu(x, y,
|
||||
contextmenu.spawn_context_menu(x, y,
|
||||
{
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-channel_create",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-channel_create",
|
||||
name: tr("Create channel"),
|
||||
invalidPermission: !channelCreate,
|
||||
callback: () => this.spawnCreateChannel()
|
||||
},
|
||||
MenuEntry.CLOSE(on_close)
|
||||
contextmenu.Entry.CLOSE(on_close)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -461,11 +461,11 @@ class ChannelTree {
|
|||
const music_entry = clients.map(e => e instanceof MusicClientEntry ? 1 : 0).reduce((a, b) => a + b, 0) > 0;
|
||||
const local_client = clients.map(e => e instanceof LocalClientEntry ? 1 : 0).reduce((a, b) => a + b, 0) > 0;
|
||||
console.log(tr("Music only: %o | Container music: %o | Container local: %o"), music_entry, music_entry, local_client);
|
||||
let entries: ContextMenuEntry[] = [];
|
||||
let entries: contextmenu.MenuEntry[] = [];
|
||||
if (!music_entry && !local_client) { //Music bots or local client cant be poked
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-poke",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-poke",
|
||||
name: tr("Poke clients"),
|
||||
callback: () => {
|
||||
createInputModal(tr("Poke clients"), tr("Poke message:<br>"), text => true, result => {
|
||||
|
@ -482,8 +482,8 @@ class ChannelTree {
|
|||
});
|
||||
}
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-move_client_to_own_channel",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-move_client_to_own_channel",
|
||||
name: tr("Move clients to your channel"),
|
||||
callback: () => {
|
||||
const target = this.client.getClient().currentChannel().getChannelId();
|
||||
|
@ -495,10 +495,10 @@ class ChannelTree {
|
|||
}
|
||||
});
|
||||
if (!local_client) {//local client cant be kicked and/or banned or kicked
|
||||
entries.push(MenuEntry.HR());
|
||||
entries.push(contextmenu.Entry.HR());
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-kick_channel",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-kick_channel",
|
||||
name: tr("Kick clients from channel"),
|
||||
callback: () => {
|
||||
createInputModal(tr("Kick clients from channel"), tr("Kick reason:<br>"), text => true, result => {
|
||||
|
@ -517,8 +517,8 @@ class ChannelTree {
|
|||
|
||||
if (!music_entry) { //Music bots cant be banned or kicked
|
||||
entries.push({
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-kick_server",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-kick_server",
|
||||
name: tr("Kick clients fom server"),
|
||||
callback: () => {
|
||||
createInputModal(tr("Kick clients from server"), tr("Kick reason:<br>"), text => true, result => {
|
||||
|
@ -534,8 +534,8 @@ class ChannelTree {
|
|||
}, {width: 400, maxLength: 255}).open();
|
||||
}
|
||||
}, {
|
||||
type: MenuEntryType.ENTRY,
|
||||
icon: "client-ban_client",
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-ban_client",
|
||||
name: tr("Ban clients"),
|
||||
invalidPermission: !this.client.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).granted(1),
|
||||
callback: () => {
|
||||
|
@ -555,10 +555,10 @@ class ChannelTree {
|
|||
});
|
||||
}
|
||||
if(music_only) {
|
||||
entries.push(MenuEntry.HR());
|
||||
entries.push(contextmenu.Entry.HR());
|
||||
entries.push({
|
||||
name: tr("Delete bots"),
|
||||
icon: "client-delete",
|
||||
icon_class: "client-delete",
|
||||
disabled: false,
|
||||
callback: () => {
|
||||
const param_string = clients.map((_, index) => "{" + index + "}").join(', ');
|
||||
|
@ -574,11 +574,11 @@ class ChannelTree {
|
|||
}
|
||||
});
|
||||
},
|
||||
type: MenuEntryType.ENTRY
|
||||
type: contextmenu.MenuEntryType.ENTRY
|
||||
});
|
||||
}
|
||||
}
|
||||
spawn_context_menu(event.pageX, event.pageY, ...entries);
|
||||
contextmenu.spawn_context_menu(event.pageX, event.pageY, ...entries);
|
||||
}
|
||||
|
||||
clientsByGroup(group: Group) : ClientEntry[] {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit d9a47d059ae9cce559d7a75553a25ba342d36229
|
||||
Subproject commit 8092afb59615aa19cff372689cd6985c96e3f2ba
|
Loading…
Reference in New Issue