diff --git a/app/components/ImageCropModal.vue b/app/components/ImageCropModal.vue new file mode 100644 index 0000000..3b76d80 --- /dev/null +++ b/app/components/ImageCropModal.vue @@ -0,0 +1,156 @@ + + + diff --git a/app/pages/me/profile/index.vue b/app/pages/me/profile/index.vue index e01e975..5638bfa 100644 --- a/app/pages/me/profile/index.vue +++ b/app/pages/me/profile/index.vue @@ -48,6 +48,16 @@ const uploadingHeaderIcon = ref(false) const avatarFileInput = ref(null) const headerIconFileInput = ref(null) +const imageCropOpen = ref(false) +const imageCropFile = ref(null) +const imageCropVariant = ref<'avatar' | 'headerIcon'>('avatar') + +watch(imageCropOpen, (isOpen) => { + if (!isOpen) { + imageCropFile.value = null + } +}) + const BIO_PREVIEW_MAX_CHARS = 200 const bioModalOpen = ref(false) const bioDraft = ref('') @@ -83,13 +93,31 @@ function openHeaderIconPicker() { headerIconFileInput.value?.click() } -async function onAvatarFileChange(ev: Event) { +function onAvatarFileChange(ev: Event) { + const input = ev.target as HTMLInputElement + const file = input.files?.[0] + input.value = '' + if (!file) { + return + } + imageCropVariant.value = 'avatar' + imageCropFile.value = file + imageCropOpen.value = true +} + +function onHeaderIconFileChange(ev: Event) { const input = ev.target as HTMLInputElement const file = input.files?.[0] input.value = '' if (!file) { return } + imageCropVariant.value = 'headerIcon' + imageCropFile.value = file + imageCropOpen.value = true +} + +async function uploadCroppedAvatar(file: File) { uploadingAvatar.value = true try { const form = new FormData() @@ -113,13 +141,7 @@ async function onAvatarFileChange(ev: Event) { } } -async function onHeaderIconFileChange(ev: Event) { - const input = ev.target as HTMLInputElement - const file = input.files?.[0] - input.value = '' - if (!file) { - return - } +async function uploadCroppedHeaderIcon(file: File) { uploadingHeaderIcon.value = true try { const form = new FormData() @@ -143,6 +165,14 @@ async function onHeaderIconFileChange(ev: Event) { } } +async function onImageCropConfirm(file: File) { + if (imageCropVariant.value === 'avatar') { + await uploadCroppedAvatar(file) + } else { + await uploadCroppedHeaderIcon(file) + } +} + async function load() { loading.value = true try { @@ -388,6 +418,13 @@ async function save() { + +