Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cropping support for avatar editing #32565

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,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.

change_password = Update Password
old_password = Current Password
Expand Down
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"chartjs-adapter-dayjs-4": "1.0.4",
"chartjs-plugin-zoom": "2.0.1",
"clippie": "4.1.3",
"cropperjs": "1.6.2",
"css-loader": "7.1.2",
"dayjs": "1.11.13",
"dropzone": "6.0.0-beta.2",
Expand Down
18 changes: 18 additions & 0 deletions templates/user/settings/profile.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,24 @@
<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>

<div class="field">
<button class="ui primary button">{{ctx.Locale.Tr "settings.update_avatar"}}</button>
<button class="ui red button link-action" data-url="{{.Link}}/avatar/delete">{{ctx.Locale.Tr "settings.delete_current_avatar"}}</button>
Expand Down
28 changes: 28 additions & 0 deletions web_src/css/features/cropper.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@import "cropperjs/dist/cropper.css";

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

.cropper-editor {
flex: 1;
max-width: 100%;
overflow: hidden;
.cropper-wrapper {
height: 600px;
max-height: 600px;
}
>div {
display: flex;
column-gap: 10px;
}
}

#cropper-result {
overflow: hidden;
width: 256px;
height: 256px;
max-width: 256px;
max-height: 256px;
}
}
1 change: 1 addition & 0 deletions web_src/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
@import "./features/codeeditor.css";
@import "./features/projects.css";
@import "./features/tribute.css";
@import "./features/cropper.css";
@import "./features/console.css";

@import "./markup/content.css";
Expand Down
61 changes: 61 additions & 0 deletions web_src/js/features/comp/Cropper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import Cropper from 'cropperjs';
kerwin612 marked this conversation as resolved.
Show resolved Hide resolved
import {showElem} from '../../utils/dom.ts';

export function initCompCropper() {
const cropperContainer = document.querySelector('#cropper-panel');
if (!cropperContainer) {
return;
}

let filename;
kerwin612 marked this conversation as resolved.
Show resolved Hide resolved
let cropper;
kerwin612 marked this conversation as resolved.
Show resolved Hide resolved
const source = document.querySelector('#cropper-source');
kerwin612 marked this conversation as resolved.
Show resolved Hide resolved
const result = document.querySelector('#cropper-result');
const input = document.querySelector('#new-avatar');

const done = function (url) {
kerwin612 marked this conversation as resolved.
Show resolved Hide resolved
source.src = url;
result.src = url;

if (cropper) {
cropper.replace(url);
} else {
cropper = new Cropper(source, {
aspectRatio: 1,
viewMode: 1,
autoCrop: false,
crop() {
const canvas = 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;
});
},
});
}
showElem(cropperContainer);
};

input.addEventListener('change', (e) => {
kerwin612 marked this conversation as resolved.
Show resolved Hide resolved
const files = e.target.files;

let reader;
let file;
if (files && files.length > 0) {
kerwin612 marked this conversation as resolved.
Show resolved Hide resolved
file = files[0];
filename = file.name;
if (URL) {
done(URL.createObjectURL(file));
} else if (FileReader) {
reader = new FileReader();
reader.addEventListener('load', () => {
done(reader.result);
});
reader.readAsDataURL(file);
}
kerwin612 marked this conversation as resolved.
Show resolved Hide resolved
}
});
}
2 changes: 2 additions & 0 deletions web_src/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {initRepoRelease, initRepoReleaseNew} from './features/repo-release.ts';
import {initRepoEditor} from './features/repo-editor.ts';
import {initCompSearchUserBox} from './features/comp/SearchUserBox.ts';
import {initInstall} from './features/install.ts';
import {initCompCropper} from './features/comp/Cropper.ts';
import {initCompWebHookEditor} from './features/comp/WebHookEditor.ts';
import {initRepoBranchButton} from './features/repo-branch.ts';
import {initCommonOrganization} from './features/common-organization.ts';
Expand Down Expand Up @@ -137,6 +138,7 @@ onDomReady(() => {

initCompSearchUserBox,
initCompWebHookEditor,
initCompCropper,

initInstall,

Expand Down
Loading