feat(circle-details): allow setting avatar image for circle#5293
feat(circle-details): allow setting avatar image for circle#5293cristianscheid wants to merge 1 commit into
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
2a114c1 to
eb90eef
Compare
|
@kra-mo following your suggestion: I positioned the avatar buttons beneath the name and description in edit mode and styled them closer to the reference in this issue. The PR description has been updated with screenshots and a short video showing the current state. Two questions I'd appreciate your input on:
Besides that, I'm also aware that probably a spacing between the buttons is needed and also some margin from the main edit mode "Cancel" and "Save" buttons. Just waiting for another round of input before moving forward. Any other thoughts are welcome :) |
eb90eef to
a5892d4
Compare
The widths should definitely be homogeneous. They should also have margins between them.
Since there is a "Cancel" button, the second behavior makes more sense. |
927fa24 to
a7b202b
Compare
|
@kra-mo thanks for the input, really appreciated! I've adopted your suggestions and updated the implementation. Also updated the main comment of this PR with new screenshots and a short video demoing the current state. Would appreciate if you could take a look at it and share your thoughts. |
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
a7b202b to
ccadcf6
Compare
| 'circle.id': { | ||
| handler() { | ||
| this.fetchTeamResources() | ||
| this.loadAvatarUrl() |
There was a problem hiding this comment.
If I start editing one team, pick a picture, then click another team in the sidebar before saving, the pending blob carries over and saves to the wrong team. Watcher should call clearPendingAvatar() (and probably reset isEditing too) when the id actually changes.
| v-bind="cropperOptions" /> | ||
| <div class="circle-avatar-cropper-buttons"> | ||
| <NcButton @click="cancelSetAvatar"> | ||
| {{ t('settings', 'Cancel') }} |
There was a problem hiding this comment.
These three (Cancel, Apply, Error cropping avatar picture) are still in the settings domain. I might be wrong but I suspect won't be picked up by the contacts gettext catalog, so they stay English regardless of locale. Should be t('contacts', ...) maybe?
| async onAvatarInputChange(e) { | ||
| try { | ||
| const file = e.target.files[0] | ||
| if (!['image/png', 'image/jpeg'].includes(file.type)) { |
There was a problem hiding this comment.
You already have VALID_MIME_TYPES at the top of the file, can we use it here too? Otherwise the picker filter and this check can drift.
| const canvasData = this.$refs.cropper.getCroppedCanvas() | ||
| const scaleFactor = canvasData.width > 512 ? 512 / canvasData.width : 1 | ||
|
|
||
| this.$refs.cropper.scale(scaleFactor, scaleFactor).getCroppedCanvas().toBlob(async (blob) => { |
There was a problem hiding this comment.
Cropper has getCroppedCanvas({ maxWidth: 512, maxHeight: 512 }) for exactly this, no need to mutate the cropper state. Same approach is used in ContactDetailsAvatar.vue around line 425.
| </NcButton> | ||
| <input | ||
| ref="avatarInput" | ||
| type="file" |
There was a problem hiding this comment.
Worth setting accept="image/png,image/jpeg" here so the native OS dialog only shows valid files. Cheap UX improvement, and the MIME check stays as the actual gate. Not a blocker for this PR though :)
One way to do it could be in setup:
setup() {
const avatarList = ref()
const { width } = useElementSize(avatarList)
return { avatarList, width, avatarAccept: VALID_MIME_TYPES.join(',') }
}and then
<input
ref="avatarInput"
type="file"
:accept="avatarAccept"
class="hidden-visually"
@change="onAvatarInputChange">| this.loadAvatarUrl() | ||
| } catch { | ||
| console.error('Unable to save avatar picture') | ||
| errors.push('avatar') |
There was a problem hiding this comment.
This is untranslated, but so are the existing name and description fields. If you have time it could be good to fix them, but not blocking for PR
| const picker = getFilePickerBuilder(t('contacts', 'Choose a team picture')) | ||
| .setMultiSelect(false) | ||
| .setMimeTypeFilter(VALID_MIME_TYPES) | ||
| .setType(1) |
There was a problem hiding this comment.
afaik FilePickerType.Choose is exported from @nextcloud/dialogs. Reads better and won't silently break if the underlying values ever shift
Summary
Screenshots
demo.webm