Merge pull request #320 from shikorism/fix/318-profile-image-srcset

プロフィール画像のsrcsetを出力するヘルパーを追加
This commit is contained in:
shibafu 2020-01-29 22:52:51 +09:00 committed by GitHub
commit 7968019e1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 42 additions and 9 deletions

View File

@ -75,4 +75,21 @@ class Formatter
return $url;
}
/**
* imgタグのsrcsetで使用できる形式で、プロフィール画像URLを生成します。
* @param object $user Userなど、getProfileImageUrl()が実装されているオブジェクト
* @param int $baseSize 1x解像度における画像サイズ
* @param int $maxDensity 最高密度
* @return string srcset用の文字列
*/
public function profileImageSrcSet($user, int $baseSize, int $maxDensity = 3)
{
$srcset = [];
for ($i = 1; $i <= $maxDensity; $i++) {
$srcset[] = $user->getProfileImageUrl($baseSize * $i) . " {$i}x";
}
return implode(',', $srcset);
}
}

View File

@ -1,7 +1,7 @@
<!-- span -->
<div>
<h5>
<a href="{{ route('user.profile', ['id' => $ejaculation->user->name]) }}" class="text-dark"><img src="{{ $ejaculation->user->getProfileImageUrl(30) }}" width="30" height="30" class="rounded d-inline-block align-bottom"> <bdi>{{ $ejaculation->user->display_name }}</bdi></a>
<a href="{{ route('user.profile', ['id' => $ejaculation->user->name]) }}" class="text-dark"><img src="{{ $ejaculation->user->getProfileImageUrl(30) }}" srcset="{{ Formatter::profileImageSrcSet($ejaculation->user, 30) }}" width="30" height="30" class="rounded d-inline-block align-bottom"> <bdi>{{ $ejaculation->user->display_name }}</bdi></a>
<a href="{{ route('checkin.show', ['id' => $ejaculation->id]) }}" class="text-muted"><small>{{ $ejaculation->ejaculated_date->format('Y/m/d H:i') }}</small></a>
</h5>
</div>
@ -39,7 +39,7 @@
<div class="like-users flex-grow-1 overflow-hidden">
@foreach ($ejaculation->likes as $like)
@if ($like->user !== null)
<a href="{{ route('user.profile', ['name' => $like->user->name]) }}"><img src="{{ $like->user->getProfileImageUrl(30) }}" width="30" height="30" class="rounded" data-toggle="tooltip" data-placement="bottom" title="{{ $like->user->display_name }}"></a>
<a href="{{ route('user.profile', ['name' => $like->user->name]) }}"><img src="{{ $like->user->getProfileImageUrl(30) }}" srcset="{{ Formatter::profileImageSrcSet($like->user, 30) }}" width="30" height="30" class="rounded" data-toggle="tooltip" data-placement="bottom" title="{{ $like->user->display_name }}"></a>
@endif
@endforeach
</div>

View File

@ -1,6 +1,6 @@
<div class="card mb-4">
<div class="card-body">
<img src="{{ $user->getProfileImageUrl(128) }}" class="rounded mb-1">
<img src="{{ $user->getProfileImageUrl(128) }}" srcset="{{ Formatter::profileImageSrcSet($user, 128) }}" class="rounded mb-1">
<h4 class="card-title">
<a class="text-dark" href="{{ route('user.profile', ['name' => $user->name]) }}">{{ $user->display_name }}</a>
</h4>

View File

@ -67,7 +67,7 @@
<div class="like-users-tall flex-grow-1 overflow-hidden">
@foreach ($ejaculation->likes as $like)
@if ($like->user !== null)
<a href="{{ route('user.profile', ['name' => $like->user->name]) }}"><img src="{{ $like->user->getProfileImageUrl(36) }}" width="36" height="36" class="rounded" data-toggle="tooltip" data-placement="bottom" title="{{ $like->user->display_name }}"></a>
<a href="{{ route('user.profile', ['name' => $like->user->name]) }}"><img src="{{ $like->user->getProfileImageUrl(36) }}" srcset="{{ Formatter::profileImageSrcSet($like->user, 36) }}" width="36" height="36" class="rounded" data-toggle="tooltip" data-placement="bottom" title="{{ $like->user->display_name }}"></a>
@endif
@endforeach
</div>

