Added the possibility to select icons within the permission editor

canary
WolverinDEV 2019-05-25 12:20:57 +02:00
parent c0601d4682
commit 64fce4f3c6
3 changed files with 113 additions and 14 deletions

View File

@ -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");

View File

@ -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}"),

View File

@ -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,