|
@@ -1,69 +1,92 @@
|
|
import { html } from 'lit';
|
|
import { html } from 'lit';
|
|
-import { Model } from '@converse/skeletor';
|
|
|
|
-import { api } from "@converse/headless";
|
|
|
|
|
|
+import { api } from '@converse/headless';
|
|
import { CustomElement } from './element.js';
|
|
import { CustomElement } from './element.js';
|
|
import { __ } from 'i18n';
|
|
import { __ } from 'i18n';
|
|
|
|
+import './styles/image-picker.scss';
|
|
|
|
|
|
const i18n_profile_picture = __('Click to set a new picture');
|
|
const i18n_profile_picture = __('Click to set a new picture');
|
|
-
|
|
|
|
|
|
+const i18n_clear_picture = __('Clear picture');
|
|
|
|
|
|
export default class ImagePicker extends CustomElement {
|
|
export default class ImagePicker extends CustomElement {
|
|
-
|
|
|
|
- constructor () {
|
|
|
|
|
|
+ constructor() {
|
|
super();
|
|
super();
|
|
this.model = null;
|
|
this.model = null;
|
|
this.width = null;
|
|
this.width = null;
|
|
this.height = null;
|
|
this.height = null;
|
|
- this.data = new Model();
|
|
|
|
this.nonce = null;
|
|
this.nonce = null;
|
|
}
|
|
}
|
|
|
|
|
|
- static get properties () {
|
|
|
|
|
|
+ static get properties() {
|
|
return {
|
|
return {
|
|
height: { type: Number },
|
|
height: { type: Number },
|
|
model: { type: Object },
|
|
model: { type: Object },
|
|
width: { type: Number },
|
|
width: { type: Number },
|
|
- }
|
|
|
|
|
|
+ };
|
|
}
|
|
}
|
|
|
|
|
|
- render () {
|
|
|
|
|
|
+ render() {
|
|
return html`
|
|
return html`
|
|
- <a class="change-avatar" @click=${this.openFileSelection} title="${i18n_profile_picture}">
|
|
|
|
- <converse-avatar
|
|
|
|
- .model=${this.model}
|
|
|
|
- .pickerdata=${this.data}
|
|
|
|
- class="avatar"
|
|
|
|
- name="${this.model.getDisplayName()}"
|
|
|
|
- height="${this.height}"
|
|
|
|
- nonce=${this.nonce || this.model.vcard?.get('vcard_updated')}
|
|
|
|
- width="${this.width}"></converse-avatar>
|
|
|
|
- </a>
|
|
|
|
- <input @change=${this.updateFilePreview} class="hidden" name="avatar_image" type="file"/>
|
|
|
|
|
|
+ <div class="image-picker">
|
|
|
|
+ <a class="change-avatar" @click=${this.openFileSelection} title="${i18n_profile_picture}">
|
|
|
|
+ <converse-avatar
|
|
|
|
+ .model=${this.model}
|
|
|
|
+ .pickerdata=${this.data}
|
|
|
|
+ class="avatar"
|
|
|
|
+ name="${this.model.getDisplayName()}"
|
|
|
|
+ height="${this.height}"
|
|
|
|
+ nonce="${this.nonce || this.model.vcard?.get('vcard_updated')}"
|
|
|
|
+ width="${this.width}"
|
|
|
|
+ ></converse-avatar>
|
|
|
|
+ </a>
|
|
|
|
+ ${this.data?.data_uri || this.model?.vcard?.get('image')
|
|
|
|
+ ? html`<button class="clear-image" @click=${this.clearImage} title="${i18n_clear_picture}">
|
|
|
|
+ <converse-icon class="fa fa-trash-alt" size="1.5em"></converse-icon>
|
|
|
|
+ </button>`
|
|
|
|
+ : ''}
|
|
|
|
+ <input @change=${this.updateFilePreview} class="hidden" name="avatar_image" type="file" />
|
|
|
|
+ </div>
|
|
`;
|
|
`;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Clears the selected image.
|
|
|
|
+ * @param {Event} ev
|
|
|
|
+ */
|
|
|
|
+ clearImage(ev) {
|
|
|
|
+ ev.preventDefault();
|
|
|
|
+ const input = /** @type {HTMLInputElement} */(this.querySelector('input[name="avatar_image'));
|
|
|
|
+ input.value = '';
|
|
|
|
+ this.model.vcard.set({
|
|
|
|
+ image: null,
|
|
|
|
+ image_type: null,
|
|
|
|
+ });
|
|
|
|
+ this.data = { data_uri: null, image_type: null };
|
|
|
|
+ this.nonce = new Date().toISOString(); // Update nonce to trigger re-render
|
|
|
|
+ this.requestUpdate();
|
|
|
|
+ }
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* @param {Event} ev
|
|
* @param {Event} ev
|
|
*/
|
|
*/
|
|
- openFileSelection (ev) {
|
|
|
|
|
|
+ openFileSelection(ev) {
|
|
ev.preventDefault();
|
|
ev.preventDefault();
|
|
- /** @type {HTMLInputElement} */(this.querySelector('input[type="file"]')).click();
|
|
|
|
|
|
+ /** @type {HTMLInputElement} */ (this.querySelector('input[type="file"]')).click();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* @param {InputEvent} ev
|
|
* @param {InputEvent} ev
|
|
*/
|
|
*/
|
|
- updateFilePreview (ev) {
|
|
|
|
- const file = /** @type {HTMLInputElement} */(ev.target).files[0];
|
|
|
|
|
|
+ updateFilePreview(ev) {
|
|
|
|
+ const file = /** @type {HTMLInputElement} */ (ev.target).files[0];
|
|
const reader = new FileReader();
|
|
const reader = new FileReader();
|
|
reader.onloadend = () => {
|
|
reader.onloadend = () => {
|
|
- this.data.set({
|
|
|
|
- 'data_uri': reader.result,
|
|
|
|
- 'image_type': file.type
|
|
|
|
- });
|
|
|
|
|
|
+ this.data = {
|
|
|
|
+ data_uri: reader.result,
|
|
|
|
+ image_type: file.type,
|
|
|
|
+ };
|
|
this.nonce = new Date().toISOString();
|
|
this.nonce = new Date().toISOString();
|
|
this.requestUpdate();
|
|
this.requestUpdate();
|
|
- }
|
|
|
|
|
|
+ };
|
|
reader.readAsDataURL(file);
|
|
reader.readAsDataURL(file);
|
|
}
|
|
}
|
|
}
|
|
}
|