Skip to content

Commit ef6dd8d

Browse files
authored
Merge pull request #6554 from WoltLab/6.2-simplify-user-avatar-upload
Simplify user avatar upload
1 parent 1356a82 commit ef6dd8d

File tree

6 files changed

+64
-124
lines changed

6 files changed

+64
-124
lines changed

ts/WoltLabSuite/Core/Component/User/Avatar.ts

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,30 @@ import { dialogFactory } from "WoltLabSuite/Core/Component/Dialog";
1414
import { registerCallback } from "WoltLabSuite/Core/Form/Builder/Field/Controller/FileProcessor";
1515
import WoltlabCoreFile from "WoltLabSuite/Core/Component/File/woltlab-core-file";
1616
import { showDefaultSuccessSnackbar } from "../Snackbar";
17+
import { prepareRequest } from "WoltLabSuite/Core/Ajax/Backend";
18+
import * as FormBuilderManager from "WoltLabSuite/Core/Form/Builder/Manager";
1719

18-
interface Result {
19-
avatar: string;
20-
}
20+
type ResponseGetForm = {
21+
dialog: string;
22+
formId: string;
23+
title: string;
24+
};
25+
26+
let defaultAvatar = "";
2127

2228
async function editAvatar(button: HTMLElement): Promise<void> {
23-
const { ok, result } = await dialogFactory().usingFormBuilder().fromEndpoint<Result>(button.dataset.editAvatar!);
29+
defaultAvatar = button.dataset.defaultAvatar || "";
2430

25-
if (ok) {
26-
const avatarForm = document.getElementById("avatarForm");
27-
if (avatarForm) {
28-
const img = avatarForm.querySelector<HTMLImageElement>("img.userAvatarImage")!;
29-
if (img.src === result.avatar) {
30-
return;
31-
}
31+
const json = (await prepareRequest(button.dataset.editAvatar!).get().fetchAsJson()) as ResponseGetForm;
32+
const dialog = dialogFactory().fromHtml(json.dialog).withoutControls();
3233

33-
// In the ACP, the form should not be reloaded after changing the avatar.
34-
img.src = result.avatar;
35-
showDefaultSuccessSnackbar();
36-
} else {
37-
window.location.reload();
34+
dialog.addEventListener("afterClose", () => {
35+
if (FormBuilderManager.hasForm(json.formId)) {
36+
FormBuilderManager.unregisterForm(json.formId);
3837
}
39-
}
38+
});
39+
40+
dialog.show(json.title);
4041
}
4142

4243
export function setup(): void {
@@ -51,28 +52,32 @@ export function setup(): void {
5152
const avatarForm = document.getElementById("avatarForm");
5253
if (avatarForm) {
5354
registerCallback("wcf\\action\\UserAvatarAction_avatarFileID", (fileId: number | undefined) => {
54-
if (!fileId) {
55-
return;
55+
let link = defaultAvatar;
56+
if (fileId !== undefined) {
57+
const file = document.querySelector<WoltlabCoreFile>(
58+
`#wcf\\\\action\\\\UserAvatarAction_avatarFileIDContainer woltlab-core-file[file-id="${fileId}"]`,
59+
)!;
60+
61+
link = file.link!;
5662
}
5763

58-
const file = document.querySelector<WoltlabCoreFile>(
59-
`#wcf\\\\action\\\\UserAvatarAction_avatarFileIDContainer woltlab-core-file[file-id="${fileId}"]`,
60-
)!;
64+
avatarForm.querySelector<HTMLImageElement>("img.userAvatarImage")!.src = link;
65+
66+
document
67+
.getElementById("wcf\\action\\UserAvatarAction_avatarFileIDContainer")
68+
?.closest("woltlab-core-dialog")
69+
?.close();
6170

62-
avatarForm.querySelector<HTMLImageElement>("img.userAvatarImage")!.src = file.link!;
6371
showDefaultSuccessSnackbar();
6472
});
6573
} else {
66-
registerCallback("wcf\\action\\UserAvatarAction_avatarFileID", (fileId: number | undefined) => {
67-
if (fileId === undefined) {
68-
return;
69-
}
70-
74+
registerCallback("wcf\\action\\UserAvatarAction_avatarFileID", () => {
7175
document
7276
.getElementById("wcf\\action\\UserAvatarAction_avatarFileIDContainer")
7377
?.closest("woltlab-core-dialog")
74-
?.querySelector<HTMLButtonElement>(".dialog__control__button--primary")
75-
?.click();
78+
?.close();
79+
80+
window.location.reload();
7681
});
7782
}
7883

wcfsetup/install/files/acp/templates/userAdd.tpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@
614614
<dl>
615615
<dt></dt>
616616
<dd>
617-
<button type="button" class="button userAvatarManagement" data-edit-avatar="{link controller="UserAvatar" forceFrontend=true id=$user->userID}{/link}">
617+
<button type="button" class="button userAvatarManagement" data-edit-avatar="{link controller="UserAvatar" forceFrontend=true id=$user->userID}{/link}" data-default-avatar="{$__wcf->getPath()}images/avatars/avatar-default.svg">
618618
{lang}wcf.user.avatar.edit{/lang}
619619
</button>
620620
</dd>

wcfsetup/install/files/js/WoltLabSuite/Core/Component/User/Avatar.js

Lines changed: 23 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wcfsetup/install/files/lib/action/UserAvatarAction.class.php

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,16 @@
22

33
namespace wcf\action;
44

5-
use Laminas\Diactoros\Response\JsonResponse;
65
use Psr\Http\Message\ResponseInterface;
76
use Psr\Http\Message\ServerRequestInterface;
87
use Psr\Http\Server\RequestHandlerInterface;
9-
use wcf\data\IStorableObject;
108
use wcf\data\user\UserProfile;
119
use wcf\http\Helper;
1210
use wcf\system\cache\runtime\UserProfileRuntimeCache;
1311
use wcf\system\exception\NamedUserException;
1412
use wcf\system\exception\PermissionDeniedException;
15-
use wcf\system\form\builder\data\processor\CustomFormDataProcessor;
16-
use wcf\system\form\builder\field\dependency\ValueFormFieldDependency;
1713
use wcf\system\form\builder\field\FileProcessorFormField;
18-
use wcf\system\form\builder\field\RadioButtonFormField;
19-
use wcf\system\form\builder\IFormDocument;
2014
use wcf\system\form\builder\Psr15DialogForm;
21-
use wcf\command\user\SetAvatar;
2215
use wcf\system\user\UserProfileHandler;
2316
use wcf\system\WCF;
2417
use wcf\util\HtmlString;
@@ -69,31 +62,6 @@ public function handle(ServerRequestInterface $request): ResponseInterface
6962

7063
if ($request->getMethod() === 'GET') {
7164
return $form->toResponse();
72-
} elseif ($request->getMethod() === 'POST') {
73-
$response = $form->validateRequest($request);
74-
if ($response !== null) {
75-
return $response;
76-
}
77-
78-
$data = $form->getData()['data'];
79-
80-
// If the user has already uploaded and optionally cropped an image,
81-
// this is already assigned to the `$user` and does not need to be saved again.
82-
// However, if the user wants to delete their avatar and use a standard avatar,
83-
// this must be saved and the cache reset
84-
if ($data['avatarType'] === 'none') {
85-
(new SetAvatar($user->getDecoratedObject()))();
86-
}
87-
88-
// Reload the user object to get the updated avatar
89-
UserProfileRuntimeCache::getInstance()->removeObject($user->userID);
90-
$user = UserProfileRuntimeCache::getInstance()->getObject($user->userID);
91-
92-
return new JsonResponse([
93-
'result' => [
94-
'avatar' => $user->getAvatar()->getURL(),
95-
],
96-
]);
9765
} else {
9866
throw new \LogicException('Unreachable');
9967
}
@@ -106,44 +74,14 @@ private function getForm(UserProfile $user): Psr15DialogForm
10674
WCF::getLanguage()->get('wcf.user.avatar.edit')
10775
);
10876
$form->appendChildren([
109-
RadioButtonFormField::create('avatarType')
110-
->value("none")
111-
->required()
112-
->options([
113-
"none" => WCF::getLanguage()->get('wcf.user.avatar.type.none'),
114-
"custom" => WCF::getLanguage()->get('wcf.user.avatar.type.custom'),
115-
]),
11677
FileProcessorFormField::create('avatarFileID')
11778
->objectType('com.woltlab.wcf.user.avatar')
11879
->description('wcf.user.avatar.type.custom.description')
119-
->required()
12080
->singleFileUpload()
12181
->bigPreview()
12282
->simpleReplace()
123-
->hideDeleteButton()
124-
->thumbnailSize('128')
125-
->addDependency(
126-
ValueFormFieldDependency::create('avatarType')
127-
->fieldId('avatarType')
128-
->values(['custom'])
129-
),
83+
->thumbnailSize('128'),
13084
]);
131-
$form->getDataHandler()->addProcessor(
132-
new CustomFormDataProcessor(
133-
'avatarType',
134-
null,
135-
function (IFormDocument $document, array $data, IStorableObject $object) {
136-
\assert($object instanceof UserProfile);
137-
if ($object->avatarFileID === null) {
138-
$data['avatarType'] = 'none';
139-
} else {
140-
$data['avatarType'] = 'custom';
141-
}
142-
143-
return $data;
144-
}
145-
)
146-
);
14785

14886
$form->markRequiredFields(false);
14987
$form->updatedObject($user);

wcfsetup/install/lang/de.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5257,9 +5257,7 @@ Sobald {if LANGUAGE_USE_INFORMAL_VARIANT}dein{else}Ihr{/if} Benutzerkonto freige
52575257
<item name="wcf.user.avatar"><![CDATA[Avatar]]></item>
52585258
<item name="wcf.user.avatar.edit"><![CDATA[Avatar bearbeiten]]></item>
52595259
<item name="wcf.user.avatar.error.disabled"><![CDATA[Der Administrator hat{if $__wcf->user->avatarID} {if LANGUAGE_USE_INFORMAL_VARIANT}deinen{else}Ihren{/if} derzeitigen Avatar gesperrt und{/if} {if LANGUAGE_USE_INFORMAL_VARIANT}dir{else}Ihnen{/if} die weitere Nutzungsberechtigung der Avatar-Funktion {if !$__wcf->user->disableAvatarReason}entzogen.{else} aus folgenden Gründen entzogen: {$__wcf->user->disableAvatarReason}{/if}]]></item>
5260-
<item name="wcf.user.avatar.type.custom"><![CDATA[Eigenen Avatar hochladen]]></item>
52615260
<item name="wcf.user.avatar.type.custom.description"><![CDATA[Eigene Avatare dürfen die Dateiendungen {"\n"|str_replace:', ':$__wcf->session->getPermission('user.profile.avatar.allowedFileExtensions')} besitzen.<br>Die Mindestgröße für Avatare liegt bei 128 × 128 Pixel.]]></item>
5262-
<item name="wcf.user.avatar.type.none"><![CDATA[Keinen Avatar verwenden]]></item>
52635261
</category>
52645262
<category name="wcf.user.condition">
52655263
<item name="wcf.user.condition.activityPoints"><![CDATA[Punkte]]></item>
@@ -5727,5 +5725,7 @@ Erlaubte Dateiendungen: {', '|implode:$allowedFileExtensions}]]></item>
57275725
<item name="wcf.user.option.skype"/>
57285726
<item name="wcf.user.profileHits"/>
57295727
<item name="wcf.user.profileHits.hitsPerDay"/>
5728+
<item name="wcf.user.avatar.type.none"/>
5729+
<item name="wcf.user.avatar.type.custom"/>
57305730
</delete>
57315731
</language>

wcfsetup/install/lang/en.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5256,9 +5256,7 @@ You also received a list of backup codes to use when your second factor becomes
52565256
<item name="wcf.user.avatar"><![CDATA[Avatar]]></item>
52575257
<item name="wcf.user.avatar.edit"><![CDATA[Edit Avatar]]></item>
52585258
<item name="wcf.user.avatar.error.disabled"><![CDATA[The administrators {if $__wcf->user->avatarID}have blocked your avatar and {/if}disallowed you from using an avatar{if $__wcf->user->disableAvatarReason}: {$__wcf->user->disableAvatarReason}{/if}.]]></item>
5259-
<item name="wcf.user.avatar.type.custom"><![CDATA[Upload Your Avatar]]></item>
52605259
<item name="wcf.user.avatar.type.custom.description"><![CDATA[You may use the following file extensions “{"\n"|str_replace:', ':$__wcf->session->getPermission('user.profile.avatar.allowedFileExtensions')}” for your avatar.<br>The minimum dimensions are 128 × 128 pixels.]]></item>
5261-
<item name="wcf.user.avatar.type.none"><![CDATA[Do Not Use Avatar]]></item>
52625260
</category>
52635261
<category name="wcf.user.condition">
52645262
<item name="wcf.user.condition.activityPoints"><![CDATA[Points]]></item>
@@ -5729,5 +5727,7 @@ Allowed extensions: {', '|implode:$allowedFileExtensions}]]></item>
57295727
<item name="wcf.user.option.skype"/>
57305728
<item name="wcf.user.profileHits"/>
57315729
<item name="wcf.user.profileHits.hitsPerDay"/>
5730+
<item name="wcf.user.avatar.type.none"/>
5731+
<item name="wcf.user.avatar.type.custom"/>
57325732
</delete>
57335733
</language>

0 commit comments

Comments
 (0)