Fallback to avatar

Signed-off-by: Vitor Mattos <vitor@php.rio>
This commit is contained in:
Vitor Mattos 2022-11-10 16:20:41 -03:00 committed by Joas Schilling
parent 73e50aff99
commit 9a381b6ad3
No known key found for this signature in database
GPG key ID: 74434EFE0D2E2205
4 changed files with 128 additions and 33 deletions

View file

@ -414,7 +414,6 @@
* Response:
- Status code:
+ `200 OK`
+ `400 Bad Request` When the conversation haven't an avatar
+ `404 Not Found` When the conversation could not be found for the participant
* Required capability: `avatar`

View file

@ -28,6 +28,7 @@ namespace OCA\Talk\Controller;
use InvalidArgumentException;
use OC\Files\Filesystem;
use OCA\Talk\Service\AvatarService;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\FileDisplayResponse;
@ -36,19 +37,26 @@ use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\IL10N;
use OCP\IRequest;
use OCP\IUserSession;
class AvatarController extends AEnvironmentAwareController {
private IAppData $appData;
private AvatarService $avatarService;
private IUserSession $userSession;
private IL10N $l;
public function __construct(
string $appName,
IRequest $request,
IAppData $appData,
AvatarService $avatarService,
IUserSession $userSession,
IL10N $l10n
) {
parent::__construct($appName, $request);
$this->appData = $appData;
$this->avatarService = $avatarService;
$this->userSession = $userSession;
$this->l = $l10n;
}
@ -94,7 +102,12 @@ class AvatarController extends AEnvironmentAwareController {
}
$mimeType = $image->mimeType();
if ($mimeType !== 'image/jpeg' && $mimeType !== 'image/png') {
$allowedMimeTypes = [
'image/jpeg',
'image/png',
'image/svg',
];
if (!in_array($mimeType, $allowedMimeTypes)) {
throw new InvalidArgumentException($this->l->t('Unknown filetype'));
}
@ -104,8 +117,7 @@ class AvatarController extends AEnvironmentAwareController {
$folder = $this->appData->newFolder('room-avatar');
}
$token = $this->getRoom()->getToken();
$extension = explode('/', $mimeType)[1];
$folder->newFile($token . '.' . $extension, $image->data());
$folder->newFile($token, $image->data());
return new DataResponse();
} catch (InvalidArgumentException $e) {
return new DataResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
@ -122,21 +134,8 @@ class AvatarController extends AEnvironmentAwareController {
* @PublicPage
* @RequireParticipant
*/
public function getAvatar(?bool $dark = false): Response {
try {
$folder = $this->appData->getFolder('room-avatar');
} catch (NotFoundException $e) {
$folder = $this->appData->newFolder('room-avatar');
}
$token = $this->getRoom()->getToken();
if ($folder->fileExists($token . '.png')) {
$file = $folder->getFile($token . '.png');
} elseif ($folder->fileExists($token . '.jpeg')) {
$file = $folder->getFile($token . '.jpeg');
} else {
// @todo Implement fallback images
return new DataResponse([], Http::STATUS_NOT_FOUND);
}
public function getAvatar(bool $dark = false): Response {
$file = $this->avatarService->getAvatar($this->getRoom(), $this->userSession->getUser(), $dark);
$response = new FileDisplayResponse($file);
$response->addHeader('Content-Type', $file->getMimeType());
@ -158,14 +157,7 @@ class AvatarController extends AEnvironmentAwareController {
* @RequireModeratorParticipant
*/
public function deleteAvatar(): DataResponse {
try {
$folder = $this->appData->getFolder('room-avatar');
} catch (NotFoundException $e) {
$folder = $this->appData->newFolder('room-avatar');
}
$token = $this->getRoom()->getToken();
$folder->delete($token . '.png');
$folder->delete($token . '.jpeg');
$this->avatarService->deleteAvatar($this->getRoom());
return new DataResponse([]);
}
}

View file

@ -0,0 +1,93 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2022, Vitor Mattos <vitor@php.rio>
*
* @author Vitor Mattos <vitor@php.rio>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Talk\Service;
use OCA\Talk\Room;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\InMemoryFile;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\IAvatarManager;
use OCP\IUser;
class AvatarService {
private IAppData $appData;
private IAvatarManager $avatarManager;
public function __construct(
IAppData $appData,
IAvatarManager $avatarManager
) {
$this->appData = $appData;
$this->avatarManager = $avatarManager;
}
public function getAvatar(Room $room, ?IUser $user, bool $dark = false): ISimpleFile {
try {
$folder = $this->appData->getFolder('room-avatar');
} catch (NotFoundException $e) {
$folder = $this->appData->newFolder('room-avatar');
}
$token = $room->getToken();
if ($folder->fileExists($token . '.png')) {
$file = $folder->getFile($token . '.png');
} elseif ($folder->fileExists($token . '.jpeg')) {
$file = $folder->getFile($token . '.jpeg');
} else {
if ($room->getType() === Room::TYPE_ONE_TO_ONE) {
$users = json_decode($room->getName(), true);
foreach ($users as $participantId) {
if ($participantId !== $user->getUID()) {
$avatar = $this->avatarManager->getAvatar($participantId);
$file = $avatar->getFile(512);
}
}
} elseif ($room->getObjectType() === 'file') {
$file = new InMemoryFile($token, file_get_contents(__DIR__ . '/../../img/icon-file-white.svg'));
} elseif ($room->getObjectType() === 'share:password') {
$file = new InMemoryFile($token, file_get_contents(__DIR__ . '/../../img/icon-password-white.svg'));
} elseif ($room->getObjectType() === 'emails') {
$file = new InMemoryFile($token, file_get_contents(__DIR__ . '/../../img/icon-mail-white.svg'));
} elseif ($room->getType() === Room::TYPE_PUBLIC) {
$file = new InMemoryFile($token, file_get_contents(__DIR__ . '/../../img/icon-public-white.svg'));
} else {
$file = new InMemoryFile($token, file_get_contents(__DIR__ . '/../../img/icon-contacts-white.svg'));
}
}
return $file;
}
public function deleteAvatar(Room $room): void {
try {
$folder = $this->appData->getFolder('room-avatar');
} catch (NotFoundException $e) {
$folder = $this->appData->newFolder('room-avatar');
}
$token = $room->getToken();
$folder->delete($token);
}
}

View file

@ -9,12 +9,23 @@ Feature: chat/avatar
| roomName | room1 |
And user "participant1" send the file "/apps/spreed/img/favicon.png" as avatar of room "room1" with 200
Then the room "room1" need to have an avatar with 200
When user "participant1" delete the avatar of room "room1" with 200
Then the room "room1" need to have an avatar with 404
And user "participant1" delete the avatar of room "room1" with 200
Scenario: Try to change the room avatar without success
Given user "participant1" creates room "room1" (v4)
Given user "participant1" creates room "room2" (v4)
| roomType | 3 |
| roomName | room1 |
Then user "participant2" send the file "/apps/spreed/img/favicon.png" as avatar of room "room1" with 404
And user "participant1" delete the avatar of room "room1" with 404
| roomName | room2 |
Then user "participant2" send the file "/apps/spreed/img/favicon.png" as avatar of room "room2" with 404
And user "participant1" delete the avatar of room "room2" with 404
Scenario: Get avatar of conversation without custom avatar (fallback)
Given user "participant1" creates room "room3" (v4)
| roomType | 3 |
| roomName | room3 |
Then the room "room3" need to have an avatar with 200
Scenario: Get avatar of one2one without custom avatar (fallback)
When user "participant1" creates room "one2one" (v4)
| roomType | 1 |
| invite | participant2 |
Then the room "one2one" need to have an avatar with 200