Merge pull request #553 from shikorism/feature/332-discard-elapsed-time
「前回チェックインからの経過時間を記録しない」チェックインオプションの追加
This commit is contained in:
commit
28520007e4
@ -19,7 +19,7 @@ class Ejaculation extends Model
|
|||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'user_id', 'ejaculated_date',
|
'user_id', 'ejaculated_date',
|
||||||
'note', 'geo_latitude', 'geo_longitude', 'link', 'source',
|
'note', 'geo_latitude', 'geo_longitude', 'link', 'source',
|
||||||
'is_private', 'is_too_sensitive',
|
'is_private', 'is_too_sensitive', 'discard_elapsed_time',
|
||||||
'checkin_webhook_id'
|
'checkin_webhook_id'
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -105,4 +105,33 @@ class Ejaculation extends Model
|
|||||||
'is_too_sensitive' => $this->is_too_sensitive,
|
'is_too_sensitive' => $this->is_too_sensitive,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function ejaculatedSpan(): string
|
||||||
|
{
|
||||||
|
if (array_key_exists('ejaculated_span', $this->attributes)) {
|
||||||
|
if ($this->ejaculated_span === null) {
|
||||||
|
return '精通';
|
||||||
|
}
|
||||||
|
if ($this->discard_elapsed_time) {
|
||||||
|
return '0日 0時間 0分'; // TODO: 気の効いたフレーズにする
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->ejaculated_span;
|
||||||
|
} else {
|
||||||
|
$previous = Ejaculation::select('ejaculated_date')
|
||||||
|
->where('user_id', $this->user_id)
|
||||||
|
->where('ejaculated_date', '<', $this->ejaculated_date)
|
||||||
|
->orderByDesc('ejaculated_date')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($previous === null) {
|
||||||
|
return '精通';
|
||||||
|
}
|
||||||
|
if ($this->discard_elapsed_time) {
|
||||||
|
return '0日 0時間 0分';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->ejaculated_date->diff($previous->ejaculated_date)->format('%a日 %h時間 %i分');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ class WebhookController extends Controller
|
|||||||
'tags.*' => ['string', 'not_regex:/[\s\r\n]/u', 'max:255'],
|
'tags.*' => ['string', 'not_regex:/[\s\r\n]/u', 'max:255'],
|
||||||
'is_private' => 'nullable|boolean',
|
'is_private' => 'nullable|boolean',
|
||||||
'is_too_sensitive' => 'nullable|boolean',
|
'is_too_sensitive' => 'nullable|boolean',
|
||||||
|
'discard_elapsed_time' => 'nullable|boolean',
|
||||||
], [
|
], [
|
||||||
'tags.*.not_regex' => 'The :attribute cannot contain spaces, tabs and newlines.'
|
'tags.*.not_regex' => 'The :attribute cannot contain spaces, tabs and newlines.'
|
||||||
]);
|
]);
|
||||||
@ -71,6 +72,7 @@ class WebhookController extends Controller
|
|||||||
'source' => Ejaculation::SOURCE_WEBHOOK,
|
'source' => Ejaculation::SOURCE_WEBHOOK,
|
||||||
'is_private' => (bool)($inputs['is_private'] ?? false),
|
'is_private' => (bool)($inputs['is_private'] ?? false),
|
||||||
'is_too_sensitive' => (bool)($inputs['is_too_sensitive'] ?? false),
|
'is_too_sensitive' => (bool)($inputs['is_too_sensitive'] ?? false),
|
||||||
|
'discard_elapsed_time' => (bool)($inputs['discard_elapsed_time'] ?? false),
|
||||||
'checkin_webhook_id' => $webhook->id
|
'checkin_webhook_id' => $webhook->id
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -32,7 +32,8 @@ class EjaculationController extends Controller
|
|||||||
'note' => old('note') ?? $request->input('note', ''),
|
'note' => old('note') ?? $request->input('note', ''),
|
||||||
'is_private' => old('is_private') ?? $request->input('is_private', 0) == 1,
|
'is_private' => old('is_private') ?? $request->input('is_private', 0) == 1,
|
||||||
'is_too_sensitive' => old('is_too_sensitive') ?? $request->input('is_too_sensitive', 0) == 1,
|
'is_too_sensitive' => old('is_too_sensitive') ?? $request->input('is_too_sensitive', 0) == 1,
|
||||||
'is_realtime' => old('is_realtime', true)
|
'is_realtime' => old('is_realtime', true),
|
||||||
|
'discard_elapsed_time' => old('discard_elapsed_time') ?? $request->input('discard_elapsed_time') == 1,
|
||||||
],
|
],
|
||||||
'errors' => isset($errors) ? $errors->getMessages() : null
|
'errors' => isset($errors) ? $errors->getMessages() : null
|
||||||
];
|
];
|
||||||
@ -85,7 +86,8 @@ class EjaculationController extends Controller
|
|||||||
'link' => $inputs['link'] ?? '',
|
'link' => $inputs['link'] ?? '',
|
||||||
'source' => Ejaculation::SOURCE_WEB,
|
'source' => Ejaculation::SOURCE_WEB,
|
||||||
'is_private' => $request->has('is_private') ?? false,
|
'is_private' => $request->has('is_private') ?? false,
|
||||||
'is_too_sensitive' => $request->has('is_too_sensitive') ?? false
|
'is_too_sensitive' => $request->has('is_too_sensitive') ?? false,
|
||||||
|
'discard_elapsed_time' => $request->has('discard_elapsed_time') ?? false,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tagIds = [];
|
$tagIds = [];
|
||||||
@ -119,21 +121,7 @@ class EjaculationController extends Controller
|
|||||||
->firstOrFail();
|
->firstOrFail();
|
||||||
$user = User::findOrFail($ejaculation->user_id);
|
$user = User::findOrFail($ejaculation->user_id);
|
||||||
|
|
||||||
// 1つ前のチェックインからの経過時間を求める
|
return view('ejaculation.show')->with(compact('user', 'ejaculation'));
|
||||||
$previousEjaculation = Ejaculation::select('ejaculated_date')
|
|
||||||
->where('user_id', $ejaculation->user_id)
|
|
||||||
->where('ejaculated_date', '<', $ejaculation->ejaculated_date)
|
|
||||||
->orderByDesc('ejaculated_date')
|
|
||||||
->first();
|
|
||||||
if (!empty($previousEjaculation)) {
|
|
||||||
$ejaculatedSpan = $ejaculation->ejaculated_date
|
|
||||||
->diff($previousEjaculation->ejaculated_date)
|
|
||||||
->format('%a日 %h時間 %i分');
|
|
||||||
} else {
|
|
||||||
$ejaculatedSpan = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return view('ejaculation.show')->with(compact('user', 'ejaculation', 'ejaculatedSpan'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(Request $request, $id)
|
public function edit(Request $request, $id)
|
||||||
@ -161,7 +149,8 @@ class EjaculationController extends Controller
|
|||||||
'tags' => $tags,
|
'tags' => $tags,
|
||||||
'note' => old('note') ?? $ejaculation->note,
|
'note' => old('note') ?? $ejaculation->note,
|
||||||
'is_private' => is_bool(old('is_private')) ? old('is_private') : $ejaculation->is_private,
|
'is_private' => is_bool(old('is_private')) ? old('is_private') : $ejaculation->is_private,
|
||||||
'is_too_sensitive' => is_bool(old('is_too_sensitive')) ? old('is_too_sensitive') : $ejaculation->is_too_sensitive
|
'is_too_sensitive' => is_bool(old('is_too_sensitive')) ? old('is_too_sensitive') : $ejaculation->is_too_sensitive,
|
||||||
|
'discard_elapsed_time' => is_bool(old('discard_elapsed_time')) ? old('discard_elapsed_time') : $ejaculation->discard_elapsed_time,
|
||||||
],
|
],
|
||||||
'errors' => isset($errors) ? $errors->getMessages() : null
|
'errors' => isset($errors) ? $errors->getMessages() : null
|
||||||
];
|
];
|
||||||
@ -203,7 +192,8 @@ class EjaculationController extends Controller
|
|||||||
'note' => $inputs['note'] ?? '',
|
'note' => $inputs['note'] ?? '',
|
||||||
'link' => $inputs['link'] ?? '',
|
'link' => $inputs['link'] ?? '',
|
||||||
'is_private' => $request->has('is_private') ?? false,
|
'is_private' => $request->has('is_private') ?? false,
|
||||||
'is_too_sensitive' => $request->has('is_too_sensitive') ?? false
|
'is_too_sensitive' => $request->has('is_too_sensitive') ?? false,
|
||||||
|
'discard_elapsed_time' => $request->has('discard_elapsed_time') ?? false,
|
||||||
])->save();
|
])->save();
|
||||||
|
|
||||||
$tagIds = [];
|
$tagIds = [];
|
||||||
|
@ -35,6 +35,7 @@ is_private,
|
|||||||
is_too_sensitive,
|
is_too_sensitive,
|
||||||
link,
|
link,
|
||||||
source,
|
source,
|
||||||
|
discard_elapsed_time,
|
||||||
to_char(before_dates.before_date, 'YYYY/MM/DD HH24:MI') AS before_date,
|
to_char(before_dates.before_date, 'YYYY/MM/DD HH24:MI') AS before_date,
|
||||||
to_char(ejaculated_date - before_dates.before_date, 'FMDDD日 FMHH24時間 FMMI分') AS ejaculated_span
|
to_char(ejaculated_date - before_dates.before_date, 'FMDDD日 FMHH24時間 FMMI分') AS ejaculated_span
|
||||||
SQL
|
SQL
|
||||||
@ -169,6 +170,7 @@ is_private,
|
|||||||
is_too_sensitive,
|
is_too_sensitive,
|
||||||
link,
|
link,
|
||||||
source,
|
source,
|
||||||
|
discard_elapsed_time,
|
||||||
to_char(before_dates.before_date, 'YYYY/MM/DD HH24:MI') AS before_date,
|
to_char(before_dates.before_date, 'YYYY/MM/DD HH24:MI') AS before_date,
|
||||||
to_char(ejaculated_date - before_dates.before_date, 'FMDDD日 FMHH24時間 FMMI分') AS ejaculated_span
|
to_char(ejaculated_date - before_dates.before_date, 'FMDDD日 FMHH24時間 FMMI分') AS ejaculated_span
|
||||||
SQL
|
SQL
|
||||||
|
@ -19,6 +19,7 @@ class ProfileStatsComposer
|
|||||||
if (!$view->offsetExists('user')) {
|
if (!$view->offsetExists('user')) {
|
||||||
throw new \LogicException('View data "user" was not exist.');
|
throw new \LogicException('View data "user" was not exist.');
|
||||||
}
|
}
|
||||||
|
/** @var \App\User $user */
|
||||||
$user = $view->offsetGet('user');
|
$user = $view->offsetGet('user');
|
||||||
|
|
||||||
// 現在のオナ禁セッションの経過時間
|
// 現在のオナ禁セッションの経過時間
|
||||||
@ -35,35 +36,44 @@ class ProfileStatsComposer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 概況欄のデータ取得
|
// 概況欄のデータ取得
|
||||||
$average = DB::select(<<<'SQL'
|
$average = 0;
|
||||||
|
$divisor = 0;
|
||||||
|
$averageSources = DB::select(<<<'SQL'
|
||||||
SELECT
|
SELECT
|
||||||
avg(span) AS average
|
extract(epoch from ejaculated_date - lead(ejaculated_date, 1, NULL) OVER (ORDER BY ejaculated_date DESC)) AS span,
|
||||||
|
discard_elapsed_time
|
||||||
FROM
|
FROM
|
||||||
(
|
ejaculations
|
||||||
SELECT
|
WHERE
|
||||||
extract(epoch from ejaculated_date - lead(ejaculated_date, 1, NULL) OVER (ORDER BY ejaculated_date DESC)) AS span
|
user_id = :user_id
|
||||||
FROM
|
ORDER BY
|
||||||
ejaculations
|
ejaculated_date DESC
|
||||||
WHERE
|
LIMIT
|
||||||
user_id = :user_id
|
30
|
||||||
ORDER BY
|
|
||||||
ejaculated_date DESC
|
|
||||||
LIMIT
|
|
||||||
30
|
|
||||||
) AS temp
|
|
||||||
SQL
|
SQL
|
||||||
, ['user_id' => $user->id]);
|
, ['user_id' => $user->id]);
|
||||||
|
foreach ($averageSources as $item) {
|
||||||
|
// 経過時間記録対象外のレコードがあったら、それより古いデータは平均の計算に加えない
|
||||||
|
if ($item->discard_elapsed_time) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$average += $item->span;
|
||||||
|
$divisor++;
|
||||||
|
}
|
||||||
|
if ($divisor > 0) {
|
||||||
|
$average /= $divisor;
|
||||||
|
}
|
||||||
|
|
||||||
$summary = DB::select(<<<'SQL'
|
$summary = DB::select(<<<'SQL'
|
||||||
SELECT
|
SELECT
|
||||||
max(span) AS longest,
|
max(span) AS longest,
|
||||||
min(span) AS shortest,
|
min(span) AS shortest,
|
||||||
sum(span) AS total_times,
|
sum(span) AS total_times
|
||||||
count(*) AS total_checkins
|
|
||||||
FROM
|
FROM
|
||||||
(
|
(
|
||||||
SELECT
|
SELECT
|
||||||
extract(epoch from ejaculated_date - lead(ejaculated_date, 1, NULL) OVER (ORDER BY ejaculated_date DESC)) AS span
|
extract(epoch from ejaculated_date - lead(ejaculated_date, 1, NULL) OVER (ORDER BY ejaculated_date DESC)) AS span,
|
||||||
|
discard_elapsed_time
|
||||||
FROM
|
FROM
|
||||||
ejaculations
|
ejaculations
|
||||||
WHERE
|
WHERE
|
||||||
@ -71,9 +81,13 @@ FROM
|
|||||||
ORDER BY
|
ORDER BY
|
||||||
ejaculated_date DESC
|
ejaculated_date DESC
|
||||||
) AS temp
|
) AS temp
|
||||||
|
WHERE
|
||||||
|
discard_elapsed_time = FALSE
|
||||||
SQL
|
SQL
|
||||||
, ['user_id' => $user->id]);
|
, ['user_id' => $user->id]);
|
||||||
|
|
||||||
$view->with(compact('latestEjaculation', 'currentSession', 'average', 'summary'));
|
$total = $user->ejaculations()->count();
|
||||||
|
|
||||||
|
$view->with(compact('latestEjaculation', 'currentSession', 'average', 'summary', 'total'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddDiscardElapsedTimeToEjaculations extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('ejaculations', function (Blueprint $table) {
|
||||||
|
$table->boolean('discard_elapsed_time')->default(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('ejaculations', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('discard_elapsed_time');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ info:
|
|||||||
description: |
|
description: |
|
||||||
夜のライフログサービス Tissue の公開API仕様です。
|
夜のライフログサービス Tissue の公開API仕様です。
|
||||||
全てのAPIのURLは `https://shikorism.net/api` から始まります。
|
全てのAPIのURLは `https://shikorism.net/api` から始まります。
|
||||||
version: 0.1.0
|
version: 0.1.1
|
||||||
servers:
|
servers:
|
||||||
- url: 'https://shikorism.net/api'
|
- url: 'https://shikorism.net/api'
|
||||||
paths:
|
paths:
|
||||||
@ -51,6 +51,10 @@ paths:
|
|||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
description: チェックイン対象のオカズをより過激なオカズとして設定
|
description: チェックイン対象のオカズをより過激なオカズとして設定
|
||||||
|
discard_elapsed_time:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
description: 前回チェックインからの経過時間を記録しない
|
||||||
examples:
|
examples:
|
||||||
simple:
|
simple:
|
||||||
description: 何も指定しなければ、現在時刻で公開チェックインをおこないます。
|
description: 何も指定しなければ、現在時刻で公開チェックインをおこないます。
|
||||||
|
@ -21,6 +21,7 @@ export const CheckinForm: React.FC<CheckinFormProps> = ({ initialState }) => {
|
|||||||
const [isRealtime, setRealtime] = useState<boolean>(mode === 'create' && initialState.fields.is_realtime);
|
const [isRealtime, setRealtime] = useState<boolean>(mode === 'create' && initialState.fields.is_realtime);
|
||||||
const [isPrivate, setPrivate] = useState<boolean>(!!initialState.fields.is_private);
|
const [isPrivate, setPrivate] = useState<boolean>(!!initialState.fields.is_private);
|
||||||
const [isTooSensitive, setTooSensitive] = useState<boolean>(!!initialState.fields.is_too_sensitive);
|
const [isTooSensitive, setTooSensitive] = useState<boolean>(!!initialState.fields.is_too_sensitive);
|
||||||
|
const [discardElapsedTime, setDiscardElapsedTime] = useState<boolean>(!!initialState.fields.discard_elapsed_time);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mode === 'create' && isRealtime) {
|
if (mode === 'create' && isRealtime) {
|
||||||
const id = setInterval(() => {
|
const id = setInterval(() => {
|
||||||
@ -164,6 +165,23 @@ export const CheckinForm: React.FC<CheckinFormProps> = ({ initialState }) => {
|
|||||||
>
|
>
|
||||||
<span className="oi oi-warning" /> チェックイン対象のオカズをより過激なオカズとして設定する
|
<span className="oi oi-warning" /> チェックイン対象のオカズをより過激なオカズとして設定する
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
|
<CheckBox
|
||||||
|
id="discardElapsedTime"
|
||||||
|
name="discard_elapsed_time"
|
||||||
|
className="mb-3"
|
||||||
|
checked={discardElapsedTime}
|
||||||
|
onChange={(v) => setDiscardElapsedTime(v)}
|
||||||
|
>
|
||||||
|
<span className="oi oi-timer" /> 前回チェックインからの経過時間を記録しない
|
||||||
|
<br />
|
||||||
|
<small className="form-text text-muted">
|
||||||
|
長期間お使いにならなかった場合など、経過時間に意味が無い時のリセット用オプションです。
|
||||||
|
<ul className="pl-3">
|
||||||
|
<li>最長・最短記録の計算から除外されます。</li>
|
||||||
|
<li>平均記録の起点がこのチェックインになります。</li>
|
||||||
|
</ul>
|
||||||
|
</small>
|
||||||
|
</CheckBox>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
<h6 class="font-weight-bold"><span class="oi oi-graph"></span> 概況</h6>
|
<h6 class="font-weight-bold"><span class="oi oi-graph"></span> 概況</h6>
|
||||||
<p class="card-text mb-0">平均記録: {{ Formatter::formatInterval($average[0]->average) }}</p>
|
<p class="card-text mb-0">平均記録: {{ Formatter::formatInterval($average) }}</p>
|
||||||
<p class="card-text mb-0">最長記録: {{ Formatter::formatInterval($summary[0]->longest) }}</p>
|
<p class="card-text mb-0">最長記録: {{ Formatter::formatInterval($summary[0]->longest) }}</p>
|
||||||
<p class="card-text mb-0">最短記録: {{ Formatter::formatInterval($summary[0]->shortest) }}</p>
|
<p class="card-text mb-0">最短記録: {{ Formatter::formatInterval($summary[0]->shortest) }}</p>
|
||||||
<p class="card-text mb-0">合計時間: {{ Formatter::formatInterval($summary[0]->total_times) }}</p>
|
<p class="card-text mb-0">合計時間: {{ Formatter::formatInterval($summary[0]->total_times) }}</p>
|
||||||
<p class="card-text">通算回数: {{ number_format($summary[0]->total_checkins) }}回</p>
|
<p class="card-text">通算回数: {{ number_format($total) }}回</p>
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<!-- span -->
|
<!-- span -->
|
||||||
<div>
|
<div>
|
||||||
<h5>{{ $ejaculatedSpan ?? '精通' }} <small class="text-muted">{{ $ejaculation->before_date }}{{ !empty($ejaculation->before_date) ? ' ~ ' : '' }}{{ $ejaculation->ejaculated_date->format('Y/m/d H:i') }}</small></h5>
|
<h5>{{ $ejaculation->ejaculatedSpan() }} <small class="text-muted">{{ !empty($ejaculation->before_date) && !$ejaculation->discard_elapsed_time ? $ejaculation->before_date . ' ~ ' : '' }}{{ $ejaculation->ejaculated_date->format('Y/m/d H:i') }}</small></h5>
|
||||||
</div>
|
</div>
|
||||||
<!-- tags -->
|
<!-- tags -->
|
||||||
@if ($ejaculation->is_private || $ejaculation->source !== 'web' || $ejaculation->tags->isNotEmpty())
|
@if ($ejaculation->is_private || $ejaculation->source !== 'web' || $ejaculation->tags->isNotEmpty())
|
||||||
|
@ -58,7 +58,7 @@
|
|||||||
<li class="list-group-item border-bottom-only pt-3 pb-3 text-break">
|
<li class="list-group-item border-bottom-only pt-3 pb-3 text-break">
|
||||||
<!-- span -->
|
<!-- span -->
|
||||||
<div>
|
<div>
|
||||||
<h5>{{ $ejaculation->ejaculated_span ?? '精通' }} <a href="{{ route('checkin.show', ['id' => $ejaculation->id]) }}" class="text-muted"><small>{{ $ejaculation->before_date }}{{ !empty($ejaculation->before_date) ? ' ~ ' : '' }}{{ $ejaculation->ejaculated_date->format('Y/m/d H:i') }}</small></a></h5>
|
<h5>{{ $ejaculation->ejaculatedSpan() }} <a href="{{ route('checkin.show', ['id' => $ejaculation->id]) }}" class="text-muted"><small>{{ !empty($ejaculation->before_date) && !$ejaculation->discard_elapsed_time ? $ejaculation->before_date . ' ~ ' : '' }}{{ $ejaculation->ejaculated_date->format('Y/m/d H:i') }}</small></a></h5>
|
||||||
</div>
|
</div>
|
||||||
<!-- tags -->
|
<!-- tags -->
|
||||||
@if ($ejaculation->is_private || $ejaculation->source !== 'web' || $ejaculation->tags->isNotEmpty())
|
@if ($ejaculation->is_private || $ejaculation->source !== 'web' || $ejaculation->tags->isNotEmpty())
|
||||||
|
Loading…
Reference in New Issue
Block a user