mirror of
https://github.com/karatektus/pl_mail.git
synced 2026-10-25 01:54:10 +00:00
The hold was already announced — the composer closes and a toast names the
time — but calling it off meant opening the draft and then opening the send
menu, and the Drafts row itself offered no way out. On a phone that was the
only way out at all: the send pill is desktop-only, so the row is the sole
surface a scheduled draft has there.
• The scheduled badge grows a cancel. Badge and × are one pill rather than
a badge with a button parked beside it — the × means nothing on its own.
It sits ON TOP of the row's overlay anchor exactly as the star and the
hover actions do (z-10 on a flex item, plus stopPropagation in
mail--message-row), so no nested <form> in a shared partial and no click
reaching the link underneath.
• POST /compose/unschedule/{id} answers with the row redrawn, not with the
composer reopened: undo() exists to catch a send you regretted while you
were still looking at it, and a hold set on Friday is called off on
Monday from a list of forty rows. Both now share callOffSend(); the
sentAt guard is in one place instead of two. A message that has already
gone is left entirely alone — submissionSendAt is by then the record of
when it was due — and the row is redrawn anyway, because what was on
screen was stale.
• The toast's action is relabelled "Cancel send". "Undo" is the wrong verb
for something that has not happened yet, and the long form pushed the
message onto four lines; _toast.html.twig takes an optional undo_label.
• On a stacked row a scheduled draft shows the badge instead of the
preview, which at 393px was two characters and an ellipsis. `hidden
@xl:inline-block`, not `@xl:block`: Tailwind emits `.hidden` after
`.block`, so the container variant does not outrank it.
Every string translated (en/de/en_PI), including the sr-only label. The
mobile spec measures the pill's bounding box and the tap target rather than
asserting presence, after the target came out 11px tall.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
48 lines
2.0 KiB
Twig
48 lines
2.0 KiB
Twig
{#
|
|
compose/_unschedule.stream.html.twig
|
|
─────────────────────────────────────────────────────────────────────────────
|
|
Answer to POST /compose/unschedule/{id}: the row that was clicked, redrawn
|
|
without its hold, plus a toast saying so.
|
|
|
|
`replace` on the row's own id, exactly as thread/status/_star.stream.html.twig
|
|
does — the list rows are patched one at a time and never reloaded whole, and
|
|
the row carries its own Stimulus controller, so replacing the <li> re-connects
|
|
it rather than leaving a dead badge behind.
|
|
|
|
The include is NOT `only`: _thread_row.html.twig reads `accounts` (the account
|
|
wedge is drawn only on a multi-account install) off the globals, the same way
|
|
the star and read streams reach it.
|
|
|
|
Variables: row (MessageThread|Message), type ('thread'|'message'),
|
|
draft_scope (bool), cancelled (bool — false when the mail had
|
|
already gone out, in which case nothing was written)
|
|
#}
|
|
<turbo-stream action="replace" target="thread_{{ row.id }}">
|
|
<template>
|
|
{% if 'thread' == type %}
|
|
{% include '_partials/_thread_row.html.twig' with {
|
|
thread: row,
|
|
draft_scope: draft_scope,
|
|
} %}
|
|
{% else %}
|
|
{% include '_partials/_thread_row.html.twig' with {
|
|
message: row,
|
|
draft_scope: draft_scope,
|
|
} %}
|
|
{% endif %}
|
|
</template>
|
|
</turbo-stream>
|
|
|
|
{# Silent on a message that had already gone: the row redraws itself into the
|
|
truth, and "cancelled" would be the one thing that did not happen. #}
|
|
{% if cancelled %}
|
|
<turbo-stream action="append" target="toast-region">
|
|
<template>
|
|
{% include '_partials/_toast.html.twig' with {
|
|
type: 'info',
|
|
message: 'toast.schedule_cancelled'|trans,
|
|
} only %}
|
|
</template>
|
|
</turbo-stream>
|
|
{% endif %}
|