Added the possibility to select icons within the permission editor
parent
c0601d4682
commit
64fce4f3c6
|
@ -591,15 +591,31 @@ class IconManager {
|
|||
}
|
||||
}
|
||||
|
||||
loadIcon(id: number) : Promise<Icon> {
|
||||
download_icon(id: number) : Promise<Icon> {
|
||||
return this._loading_promises[id] || (this._loading_promises[id] = this._load_icon(id));
|
||||
}
|
||||
|
||||
async resolve_icon(id: number) : Promise<Icon> {
|
||||
id = id >>> 0;
|
||||
try {
|
||||
return await this.resolved_cached(id);
|
||||
} catch(error) { }
|
||||
|
||||
try {
|
||||
return await this.download_icon(id);
|
||||
} catch(error) {
|
||||
console.error(tr("Icon download failed of icon %d: %o"), id, error);
|
||||
}
|
||||
|
||||
throw "icon not found";
|
||||
}
|
||||
|
||||
generateTag(id: number, options?: {
|
||||
animate?: boolean
|
||||
}) : JQuery<HTMLDivElement> {
|
||||
options = options || {};
|
||||
|
||||
id = id >>> 0;
|
||||
if(id == 0)
|
||||
return $.spawn("div").addClass("icon_empty");
|
||||
else if(id < 1000)
|
||||
|
@ -617,18 +633,7 @@ class IconManager {
|
|||
icon_load_image.appendTo(icon_container);
|
||||
|
||||
(async () => {
|
||||
let icon: Icon;
|
||||
try {
|
||||
icon = await this.resolved_cached(id);
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
if(!icon)
|
||||
icon = await this.loadIcon(id);
|
||||
|
||||
if(!icon)
|
||||
throw "failed to download icon";
|
||||
let icon: Icon = await this.resolve_icon(id);
|
||||
|
||||
icon_image.attr("src", icon.url);
|
||||
icon_container.append(icon_image).removeClass("icon_empty");
|
||||
|
|
|
@ -65,6 +65,9 @@ namespace Modals {
|
|||
|
||||
private entry_editor: ui.PermissionEditor;
|
||||
|
||||
icon_resolver: (id: number) => Promise<HTMLImageElement>;
|
||||
icon_selector: (current_id: number) => Promise<number>;
|
||||
|
||||
constructor(permissions: GroupedPermissions[]) {
|
||||
this.permissions = permissions;
|
||||
this.entry_editor = new ui.PermissionEditor(permissions);
|
||||
|
@ -167,6 +170,15 @@ namespace Modals {
|
|||
element.flag_negate = entry.flag_negate;
|
||||
}
|
||||
|
||||
if(permission.name === "i_icon_id") {
|
||||
this.icon_resolver(entry.value).then(e => {
|
||||
entry.set_icon_id_image(e);
|
||||
entry.request_full_draw();
|
||||
this.entry_editor.request_draw(false);
|
||||
}).catch(error => {
|
||||
console.warn(tr("Failed to load icon for permission editor: %o"), error);
|
||||
});
|
||||
}
|
||||
entry.request_full_draw();
|
||||
this.entry_editor.request_draw(false);
|
||||
}).catch(() => {
|
||||
|
@ -301,10 +313,21 @@ namespace Modals {
|
|||
entry.value = value.value;
|
||||
entry.flag_skip = value.flag_skip;
|
||||
entry.flag_negate = value.flag_negate;
|
||||
if(permission.name === "i_icon_id") {
|
||||
this.icon_resolver(value.value).then(e => {
|
||||
entry.set_icon_id_image(e);
|
||||
entry.request_full_draw();
|
||||
this.entry_editor.request_draw(false);
|
||||
}).catch(error => {
|
||||
console.warn(tr("Failed to load icon for permission editor: %o"), error);
|
||||
});
|
||||
entry.on_icon_select = this.icon_selector;
|
||||
}
|
||||
} else {
|
||||
entry.value = undefined;
|
||||
entry.flag_skip = false;
|
||||
entry.flag_negate = false;
|
||||
entry.set_icon_id_image(undefined);
|
||||
}
|
||||
|
||||
if(value && value.hasGrant()) {
|
||||
|
@ -353,6 +376,22 @@ namespace Modals {
|
|||
let tag = $("#tmpl_server_permissions").renderTag(properties);
|
||||
const pe = new PermissionEditor(connection.permissions.groupedPermissions());
|
||||
pe.build_tag();
|
||||
pe.icon_resolver = id => connection.fileManager.icons.resolve_icon(id).then(async icon => {
|
||||
if(!icon)
|
||||
return undefined;
|
||||
|
||||
const tag = document.createElement("img");
|
||||
await new Promise((resolve, reject) => {
|
||||
tag.onerror = reject;
|
||||
tag.onload = resolve;
|
||||
tag.src = icon.url;
|
||||
});
|
||||
return tag;
|
||||
});
|
||||
pe.icon_selector = current_icon => new Promise<number>(resolve => {
|
||||
spawnIconSelect(connection, id => resolve(new Int32Array([id])[0]), current_icon);
|
||||
});
|
||||
|
||||
/* initialisation */
|
||||
{
|
||||
const pe_server = tag.find("permission-editor.group-server");
|
||||
|
@ -972,6 +1011,7 @@ namespace Modals {
|
|||
let current_group;
|
||||
|
||||
/* list all groups */
|
||||
let update_icon: (icon_id: number) => any;
|
||||
{
|
||||
let group_list = tab_tag.find(".list-group-server .entries");
|
||||
|
||||
|
@ -986,7 +1026,10 @@ namespace Modals {
|
|||
continue;
|
||||
}
|
||||
let tag = $.spawn("div").addClass("group").attr("group-id", group.id);
|
||||
connection.fileManager.icons.generateTag(group.properties.iconid).appendTo(tag);
|
||||
let icon_tag = connection.fileManager.icons.generateTag(group.properties.iconid);
|
||||
icon_tag.appendTo(tag);
|
||||
const _update_icon = icon_id => icon_tag.replaceWith(icon_tag = connection.fileManager.icons.generateTag(icon_id));
|
||||
|
||||
{
|
||||
let name = $.spawn("a").text(group.name + " (" + group.id + ")").addClass("name");
|
||||
if(group.properties.savedb)
|
||||
|
@ -999,6 +1042,7 @@ namespace Modals {
|
|||
|
||||
tag.on('click', event => {
|
||||
current_group = group;
|
||||
update_icon = _update_icon;
|
||||
group_list.find(".selected").removeClass("selected");
|
||||
tag.addClass("selected");
|
||||
editor.trigger_update();
|
||||
|
@ -1042,6 +1086,10 @@ namespace Modals {
|
|||
return connection.serverConnection.send_command("servergroupdelperm", {
|
||||
sgid: current_group.id,
|
||||
permid: permission.id,
|
||||
}).then(e => {
|
||||
if(permission.name === "i_icon_id" && update_icon)
|
||||
update_icon(0);
|
||||
return e;
|
||||
});
|
||||
} else {
|
||||
log.info(LogCategory.PERMISSIONS, tr("Removing server group grant permission %s. permission.id: %o"),
|
||||
|
@ -1072,6 +1120,10 @@ namespace Modals {
|
|||
permvalue: value.value,
|
||||
permskip: value.flag_skip,
|
||||
permnegate: value.flag_negate
|
||||
}).then(e => {
|
||||
if(permission.name === "i_icon_id" && update_icon)
|
||||
update_icon(value.value);
|
||||
return e;
|
||||
});
|
||||
} else {
|
||||
log.info(LogCategory.PERMISSIONS, tr("Adding or updating server group grant permission %s. permission.{id: %o, value: %o}"),
|
||||
|
|
|
@ -459,7 +459,9 @@ namespace ui {
|
|||
private _listener_value: InteractionListener;
|
||||
private _listener_grant: InteractionListener;
|
||||
private _listener_general: InteractionListener;
|
||||
private _icon_image: HTMLImageElement | undefined;
|
||||
|
||||
on_icon_select?: (current_id: number) => Promise<number>;
|
||||
on_context_menu?: (x: number, y: number) => any;
|
||||
on_grant_change?: () => any;
|
||||
on_change?: () => any;
|
||||
|
@ -469,6 +471,16 @@ namespace ui {
|
|||
this._permission = permission;
|
||||
}
|
||||
|
||||
set_icon_id_image(image: HTMLImageElement | undefined) {
|
||||
if(this._icon_image === image)
|
||||
return;
|
||||
this._icon_image = image;
|
||||
if(image) {
|
||||
image.height = 16;
|
||||
image.width = 16;
|
||||
}
|
||||
}
|
||||
|
||||
permission() { return this._permission; }
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D, full: boolean) {
|
||||
|
@ -561,11 +573,19 @@ namespace ui {
|
|||
const x = w + PermissionEntry.COLUMN_VALUE - PermissionEntry.CHECKBOX_HEIGHT;
|
||||
const y = 1;
|
||||
|
||||
this._listener_value.region.width = PermissionEntry.CHECKBOX_HEIGHT;
|
||||
this._listener_value.region.x = original_x + x;
|
||||
this._listener_value.region.y = original_y + y;
|
||||
|
||||
this._draw_checkbox_field(ctx, this.colors.permission.value_b, x, y, PermissionEntry.CHECKBOX_HEIGHT, this.value > 0, this.flag_value_hovered);
|
||||
} else if(this._permission.name === "i_icon_id" && this._icon_image) {
|
||||
this._listener_value.region.x = original_x + w;
|
||||
this._listener_value.region.y = original_y;
|
||||
this._listener_value.region.width = PermissionEntry.CHECKBOX_HEIGHT;
|
||||
|
||||
this._draw_icon_field(ctx, this.colors.permission.value_b, w, 0, PermissionEntry.COLUMN_VALUE, this.flag_value_hovered, this._icon_image);
|
||||
} else {
|
||||
this._listener_value.region.width = PermissionEntry.COLUMN_VALUE;
|
||||
this._listener_value.region.x = original_x + w;
|
||||
this._listener_value.region.y = original_y;
|
||||
|
||||
|
@ -600,6 +620,20 @@ namespace ui {
|
|||
this._listener_general.region.x = -1e8;
|
||||
}
|
||||
|
||||
private _draw_icon_field(ctx: CanvasRenderingContext2D, scheme: scheme.CheckBox, x: number, y: number, width: number, hovered: boolean, image: HTMLImageElement) {
|
||||
const line = ctx.lineWidth;
|
||||
ctx.lineWidth = 2;
|
||||
ctx.fillStyle = scheme.border;
|
||||
ctx.strokeRect(x + 1, y + 1, PermissionEntry.HEIGHT - 2, PermissionEntry.HEIGHT - 2);
|
||||
ctx.lineWidth = line;
|
||||
|
||||
ctx.fillStyle = hovered ? scheme.background_hovered : scheme.background;
|
||||
ctx.fillRect(x + 1, y + 1, PermissionEntry.HEIGHT - 2, PermissionEntry.HEIGHT - 2);
|
||||
|
||||
const center_y = y + PermissionEntry.HEIGHT / 2;
|
||||
const center_x = x + PermissionEntry.HEIGHT / 2;
|
||||
ctx.drawImage(image, center_x - image.width / 2, center_y - image.height / 2);
|
||||
}
|
||||
|
||||
private _draw_number_field(ctx: CanvasRenderingContext2D, scheme: scheme.TextField, x: number, y: number, width: number, value: number, hovered: boolean) {
|
||||
ctx.fillStyle = hovered ? scheme.background_hovered : scheme.background;
|
||||
|
@ -721,6 +755,14 @@ namespace ui {
|
|||
if(this.on_change)
|
||||
this.on_change();
|
||||
return RepaintMode.REPAINT_OBJECT_FULL;
|
||||
} else if(this._permission.name === "i_icon_id") {
|
||||
this.on_icon_select(this.value).then(value => {
|
||||
this.value = value;
|
||||
if(this.on_change)
|
||||
this.on_change();
|
||||
}).catch(error => {
|
||||
console.warn(tr("Failed to select icon: %o"), error);
|
||||
})
|
||||
} else {
|
||||
this._spawn_number_edit(
|
||||
this._listener_value.region.x,
|
||||
|
|
Loading…
Reference in New Issue