Improve voice transcribe design.

This commit is contained in:
John Preston 2022-05-25 16:18:49 +04:00
parent 28733fadcd
commit e5d95c0ab0
12 changed files with 159 additions and 29 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

View File

@ -13,18 +13,42 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "ui/chat/chat_style.h"
#include "ui/click_handler.h"
#include "ui/effects/radial_animation.h"
#include "api/api_transcribes.h"
#include "apiwrap.h"
#include "styles/style_chat.h"
namespace HistoryView {
namespace {
constexpr auto kInNonChosenOpacity = 0.12;
constexpr auto kOutNonChosenOpacity = 0.18;
} // namespace
TranscribeButton::TranscribeButton(not_null<HistoryItem*> item)
: _item(item) {
}
TranscribeButton::~TranscribeButton() = default;
QSize TranscribeButton::size() const {
return QSize(st::historyTranscribeSize, st::historyTranscribeSize);
return st::historyTranscribeSize;
}
void TranscribeButton::setLoading(bool loading, Fn<void()> update) {
if (_loading == loading) {
return;
}
_loading = loading;
if (_loading) {
_animation = std::make_unique<Ui::InfiniteRadialAnimation>(
update,
st::defaultInfiniteRadialAnimation);
_animation->start();
} else if (_animation) {
_animation->stop();
}
}
void TranscribeButton::paint(
@ -33,10 +57,80 @@ void TranscribeButton::paint(
int y,
const PaintContext &context) {
auto hq = PainterHighQualityEnabler(p);
const auto opened = _openedAnimation.value(_opened ? 1. : 0.);
const auto stm = context.messageStyle();
p.setBrush(stm->msgWaveformInactive);
const auto radius = size().width() / 4;
p.drawRoundedRect(QRect{ QPoint(x, y), size() }, radius, radius);
auto bg = stm->msgFileBg->c;
bg.setAlphaF(bg.alphaF() * (context.outbg
? kOutNonChosenOpacity
: kInNonChosenOpacity));
p.setBrush(bg);
const auto radius = st::historyTranscribeRadius;
const auto state = _animation
? _animation->computeState()
: Ui::RadialState();
if (state.shown > 0.) {
auto fg = stm->msgWaveformActive->c;
fg.setAlphaF(fg.alphaF() * state.shown * (1. - opened));
auto pen = QPen(fg);
const auto thickness = style::ConvertScaleExact(2.);
const auto widthNoRadius = size().width() - 2 * radius;
const auto heightNoRadius = size().height() - 2 * radius;
const auto length = 2 * (widthNoRadius + heightNoRadius)
+ 2 * M_PI * radius;
pen.setWidthF(thickness);
pen.setCapStyle(Qt::RoundCap);
const auto ratio = length / (Ui::RadialState::kFull * thickness);
const auto filled = ratio * state.arcLength;
pen.setDashPattern({ filled, (length / thickness) - filled });
pen.setDashOffset(ratio * (state.arcFrom + state.arcLength));
p.setPen(pen);
} else {
p.setPen(Qt::NoPen);
if (!_loading) {
_animation = nullptr;
}
}
const auto r = QRect{ QPoint(x, y), size() };
p.drawRoundedRect(r, radius, radius);
if (opened > 0.) {
if (opened != 1.) {
p.save();
p.setOpacity(opened);
p.translate(r.center());
p.scale(opened, opened);
p.translate(-r.center());
}
stm->historyTranscribeHide.paintInCenter(p, r);
if (opened != 1.) {
p.restore();
}
}
if (opened < 1.) {
if (opened != 0.) {
p.save();
p.setOpacity(1. - opened);
p.translate(r.center());
p.scale(1. - opened, 1. - opened);
p.translate(-r.center());
}
stm->historyTranscribeIcon.paintInCenter(p, r);
if (opened != 0.) {
p.restore();
}
}
p.setOpacity(1.);
}
void TranscribeButton::setOpened(bool opened, Fn<void()> update) {
if (_opened == opened) {
return;
}
_opened = opened;
_openedAnimation.start(
std::move(update),
_opened ? 0. : 1.,
_opened ? 1. : 0.,
st::fadeWrapDuration);
}
ClickHandlerPtr TranscribeButton::link() {

View File

@ -7,8 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "ui/effects/animations.h"
namespace Ui {
struct ChatPaintContext;
class InfiniteRadialAnimation;
} // namespace Ui
namespace HistoryView {
@ -18,9 +21,12 @@ using PaintContext = Ui::ChatPaintContext;
class TranscribeButton final {
public:
explicit TranscribeButton(not_null<HistoryItem*> item);
~TranscribeButton();
[[nodiscard]] QSize size() const;
void setOpened(bool opened, Fn<void()> update);
void setLoading(bool loading, Fn<void()> update);
void paint(QPainter &p, int x, int y, const PaintContext &context);
[[nodiscard]] ClickHandlerPtr link();
@ -28,10 +34,12 @@ public:
private:
const not_null<HistoryItem*> _item;
mutable std::unique_ptr<Ui::InfiniteRadialAnimation> _animation;
ClickHandlerPtr _link;
QString _text;
bool _loaded = false;
Ui::Animations::Simple _openedAnimation;
bool _loading = false;
bool _opened = false;
};

View File

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h"
#include "ui/text/format_values.h"
#include "ui/text/format_song_document_name.h"
#include "ui/text/text_utilities.h"
#include "ui/chat/message_bubble.h"
#include "ui/chat/chat_style.h"
#include "ui/cached_round_corners.h"
@ -105,6 +106,7 @@ void PaintWaveform(
const auto maxDelta = st::msgWaveformMax - st::msgWaveformMin;
const auto &bottom = st::msgWaveformMax;
p.setPen(Qt::NoPen);
auto hq = PainterHighQualityEnabler(p);
for (auto i = 0, barLeft = 0, sum = 0, maxValue = 0; i < wfSize; ++i) {
const auto value = wf ? wf->at(i) : 0;
if (sum + barCount < wfSize) {
@ -120,16 +122,20 @@ void PaintWaveform(
const auto barValue = ((maxValue * maxDelta) + (barNormValue / 2))
/ barNormValue;
const auto barHeight = st::msgWaveformMin + barValue;
const auto barTop = bottom - barValue;
const auto barTop = st::lineWidth + (st::msgWaveformMax - barValue) / 2.;
if ((barLeft < activeWidth) && (barLeft + barWidth > activeWidth)) {
const auto leftWidth = activeWidth - barLeft;
const auto rightWidth = barWidth - leftWidth;
p.fillRect(barLeft, barTop, leftWidth, barHeight, active);
p.fillRect(activeWidth, barTop, rightWidth, barHeight, inactive);
p.fillRect(
QRectF(barLeft, barTop, leftWidth, barHeight),
active);
p.fillRect(
QRectF(activeWidth, barTop, rightWidth, barHeight),
inactive);
} else {
const auto &color = (barLeft >= activeWidth) ? inactive : active;
p.fillRect(barLeft, barTop, barWidth, barHeight, color);
p.fillRect(QRectF(barLeft, barTop, barWidth, barHeight), color);
}
barLeft += barWidth + st::msgWaveformSkip;
@ -244,22 +250,26 @@ QSize Document::countOptimalSize() {
}
const auto &entry = session->api().transcribes().entry(
_realParent);
auto text = entry.requestId
? "Transcribing..."
const auto update = [=] { repaint(); };
voice->transcribe->setLoading(
entry.shown && (entry.requestId || entry.pending),
update);
auto text = (entry.requestId || !entry.shown)
? TextWithEntities()
: entry.failed
? "Transcribing Failed."
: entry.shown
? ((entry.pending ? "Still Transcribing...\n" : "")
+ entry.result)
: QString();
if (text.isEmpty()) {
? Ui::Text::Italic(tr::lng_attach_failed(tr::now))
: TextWithEntities{ entry.result };
voice->transcribe->setOpened(!text.empty(), update);
if (text.empty()) {
voice->transcribeText = {};
} else {
const auto minResizeWidth = st::minPhotoSize
- st::msgPadding.left()
- st::msgPadding.right();
voice->transcribeText = Ui::Text::String(minResizeWidth);
voice->transcribeText.setText(st::messageTextStyle, text);
voice->transcribeText.setMarkedText(
st::messageTextStyle,
text);
hasTranscribe = true;
}
}
@ -599,10 +609,7 @@ void Document::draw(
const auto size = voice->transcribe->size();
namewidth -= st::historyTranscribeSkip + size.width();
const auto x = nameleft + namewidth + st::historyTranscribeSkip;
const auto y = st.padding.top()
- topMinus
+ st::msgWaveformMax
- size.height();
const auto y = st.padding.top() - topMinus;
voice->transcribe->paint(p, x, y, context);
}
p.save();
@ -837,10 +844,7 @@ TextState Document::textState(
const auto size = voice->transcribe->size();
namewidth -= st::historyTranscribeSkip + size.width();
const auto x = nameleft + namewidth + st::historyTranscribeSkip;
const auto y = st.padding.top()
- topMinus
+ st::msgWaveformMax
- size.height();
const auto y = st.padding.top() - topMinus;
if (QRect(QPoint(x, y), size).contains(point)) {
result.link = voice->transcribe->link();
return result;

View File

@ -652,11 +652,20 @@ msgVideoSize: size(320px, 240px);
msgWaveformBar: 2px;
msgWaveformSkip: 1px;
msgWaveformMin: 2px;
msgWaveformMax: 20px;
msgWaveformMin: 3px;
msgWaveformMax: 17px;
historyTranscribeSkip: 10px;
historyTranscribeSize: 24px;
historyTranscribeSize: size(28px, 22px);
historyTranscribeRadius: 4px;
historyTranscribeInIcon: icon {{ "chat/voice_to_text", msgFileInBg }};
historyTranscribeInIconSelected: icon {{ "chat/voice_to_text", msgFileInBgSelected }};
historyTranscribeOutIcon: icon {{ "chat/voice_to_text", msgFileOutBg }};
historyTranscribeOutIconSelected: icon {{ "chat/voice_to_text", msgFileOutBgSelected }};
historyTranscribeInHide: icon {{ "chat/voice_to_text_collapse", msgFileInBg }};
historyTranscribeInHideSelected: icon {{ "chat/voice_to_text_collapse", msgFileInBgSelected }};
historyTranscribeOutHide: icon {{ "chat/voice_to_text_collapse", msgFileOutBg }};
historyTranscribeOutHideSelected: icon {{ "chat/voice_to_text_collapse", msgFileOutBgSelected }};
historyVideoMessageMute: icon {{ "volume_mute", historyFileThumbIconFg }};
historyVideoMessageMuteSelected: icon {{ "volume_mute", historyFileThumbIconFgSelected }};

View File

@ -398,6 +398,18 @@ ChatStyle::ChatStyle() {
st::historyPollInChoiceRightSelected,
st::historyPollOutChoiceRight,
st::historyPollOutChoiceRightSelected);
make(
&MessageStyle::historyTranscribeIcon,
st::historyTranscribeInIcon,
st::historyTranscribeInIconSelected,
st::historyTranscribeOutIcon,
st::historyTranscribeOutIconSelected);
make(
&MessageStyle::historyTranscribeHide,
st::historyTranscribeInHide,
st::historyTranscribeInHideSelected,
st::historyTranscribeOutHide,
st::historyTranscribeOutHideSelected);
make(
&MessageImageStyle::msgDateImgBg,
st::msgDateImgBg,

View File

@ -70,6 +70,9 @@ struct MessageStyle {
style::icon historyQuizExplain = { Qt::Uninitialized };
style::icon historyPollChosen = { Qt::Uninitialized };
style::icon historyPollChoiceRight = { Qt::Uninitialized };
style::icon historyTranscribeIcon = { Qt::Uninitialized };
style::icon historyTranscribeHide = { Qt::Uninitialized };
};
struct MessageImageStyle {