mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-01 12:00:48 +00:00
Allow selecting / copying voice transcribe text.
This commit is contained in:
parent
1467b1c720
commit
0fc687953f
@ -35,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/emoji_config.h"
|
||||
#include "api/api_sending.h"
|
||||
#include "api/api_transcribes.h"
|
||||
#include "storage/storage_shared_media.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "chat_helpers/stickers_dice_pack.h" // Stickers::DicePacks::IsSlot.
|
||||
@ -56,6 +57,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/file_upload.h"
|
||||
#include "window/window_session_controller.h" // Window::Show
|
||||
#include "apiwrap.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
|
||||
@ -858,9 +860,27 @@ TextForMimeData MediaFile::clipboardText() const {
|
||||
}
|
||||
return tr::lng_in_dlg_file(tr::now) + addName;
|
||||
}();
|
||||
return WithCaptionClipboardText(
|
||||
attachType,
|
||||
parent()->clipboardText());
|
||||
auto caption = parent()->clipboardText();
|
||||
|
||||
if (_document->isVoiceMessage()) {
|
||||
const auto &entry = _document->session().api().transcribes().entry(
|
||||
parent());
|
||||
if (!entry.requestId
|
||||
&& entry.shown
|
||||
&& !entry.toolong
|
||||
&& !entry.failed
|
||||
&& (entry.pending || !entry.result.isEmpty())) {
|
||||
const auto text = "{{\n"
|
||||
+ entry.result
|
||||
+ (entry.result.isEmpty() ? "" : " ")
|
||||
+ (entry.pending ? "[...]" : "")
|
||||
+ "\n}}"
|
||||
+ (caption.rich.text.isEmpty() ? "" : "\n");
|
||||
caption = TextForMimeData{ text, { text } }.append(std::move(caption));
|
||||
}
|
||||
}
|
||||
|
||||
return WithCaptionClipboardText(attachType, std::move(caption));
|
||||
}
|
||||
|
||||
bool MediaFile::allowsEditCaption() const {
|
||||
|
@ -235,6 +235,17 @@ void Document::fillNamedFromData(HistoryDocumentNamed *named) {
|
||||
|
||||
QSize Document::countOptimalSize() {
|
||||
auto captioned = Get<HistoryDocumentCaptioned>();
|
||||
if (_parent->media() != this && !_realParent->groupId()) {
|
||||
if (captioned) {
|
||||
RemoveComponents(HistoryDocumentCaptioned::Bit());
|
||||
captioned = nullptr;
|
||||
}
|
||||
} else if (captioned && captioned->_caption.hasSkipBlock()) {
|
||||
captioned->_caption.updateSkipBlock(
|
||||
_parent->skipBlockWidth(),
|
||||
_parent->skipBlockHeight());
|
||||
}
|
||||
|
||||
auto hasTranscribe = false;
|
||||
const auto voice = Get<HistoryDocumentVoice>();
|
||||
if (voice) {
|
||||
@ -277,21 +288,17 @@ QSize Document::countOptimalSize() {
|
||||
st::messageTextStyle,
|
||||
text);
|
||||
hasTranscribe = true;
|
||||
if (const auto skipBlockWidth = captioned
|
||||
? 0
|
||||
: _parent->skipBlockWidth()) {
|
||||
voice->transcribeText.updateSkipBlock(
|
||||
skipBlockWidth,
|
||||
_parent->skipBlockHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_parent->media() != this && !_realParent->groupId()) {
|
||||
if (captioned) {
|
||||
RemoveComponents(HistoryDocumentCaptioned::Bit());
|
||||
captioned = nullptr;
|
||||
}
|
||||
} else if (captioned && captioned->_caption.hasSkipBlock()) {
|
||||
captioned->_caption.updateSkipBlock(
|
||||
_parent->skipBlockWidth(),
|
||||
_parent->skipBlockHeight());
|
||||
}
|
||||
|
||||
auto thumbed = Get<HistoryDocumentThumbed>();
|
||||
const auto &st = thumbed ? st::msgFileThumbLayout : st::msgFileLayout;
|
||||
if (thumbed) {
|
||||
@ -655,15 +662,17 @@ void Document::draw(
|
||||
}
|
||||
}
|
||||
|
||||
auto selection = context.selection;
|
||||
auto captiontop = bottom;
|
||||
if (voice && !voice->transcribeText.isEmpty()) {
|
||||
p.setPen(stm->historyTextFg);
|
||||
voice->transcribeText.draw(p, st::msgPadding.left(), bottom, captionw, style::al_left, 0, -1, context.selection);
|
||||
voice->transcribeText.draw(p, st::msgPadding.left(), bottom, captionw, style::al_left, 0, -1, selection);
|
||||
captiontop += voice->transcribeText.countHeight(captionw) + st::mediaCaptionSkip;
|
||||
selection = HistoryView::UnshiftItemSelection(selection, voice->transcribeText);
|
||||
}
|
||||
if (auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
if (const auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
p.setPen(stm->historyTextFg);
|
||||
captioned->_caption.draw(p, st::msgPadding.left(), captiontop, captionw, style::al_left, 0, -1, context.selection);
|
||||
captioned->_caption.draw(p, st::msgPadding.left(), captiontop, captionw, style::al_left, 0, -1, selection);
|
||||
}
|
||||
}
|
||||
|
||||
@ -812,7 +821,7 @@ TextState Document::textState(
|
||||
const auto nametop = st.nameTop - topMinus;
|
||||
const auto nameright = st.padding.left();
|
||||
const auto linktop = st.linkTop - topMinus;
|
||||
const auto bottom = st.padding.top() + st.thumbSize + st.padding.bottom() - topMinus;
|
||||
auto bottom = st.padding.top() + st.thumbSize + st.padding.bottom() - topMinus;
|
||||
const auto rthumb = style::rtlrect(st.padding.left(), st.padding.top() - topMinus, st.thumbSize, st.thumbSize, width);
|
||||
const auto innerSize = st::msgFileLayout.thumbSize;
|
||||
const auto inner = QRect(rthumb.x() + (rthumb.width() - innerSize) / 2, rthumb.y() + (rthumb.height() - innerSize) / 2, innerSize, innerSize);
|
||||
@ -844,6 +853,9 @@ TextState Document::textState(
|
||||
|
||||
const auto voice = Get<HistoryDocumentVoice>();
|
||||
auto namewidth = width - nameleft - nameright;
|
||||
auto transcribeLength = 0;
|
||||
auto transcribeHeight = 0;
|
||||
auto painth = layout.height();
|
||||
if (voice) {
|
||||
auto waveformbottom = st.padding.top() - topMinus + st::msgWaveformMax + st::msgWaveformMin;
|
||||
if (voice->transcribe) {
|
||||
@ -867,15 +879,36 @@ TextState Document::textState(
|
||||
return result;
|
||||
}
|
||||
}
|
||||
transcribeLength = voice->transcribeText.length();
|
||||
if (transcribeLength > 0) {
|
||||
auto captionw = width - st::msgPadding.left() - st::msgPadding.right();
|
||||
transcribeHeight = voice->transcribeText.countHeight(captionw);
|
||||
painth -= transcribeHeight;
|
||||
if (point.y() >= bottom && point.y() < bottom + transcribeHeight) {
|
||||
result = TextState(_parent, voice->transcribeText.getState(
|
||||
point - QPoint(st::msgPadding.left(), bottom),
|
||||
width - st::msgPadding.left() - st::msgPadding.right(),
|
||||
request.forText()));
|
||||
return result;
|
||||
}
|
||||
bottom += transcribeHeight;
|
||||
}
|
||||
}
|
||||
|
||||
auto painth = layout.height();
|
||||
if (const auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
if (point.y() >= bottom) {
|
||||
result.symbol += transcribeLength;
|
||||
}
|
||||
if (transcribeHeight) {
|
||||
painth -= st::mediaCaptionSkip;
|
||||
bottom += st::mediaCaptionSkip;
|
||||
}
|
||||
if (point.y() >= bottom) {
|
||||
result = TextState(_parent, captioned->_caption.getState(
|
||||
point - QPoint(st::msgPadding.left(), bottom),
|
||||
width - st::msgPadding.left() - st::msgPadding.right(),
|
||||
request.forText()));
|
||||
result.symbol += transcribeLength;
|
||||
return result;
|
||||
}
|
||||
auto captionw = width - st::msgPadding.left() - st::msgPadding.right();
|
||||
@ -883,6 +916,8 @@ TextState Document::textState(
|
||||
if (isBubbleBottom()) {
|
||||
painth -= st::msgPadding.bottom();
|
||||
}
|
||||
} else if (transcribeHeight && isBubbleBottom()) {
|
||||
painth -= st::msgPadding.bottom();
|
||||
}
|
||||
const auto till = voice ? (nameleft + namewidth) : width;
|
||||
if (QRect(0, 0, till, painth).contains(point)
|
||||
@ -901,7 +936,7 @@ TextState Document::textState(
|
||||
|
||||
void Document::updatePressed(QPoint point) {
|
||||
// LayoutMode should be passed here.
|
||||
if (auto voice = Get<HistoryDocumentVoice>()) {
|
||||
if (const auto voice = Get<HistoryDocumentVoice>()) {
|
||||
if (voice->seeking()) {
|
||||
const auto thumbed = Get<HistoryDocumentThumbed>();
|
||||
const auto &st = thumbed ? st::msgFileThumbLayout : st::msgFileLayout;
|
||||
@ -920,28 +955,80 @@ void Document::updatePressed(QPoint point) {
|
||||
TextSelection Document::adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const {
|
||||
auto transcribe = (const Ui::Text::String*)nullptr;
|
||||
auto caption = (const Ui::Text::String*)nullptr;
|
||||
if (const auto voice = Get<HistoryDocumentVoice>()) {
|
||||
transcribe = &voice->transcribeText;
|
||||
}
|
||||
if (const auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
return captioned->_caption.adjustSelection(selection, type);
|
||||
caption = &captioned->_caption;
|
||||
}
|
||||
const auto transcribeLength = transcribe ? transcribe->length() : 0;
|
||||
if (transcribe && selection.from < transcribeLength) {
|
||||
const auto adjusted = transcribe->adjustSelection(selection, type);
|
||||
if (selection.to <= transcribeLength) {
|
||||
return adjusted;
|
||||
}
|
||||
selection = TextSelection(adjusted.from, selection.to);
|
||||
}
|
||||
if (caption && selection.to > transcribeLength) {
|
||||
auto unshifted = transcribe
|
||||
? HistoryView::UnshiftItemSelection(selection, *transcribe)
|
||||
: selection;
|
||||
const auto adjusted = caption->adjustSelection(unshifted, type);
|
||||
const auto shifted = transcribe
|
||||
? HistoryView::ShiftItemSelection(adjusted, *transcribe)
|
||||
: adjusted;
|
||||
if (selection.from >= transcribeLength) {
|
||||
return shifted;
|
||||
}
|
||||
selection = TextSelection(selection.from, shifted.to);
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
|
||||
uint16 Document::fullSelectionLength() const {
|
||||
auto result = uint16();
|
||||
if (const auto voice = Get<HistoryDocumentVoice>()) {
|
||||
result += voice->transcribeText.length();
|
||||
}
|
||||
if (const auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
return captioned->_caption.length();
|
||||
result += captioned->_caption.length();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Document::hasTextForCopy() const {
|
||||
if (const auto voice = Get<HistoryDocumentVoice>()) {
|
||||
if (!voice->transcribeText.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Has<HistoryDocumentCaptioned>();
|
||||
}
|
||||
|
||||
TextForMimeData Document::selectedText(TextSelection selection) const {
|
||||
if (const auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
return captioned->_caption.toTextForMimeData(selection);
|
||||
auto result = TextForMimeData();
|
||||
if (const auto voice = Get<HistoryDocumentVoice>()) {
|
||||
const auto length = voice->transcribeText.length();
|
||||
if (selection.from < length) {
|
||||
result.append(
|
||||
voice->transcribeText.toTextForMimeData(selection));
|
||||
}
|
||||
if (selection.to <= length) {
|
||||
return result;
|
||||
}
|
||||
selection = HistoryView::UnshiftItemSelection(
|
||||
selection,
|
||||
voice->transcribeText);
|
||||
}
|
||||
return TextForMimeData();
|
||||
if (const auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
if (!result.empty()) {
|
||||
result.append("\n\n");
|
||||
}
|
||||
result.append(captioned->_caption.toTextForMimeData(selection));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Document::uploading() const {
|
||||
|
Loading…
Reference in New Issue
Block a user