Skip to content

Commit

Permalink
improve
Browse files Browse the repository at this point in the history
  • Loading branch information
wxiaoguang committed Nov 27, 2024
1 parent ea2a23c commit 5f893c3
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 89 deletions.
2 changes: 1 addition & 1 deletion options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ uploaded_avatar_not_a_image = The uploaded file is not an image.
uploaded_avatar_is_too_big = The uploaded file size (%d KiB) exceeds the maximum size (%d KiB).
update_avatar_success = Your avatar has been updated.
update_user_avatar_success = The user's avatar has been updated.
cropper_prompt = Note: The saved image format after cropping is unified as PNG.
cropper_prompt = You could edit the avatar image before saving, edited image will be saved as PNG.

change_password = Update Password
old_password = Current Password
Expand Down
19 changes: 3 additions & 16 deletions templates/user/settings/profile.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -127,22 +127,9 @@
<input id="new-avatar" name="avatar" type="file" accept="image/png,image/jpeg,image/gif,image/webp">
</div>

<div class="inline field cropper-panel tw-hidden" id="cropper-panel">
<div class="cropper-preview">
<h3>{{ctx.Locale.Tr "preview"}}</h3>
<div>
<img id="cropper-result" class="ui avatar tw-align-middle">
</div>
</div>
<div class="cropper-editor">
<div>
<h3>{{ctx.Locale.Tr "edit"}}</h3>
<span>{{ctx.Locale.Tr "settings.cropper_prompt"}}</span>
</div>
<div class="cropper-wrapper">
<img class="tw-hidden" id="cropper-source">
</div>
</div>
<div class="field tw-pl-4 cropper-panel tw-hidden">
<div>{{ctx.Locale.Tr "settings.cropper_prompt"}}</div>
<div class="cropper-wrapper"><img class="cropper-source" src alt></div>
</div>

<div class="field">
Expand Down
36 changes: 3 additions & 33 deletions web_src/css/features/cropper.css
Original file line number Diff line number Diff line change
@@ -1,36 +1,6 @@
@import "cropperjs/dist/cropper.css";

.cropper-panel {
display: flex;
flex-wrap: wrap;
column-gap: 10px;
}

.cropper-panel h3 {
word-break: keep-all;
}

.cropper-panel #cropper-result {
overflow: hidden;
width: 256px;
height: 256px;
max-width: 256px;
max-height: 256px;
}

.cropper-panel .cropper-editor {
flex: 1;
min-width: 300px;
max-width: 100%;
overflow: hidden;
}

.cropper-panel .cropper-editor >div {
display: flex;
column-gap: 10px;
}

.cropper-panel .cropper-editor .cropper-wrapper {
height: 600px;
max-height: 600px;
.page-content.user.profile .cropper-panel .cropper-wrapper {
max-width: 400px;
max-height: 400px;
}
65 changes: 28 additions & 37 deletions web_src/js/features/comp/Cropper.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,39 @@
import {showElem} from '../../utils/dom.ts';

export async function initCompCropper() {
const cropperContainer = document.querySelector('#cropper-panel');
if (!cropperContainer) {
return;
}
type CropperOpts = {
container: HTMLElement,
imageSource: HTMLImageElement,
fileInput: HTMLInputElement,
}

export async function initCompCropper({container, fileInput, imageSource}:CropperOpts) {
const {default: Cropper} = await import(/* webpackChunkName: "cropperjs" */'cropperjs');

const source = document.querySelector('#cropper-source');
const result = document.querySelector('#cropper-result');
const input = document.querySelector('#new-avatar');

const done = function (url: string, filename: string): void {
source.src = url;
result.src = url;

if (input._cropper) {
input._cropper.replace(url);
} else {
input._cropper = new Cropper(source, {
aspectRatio: 1,
viewMode: 1,
autoCrop: false,
crop() {
const canvas = input._cropper.getCroppedCanvas();
result.src = canvas.toDataURL();
canvas.toBlob((blob) => {
const file = new File([blob], filename, {type: 'image/png', lastModified: Date.now()});
const container = new DataTransfer();
container.items.add(file);
input.files = container.files;
});
},
let currentFileName = '', currentFileLastModified = 0;
const cropper = new Cropper(imageSource, {
aspectRatio: 1,
viewMode: 2,
autoCrop: false,
crop() {
const canvas = cropper.getCroppedCanvas();
canvas.toBlob((blob) => {
const croppedFileName = currentFileName.replace(/\.[^.]{3,4}$/, '.png');
const croppedFile = new File([blob], croppedFileName, {type: 'image/png', lastModified: currentFileLastModified});
const dataTransfer = new DataTransfer();
dataTransfer.items.add(croppedFile);
fileInput.files = dataTransfer.files;
});
}
showElem(cropperContainer);
};
},
});

input.addEventListener('change', (e: Event & {target: HTMLInputElement}) => {
fileInput.addEventListener('input', (e: Event & {target: HTMLInputElement}) => {
const files = e.target.files;

if (files?.length > 0) {
done(URL.createObjectURL(files[0]), files[0].name);
currentFileName = files[0].name;
currentFileLastModified = files[0].lastModified;
const fileURL = URL.createObjectURL(files[0]);
imageSource.src = fileURL;
cropper.replace(fileURL);
showElem(container);
}
});
}
12 changes: 10 additions & 2 deletions web_src/js/features/user-settings.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import {hideElem, showElem} from '../utils/dom.ts';
import {initCompCropper} from './comp/Cropper.ts';

function initUserSettingsAvatarCropper() {
const fileInput = document.querySelector<HTMLInputElement>('#new-avatar');
const container = document.querySelector<HTMLElement>('.user.settings.profile .cropper-panel');
const imageSource = container.querySelector<HTMLImageElement>('.cropper-source');
initCompCropper({container, fileInput, imageSource});
}

export function initUserSettings() {
if (!document.querySelectorAll('.user.settings.profile').length) return;
initCompCropper();
if (!document.querySelector('.user.settings.profile')) return;

initUserSettingsAvatarCropper();

const usernameInput = document.querySelector('#username');
if (!usernameInput) return;
Expand Down

0 comments on commit 5f893c3

Please sign in to comment.