View File

@ -10,7 +10,7 @@
<div class="card mb-4">
<div class="card-body">
<div class="d-flex flex-row align-items-end mb-4">
<img src="{{ Auth::user()->getProfileImageUrl(48) }}" class="rounded mr-2">
<img src="{{ Auth::user()->getProfileImageUrl(48) }}" srcset="{{ Formatter::profileImageSrcSet(Auth::user(), 48) }}" class="rounded mr-2">
<div class="d-flex flex-column overflow-hidden">
<h5 class="card-title text-truncate">
<a class="text-dark" href="{{ route('user.profile', ['name' => Auth::user()->name]) }}">{{ Auth::user()->display_name }}</a>

View File

@ -40,7 +40,7 @@
<div class="d-lg-none navbar-nav">
<div class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle p-2" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img src="{{ Auth::user()->getProfileImageUrl(30) }}" width="30" height="30" class="rounded d-inline-block align-top">
<img src="{{ Auth::user()->getProfileImageUrl(30) }}" srcset="{{ Formatter::profileImageSrcSet(Auth::user(), 30) }}" width="30" height="30" class="rounded d-inline-block align-top">
</a>
<div class="dropdown-menu dropdown-menu-right position-absolute" aria-labelledby="navbarDropdownMenuLink" id="navbarAccountDropdownSp">
<a href="{{ route('user.profile', ['name' => Auth::user()->name]) }}" class="dropdown-item text-truncate">
@ -103,7 +103,7 @@
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img src="{{ Auth::user()->getProfileImageUrl(30) }}" width="30" height="30" class="rounded d-inline-block align-top">
<img src="{{ Auth::user()->getProfileImageUrl(30) }}" srcset="{{ Formatter::profileImageSrcSet(Auth::user(), 30) }}" width="30" height="30" class="rounded d-inline-block align-top">
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdownMenuLink">
<a href="{{ route('user.profile', ['name' => Auth::user()->name]) }}" class="dropdown-item">

View File

@ -9,7 +9,7 @@
{{ csrf_field() }}
<div class="from-group">
<label for="name">アイコン</label>
<img src="{{ Auth::user()->getProfileImageUrl(128) }}" class="rounded d-block">
<img src="{{ Auth::user()->getProfileImageUrl(128) }}" srcset="{{ Formatter::profileImageSrcSet(Auth::user(), 128) }}" class="rounded d-block">
<small class="form-text text-muted">変更は<a href="https://gravatar.com/" target="_blank">Gravatar</a>から行えます。</small>
</div>
<div class="from-group mt-3">

View File

@ -73,7 +73,7 @@
<div class="like-users flex-grow-1 overflow-hidden">
@foreach ($ejaculation->likes as $like)
@if ($like->user !== null)
<a href="{{ route('user.profile', ['name' => $like->user->name]) }}"><img src="{{ $like->user->getProfileImageUrl(30) }}" width="30" height="30" class="rounded" data-toggle="tooltip" data-placement="bottom" title="{{ $like->user->display_name }}"></a>
<a href="{{ route('user.profile', ['name' => $like->user->name]) }}"><img src="{{ $like->user->getProfileImageUrl(30) }}" srcset="{{ Formatter::profileImageSrcSet($like->user, 30) }}" width="30" height="30" class="rounded" data-toggle="tooltip" data-placement="bottom" title="{{ $like->user->display_name }}"></a>
@endif
@endforeach
</div>

View File

@ -54,4 +54,20 @@ class FormatterTest extends TestCase
$url = 'http://example.com/path/to?foo=bar&hoge=fuga#';
$this->assertEquals('http://example.com/path/to?foo=bar&hoge=fuga', $formatter->normalizeUrl($url));
}
public function testProfileImageSrcSet()
{
$formatter = new Formatter();
$profileImageProvider = new class() {
public function getProfileImageUrl(int $size)
{
return "https://example.com/$size.png";
}
};
$this->assertSame(
'https://example.com/128.png 1x,https://example.com/256.png 2x',
$formatter->profileImageSrcSet($profileImageProvider, 128, 2)
);
}
}