mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Added initial ability to transcribe video messages.
This commit is contained in:
parent
b4a9705564
commit
579b20fff7
13 changed files with 134 additions and 21 deletions
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history_item.h"
|
||||
#include "history/history.h"
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "apiwrap.h"
|
||||
|
@ -30,6 +31,9 @@ void Transcribes::toggle(not_null<HistoryItem*> item) {
|
|||
_session->data().requestItemResize(item);
|
||||
} else if (!i->second.requestId) {
|
||||
i->second.shown = !i->second.shown;
|
||||
if (i->second.roundview) {
|
||||
_session->data().requestItemViewRefresh(item);
|
||||
}
|
||||
_session->data().requestItemResize(item);
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +59,9 @@ void Transcribes::apply(const MTPDupdateTranscribedAudio &update) {
|
|||
j->second.result = text;
|
||||
j->second.pending = update.is_pending();
|
||||
if (const auto item = _session->data().message(i->second)) {
|
||||
if (j->second.roundview) {
|
||||
_session->data().requestItemViewRefresh(item);
|
||||
}
|
||||
_session->data().requestItemResize(item);
|
||||
}
|
||||
}
|
||||
|
@ -63,29 +70,41 @@ void Transcribes::load(not_null<HistoryItem*> item) {
|
|||
if (!item->isHistoryEntry() || item->isLocal()) {
|
||||
return;
|
||||
}
|
||||
const auto toggleRound = [](not_null<HistoryItem*> item, Entry &entry) {
|
||||
if (const auto media = item->media()) {
|
||||
if (const auto document = media->document()) {
|
||||
if (document->isVideoMessage()) {
|
||||
entry.roundview = true;
|
||||
document->owner().requestItemViewRefresh(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const auto id = item->fullId();
|
||||
const auto requestId = _api.request(MTPmessages_TranscribeAudio(
|
||||
item->history()->peer->input,
|
||||
MTP_int(item->id)
|
||||
)).done([=](const MTPmessages_TranscribedAudio &result) {
|
||||
result.match([&](const MTPDmessages_transcribedAudio &data) {
|
||||
auto &entry = _map[id];
|
||||
entry.requestId = 0;
|
||||
entry.pending = data.is_pending();
|
||||
entry.result = qs(data.vtext());
|
||||
_ids.emplace(data.vtranscription_id().v, id);
|
||||
if (const auto item = _session->data().message(id)) {
|
||||
_session->data().requestItemResize(item);
|
||||
}
|
||||
});
|
||||
const auto &data = result.data();
|
||||
auto &entry = _map[id];
|
||||
entry.requestId = 0;
|
||||
entry.pending = data.is_pending();
|
||||
entry.result = qs(data.vtext());
|
||||
_ids.emplace(data.vtranscription_id().v, id);
|
||||
if (const auto item = _session->data().message(id)) {
|
||||
toggleRound(item, entry);
|
||||
_session->data().requestItemResize(item);
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
auto &entry = _map[id];
|
||||
entry.requestId = 0;
|
||||
entry.pending = false;
|
||||
entry.failed = true;
|
||||
if (error.type() == qstr("MSG_VOICE_TOO_LONG")) {
|
||||
if (error.type() == u"MSG_VOICE_TOO_LONG"_q) {
|
||||
entry.toolong = true;
|
||||
} else if (const auto item = _session->data().message(id)) {
|
||||
}
|
||||
if (const auto item = _session->data().message(id)) {
|
||||
toggleRound(item, entry);
|
||||
_session->data().requestItemResize(item);
|
||||
}
|
||||
}).send();
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
bool failed = false;
|
||||
bool toolong = false;
|
||||
bool pending = false;
|
||||
bool roundview = false;
|
||||
mtpRequestId requestId = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -381,6 +381,10 @@ void DocumentData::setattributes(
|
|||
type = data.is_round_message()
|
||||
? RoundVideoDocument
|
||||
: VideoDocument;
|
||||
if (data.is_round_message()) {
|
||||
_additional = std::make_unique<RoundData>();
|
||||
round()->duration = data.vduration().v;
|
||||
}
|
||||
} else if (const auto info = sticker()) {
|
||||
info->type = StickerType::Webm;
|
||||
}
|
||||
|
@ -397,7 +401,7 @@ void DocumentData::setattributes(
|
|||
_additional = std::make_unique<SongData>();
|
||||
}
|
||||
}
|
||||
if (const auto voiceData = voice()) {
|
||||
if (const auto voiceData = voice() ? voice() : round()) {
|
||||
voiceData->duration = data.vduration().v;
|
||||
voiceData->waveform = documentWaveformDecode(
|
||||
data.vwaveform().value_or_empty());
|
||||
|
@ -1252,6 +1256,16 @@ const VoiceData *DocumentData::voice() const {
|
|||
return const_cast<DocumentData*>(this)->voice();
|
||||
}
|
||||
|
||||
RoundData *DocumentData::round() {
|
||||
return isVideoMessage()
|
||||
? static_cast<RoundData*>(_additional.get())
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
const RoundData *DocumentData::round() const {
|
||||
return const_cast<DocumentData*>(this)->round();
|
||||
}
|
||||
|
||||
bool DocumentData::hasRemoteLocation() const {
|
||||
return (_dc != 0 && _access != 0);
|
||||
}
|
||||
|
|
|
@ -90,6 +90,8 @@ struct VoiceData : public DocumentAdditionalData {
|
|||
char wavemax = 0;
|
||||
};
|
||||
|
||||
using RoundData = VoiceData;
|
||||
|
||||
namespace Serialize {
|
||||
class Document;
|
||||
} // namespace Serialize;
|
||||
|
@ -152,6 +154,8 @@ public:
|
|||
[[nodiscard]] const SongData *song() const;
|
||||
[[nodiscard]] VoiceData *voice();
|
||||
[[nodiscard]] const VoiceData *voice() const;
|
||||
[[nodiscard]] RoundData *round();
|
||||
[[nodiscard]] const RoundData *round() const;
|
||||
|
||||
void forceIsStreamedAnimation();
|
||||
[[nodiscard]] bool isVoiceMessage() const;
|
||||
|
|
|
@ -1048,6 +1048,23 @@ std::unique_ptr<HistoryView::Media> MediaFile::createView(
|
|||
_document,
|
||||
_skipPremiumEffect,
|
||||
replacing));
|
||||
} else if (_document->isVideoMessage()) {
|
||||
const auto &entry = _document->session().api().transcribes().entry(
|
||||
parent());
|
||||
if (!entry.requestId
|
||||
&& entry.shown
|
||||
&& entry.roundview
|
||||
&& !entry.pending) {
|
||||
return std::make_unique<HistoryView::Document>(
|
||||
message,
|
||||
realParent,
|
||||
_document);
|
||||
} else {
|
||||
return std::make_unique<HistoryView::Gif>(
|
||||
message,
|
||||
realParent,
|
||||
_document);
|
||||
}
|
||||
} else if (_document->isAnimation() || _document->isVideoFile()) {
|
||||
return std::make_unique<HistoryView::Gif>(
|
||||
message,
|
||||
|
|
|
@ -839,7 +839,7 @@ std::optional<int> RepliesList::computeUnreadCountLocally(
|
|||
end(_list),
|
||||
wasReadTillId,
|
||||
std::greater<>());
|
||||
return std::max(*wasUnreadCountAfter - (till - from), 0);
|
||||
return std::max(int(*wasUnreadCountAfter - (till - from)), 0);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ void PaintWaveform(
|
|||
if (const auto song = document->song()) {
|
||||
add(FormatPlayedText(duration, duration));
|
||||
add(FormatDurationAndSizeText(duration, document->size));
|
||||
} else if (const auto voice = document->voice()) {
|
||||
} else if (const auto voice = document->voice() ? document->voice() : document->round()) {
|
||||
add(FormatPlayedText(duration, duration));
|
||||
add(FormatDurationAndSizeText(duration, document->size));
|
||||
} else if (document->isVideoFile()) {
|
||||
|
@ -174,6 +174,12 @@ Document::Document(
|
|||
not_null<DocumentData*> document)
|
||||
: File(parent, realParent)
|
||||
, _data(document) {
|
||||
if (_data->isVideoMessage()) {
|
||||
const auto &entry = _data->session().api().transcribes().entry(
|
||||
realParent);
|
||||
_transcribedRound = entry.shown;
|
||||
}
|
||||
|
||||
auto caption = createCaption();
|
||||
|
||||
createComponents(!caption.isEmpty());
|
||||
|
@ -215,7 +221,7 @@ bool Document::dataLoaded() const {
|
|||
|
||||
void Document::createComponents(bool caption) {
|
||||
uint64 mask = 0;
|
||||
if (_data->isVoiceMessage()) {
|
||||
if (_data->isVoiceMessage() || _transcribedRound) {
|
||||
mask |= HistoryDocumentVoice::Bit();
|
||||
} else {
|
||||
mask |= HistoryDocumentNamed::Bit();
|
||||
|
@ -344,7 +350,9 @@ QSize Document::countOptimalSize() {
|
|||
if (thumbed) {
|
||||
accumulate_max(maxWidth, tleft + MaxStatusWidth(_data) + tright);
|
||||
} else {
|
||||
auto unread = _data->isVoiceMessage() ? (st::mediaUnreadSkip + st::mediaUnreadSize) : 0;
|
||||
auto unread = (_data->isVoiceMessage() || _transcribedRound)
|
||||
? (st::mediaUnreadSkip + st::mediaUnreadSize)
|
||||
: 0;
|
||||
accumulate_max(maxWidth, tleft + MaxStatusWidth(_data) + unread + _parent->skipBlockWidth() + st::msgPadding.right());
|
||||
}
|
||||
|
||||
|
@ -604,8 +612,11 @@ void Document::draw(
|
|||
if (voice) {
|
||||
ensureDataMediaCreated();
|
||||
|
||||
if (const auto voiceData = _data->voice()) {
|
||||
if (voiceData->waveform.isEmpty()) {
|
||||
{
|
||||
const auto voiceData = _data->isVideoMessage()
|
||||
? _data->round()
|
||||
: _data->voice();
|
||||
if (voiceData && voiceData->waveform.isEmpty()) {
|
||||
if (loaded) {
|
||||
Local::countVoiceWaveform(_dataMedia.get());
|
||||
}
|
||||
|
@ -642,7 +653,7 @@ void Document::draw(
|
|||
|
||||
PaintWaveform(p,
|
||||
context,
|
||||
_data->voice(),
|
||||
_transcribedRound ? _data->round() : _data->voice(),
|
||||
namewidth + st::msgWaveformSkip,
|
||||
progress);
|
||||
p.restore();
|
||||
|
@ -1156,6 +1167,8 @@ void Document::setStatusSize(int64 newSize, TimeId realDuration) const {
|
|||
? _data->song()->duration
|
||||
: (_data->isVoiceMessage()
|
||||
? _data->voice()->duration
|
||||
: _transcribedRound
|
||||
? _data->round()->duration
|
||||
: -1);
|
||||
File::setStatusSize(newSize, _data->size, duration, realDuration);
|
||||
if (auto thumbed = Get<HistoryDocumentThumbed>()) {
|
||||
|
@ -1190,7 +1203,7 @@ bool Document::updateStatusText() const {
|
|||
statusSize = Ui::FileStatusSizeReady;
|
||||
}
|
||||
|
||||
if (_data->isVoiceMessage()) {
|
||||
if (_data->isVoiceMessage() || _transcribedRound) {
|
||||
const auto state = ::Media::Player::instance()->getState(AudioMsgId::Type::Voice);
|
||||
if (state.id == AudioMsgId(_data, _realParent->fullId(), state.id.externalPlayId())
|
||||
&& !::Media::Player::IsStoppedOrStopping(state.state)) {
|
||||
|
|
|
@ -174,6 +174,8 @@ private:
|
|||
|
||||
mutable TooltipFilename _tooltipFilename;
|
||||
|
||||
bool _transcribedRound = false;
|
||||
|
||||
};
|
||||
|
||||
bool DrawThumbnailAsSongCover(
|
||||
|
|
|
@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "history/view/media/history_view_gif.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_transcribes.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
#include "main/main_session.h"
|
||||
|
@ -93,6 +95,13 @@ Gif::Gif(
|
|||
_data->loadVideoThumbnail(realParent->fullId());
|
||||
}
|
||||
}
|
||||
|
||||
_transcribe = std::make_shared<LambdaClickHandler>([=,
|
||||
id = realParent->fullId()] {
|
||||
if (const auto item = _data->session().data().message(id)) {
|
||||
_data->session().api().transcribes().toggle(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Gif::~Gif() {
|
||||
|
@ -673,6 +682,21 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
|||
fastShareTop -= (st::msgDateImgDelta + st::msgDateImgPadding.y() + st::msgDateFont->height + st::msgDateImgPadding.y());
|
||||
}
|
||||
_parent->drawRightAction(p, context, fastShareLeft, fastShareTop, 2 * paintx + paintw);
|
||||
if (_data->session().premium()) {
|
||||
const auto stm = context.messageStyle();
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(context.st->msgServiceBg());
|
||||
|
||||
const auto s = st::historyFastShareSize;
|
||||
const auto r = QRect(
|
||||
fastShareLeft,
|
||||
fastShareTop - s - st::msgDateImgDelta,
|
||||
s,
|
||||
s);
|
||||
p.drawEllipse(r);
|
||||
context.st->historyFastTranscribeIcon().paintInCenter(p, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -976,6 +1000,17 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
|
|||
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
|
||||
result.link = _parent->rightActionLink();
|
||||
}
|
||||
if (_data->session().premium()) {
|
||||
const auto s = st::historyFastShareSize;
|
||||
const auto r = QRect(
|
||||
fastShareLeft,
|
||||
fastShareTop - s - st::msgDateImgDelta,
|
||||
s,
|
||||
s);
|
||||
if (r.contains(point)) {
|
||||
result.link = _transcribe;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -201,6 +201,8 @@ private:
|
|||
mutable bool _thumbCacheBlurred = false;
|
||||
mutable bool _thumbIsEllipse = false;
|
||||
|
||||
ClickHandlerPtr _transcribe;
|
||||
|
||||
};
|
||||
|
||||
} // namespace HistoryView
|
||||
|
|
|
@ -876,6 +876,7 @@ historyFastShareBottom: 5px;
|
|||
historyFastShareIcon: icon {{ "fast_share", msgServiceFg }};
|
||||
historyGoToOriginalIcon: icon {{ "fast_to_original", msgServiceFg }};
|
||||
historyFastCommentsIcon: icon {{ "fast_comments", msgServiceFg }};
|
||||
historyFastTranscribeIcon: icon {{ "chat/voice_to_text", msgServiceFg }};
|
||||
|
||||
historySavedFont: font(semibold 14px);
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ ChatStyle::ChatStyle() {
|
|||
make(_msgBotKbWebviewIcon, st::msgBotKbWebviewIcon);
|
||||
make(_historyFastCommentsIcon, st::historyFastCommentsIcon);
|
||||
make(_historyFastShareIcon, st::historyFastShareIcon);
|
||||
make(_historyFastTranscribeIcon, st::historyFastTranscribeIcon);
|
||||
make(_historyGoToOriginalIcon, st::historyGoToOriginalIcon);
|
||||
make(_historyMapPoint, st::historyMapPoint);
|
||||
make(_historyMapPointInner, st::historyMapPointInner);
|
||||
|
|
|
@ -252,6 +252,9 @@ public:
|
|||
[[nodiscard]] const style::icon &historyFastShareIcon() const {
|
||||
return _historyFastShareIcon;
|
||||
}
|
||||
[[nodiscard]] const style::icon &historyFastTranscribeIcon() const {
|
||||
return _historyFastTranscribeIcon;
|
||||
}
|
||||
[[nodiscard]] const style::icon &historyGoToOriginalIcon() const {
|
||||
return _historyGoToOriginalIcon;
|
||||
}
|
||||
|
@ -344,6 +347,7 @@ private:
|
|||
style::icon _msgBotKbWebviewIcon = { Qt::Uninitialized };
|
||||
style::icon _historyFastCommentsIcon = { Qt::Uninitialized };
|
||||
style::icon _historyFastShareIcon = { Qt::Uninitialized };
|
||||
style::icon _historyFastTranscribeIcon = { Qt::Uninitialized };
|
||||
style::icon _historyGoToOriginalIcon = { Qt::Uninitialized };
|
||||
style::icon _historyMapPoint = { Qt::Uninitialized };
|
||||
style::icon _historyMapPointInner = { Qt::Uninitialized };
|
||||
|
|
Loading…
Add table
Reference in a new issue