mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 22:27:20 +02:00
Improve voice transcribe design.
This commit is contained in:
parent
28733fadcd
commit
e5d95c0ab0
12 changed files with 159 additions and 29 deletions
BIN
Telegram/Resources/icons/chat/voice_to_text.png
Normal file
BIN
Telegram/Resources/icons/chat/voice_to_text.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 494 B |
BIN
Telegram/Resources/icons/chat/voice_to_text@2x.png
Normal file
BIN
Telegram/Resources/icons/chat/voice_to_text@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 816 B |
BIN
Telegram/Resources/icons/chat/voice_to_text@3x.png
Normal file
BIN
Telegram/Resources/icons/chat/voice_to_text@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
Telegram/Resources/icons/chat/voice_to_text_collapse.png
Normal file
BIN
Telegram/Resources/icons/chat/voice_to_text_collapse.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 259 B |
BIN
Telegram/Resources/icons/chat/voice_to_text_collapse@2x.png
Normal file
BIN
Telegram/Resources/icons/chat/voice_to_text_collapse@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 360 B |
BIN
Telegram/Resources/icons/chat/voice_to_text_collapse@3x.png
Normal file
BIN
Telegram/Resources/icons/chat/voice_to_text_collapse@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 471 B |
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 }};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue