Inline bot results preview: photo, audio, file, voice. Beta 9040126.

This commit is contained in:
John Preston 2016-04-10 22:18:26 +04:00
parent fe59c815b2
commit dd1d04e9b0
32 changed files with 597 additions and 258 deletions

View File

@ -1736,14 +1736,16 @@ namespace {
}
HistoryItem *histItemById(ChannelId channelId, MsgId itemId) {
MsgsData *data = fetchMsgsData(channelId, false);
if (!data) return 0;
if (!itemId) return nullptr;
MsgsData::const_iterator i = data->constFind(itemId);
MsgsData *data = fetchMsgsData(channelId, false);
if (!data) return nullptr;
auto i = data->constFind(itemId);
if (i != data->cend()) {
return i.value();
}
return 0;
return nullptr;
}
void historyRegItem(HistoryItem *item) {

View File

@ -171,7 +171,7 @@ void StickerSetInner::mouseMoveEvent(QMouseEvent *e) {
int32 index = stickerFromGlobalPos(e->globalPos());
if (index >= 0 && index < _pack.size() && index != _previewShown) {
_previewShown = index;
Ui::showStickerPreview(_pack.at(_previewShown));
Ui::showMediaPreview(_pack.at(_previewShown));
}
}
}
@ -184,7 +184,7 @@ void StickerSetInner::onPreview() {
int32 index = stickerFromGlobalPos(QCursor::pos());
if (index >= 0 && index < _pack.size()) {
_previewShown = index;
Ui::showStickerPreview(_pack.at(_previewShown));
Ui::showMediaPreview(_pack.at(_previewShown));
}
}

View File

@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
static const int32 AppVersion = 9040;
static const wchar_t *AppVersionStr = L"0.9.40";
static const bool DevVersion = false;
#define BETA_VERSION (9040124ULL) // just comment this line to build public version
#define BETA_VERSION (9040126ULL) // just comment this line to build public version
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
static const wchar_t *AppName = L"Telegram Desktop";

View File

@ -2046,6 +2046,19 @@ int32 StickerPanInner::validateExistingInlineRows(const InlineResults &results)
return until;
}
void StickerPanInner::notify_inlineItemLayoutChanged(const InlineItem *layout) {
if (_selected < 0 || !_showingInlineItems) {
return;
}
int32 row = _selected / MatrixRowShift, col = _selected % MatrixRowShift;
if (row < _inlineRows.size() && col < _inlineRows.at(row).items.size()) {
if (layout == _inlineRows.at(row).items.at(col)) {
updateSelected();
}
}
}
void StickerPanInner::ui_repaintInlineItem(const InlineItem *layout) {
uint64 ms = getms();
if (_lastScrolled + 100 <= ms) {
@ -2279,8 +2292,11 @@ void StickerPanInner::updateSelected() {
if (_pressedSel >= 0 && _selected >= 0 && _pressedSel != _selected) {
_pressedSel = _selected;
if (row >= 0 && col >= 0) {
if (DocumentData *previewDocument = _inlineRows.at(row).items.at(col)->getPreviewDocument()) {
Ui::showStickerPreview(previewDocument);
auto layout = _inlineRows.at(row).items.at(col);
if (auto previewDocument = layout->getPreviewDocument()) {
Ui::showMediaPreview(previewDocument);
} else if (auto previewPhoto = layout->getPreviewPhoto()) {
Ui::showMediaPreview(previewPhoto);
}
}
}
@ -2366,7 +2382,7 @@ void StickerPanInner::updateSelected() {
if (_pressedSel >= 0 && _selected >= 0 && _pressedSel != _selected) {
_pressedSel = _selected;
if (newSel >= 0 && xNewSel < 0) {
Ui::showStickerPreview(_sets.at(newSelTab).pack.at(newSel % MatrixRowShift));
Ui::showMediaPreview(_sets.at(newSelTab).pack.at(newSel % MatrixRowShift));
}
}
if (startanim && !_a_selected.animating()) _a_selected.start();
@ -2381,15 +2397,19 @@ void StickerPanInner::onPreview() {
if (_showingInlineItems) {
int32 row = _pressedSel / MatrixRowShift, col = _pressedSel % MatrixRowShift;
if (row < _inlineRows.size() && col < _inlineRows.at(row).items.size()) {
if (DocumentData *previewDocument = _inlineRows.at(row).items.at(col)->getPreviewDocument()) {
Ui::showStickerPreview(previewDocument);
auto layout = _inlineRows.at(row).items.at(col);
if (auto previewDocument = layout->getPreviewDocument()) {
Ui::showMediaPreview(previewDocument);
_previewShown = true;
} else if (auto previewPhoto = layout->getPreviewPhoto()) {
Ui::showMediaPreview(previewPhoto);
_previewShown = true;
}
}
} else if (_pressedSel < MatrixRowShift * _sets.size()) {
int tab = (_pressedSel / MatrixRowShift), sel = _pressedSel % MatrixRowShift;
if (sel < _sets.at(tab).pack.size()) {
Ui::showStickerPreview(_sets.at(tab).pack.at(sel));
Ui::showMediaPreview(_sets.at(tab).pack.at(sel));
_previewShown = true;
}
}
@ -3392,6 +3412,12 @@ void EmojiPan::stickersInstalled(uint64 setId) {
showStart();
}
void EmojiPan::notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout) {
if (_stickersShown && !isHidden()) {
s_inner.notify_inlineItemLayoutChanged(layout);
}
}
void EmojiPan::ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout) {
if (_stickersShown && !isHidden()) {
s_inner.ui_repaintInlineItem(layout);
@ -4233,7 +4259,7 @@ void MentionsInner::onUpdateSelected(bool force) {
if (_down >= 0 && _sel >= 0 && _down != _sel) {
_down = _sel;
if (_down >= 0 && _down < _srows->size()) {
Ui::showStickerPreview(_srows->at(_down));
Ui::showMediaPreview(_srows->at(_down));
}
}
}
@ -4249,7 +4275,7 @@ void MentionsInner::onParentGeometryChanged() {
void MentionsInner::onPreview() {
if (_down >= 0 && _down < _srows->size()) {
Ui::showStickerPreview(_srows->at(_down));
Ui::showMediaPreview(_srows->at(_down));
_previewShown = true;
}
}

View File

@ -383,6 +383,7 @@ public:
uint64 currentSet(int yOffset) const;
void notify_inlineItemLayoutChanged(const InlineItem *layout);
void ui_repaintInlineItem(const InlineItem *layout);
bool ui_isInlineItemVisible(const InlineItem *layout);
bool ui_isInlineItemBeingChosen();
@ -607,6 +608,7 @@ public:
).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
}
void notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
void ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
bool ui_isInlineItemVisible(const InlineBots::Layout::ItemBase *layout);
bool ui_isInlineItemBeingChosen();

View File

@ -149,15 +149,21 @@ namespace App {
namespace Ui {
void showStickerPreview(DocumentData *sticker) {
void showMediaPreview(DocumentData *document) {
if (Window *w = App::wnd()) {
w->ui_showStickerPreview(sticker);
w->ui_showMediaPreview(document);
}
}
void hideStickerPreview() {
void showMediaPreview(PhotoData *photo) {
if (Window *w = App::wnd()) {
w->ui_hideStickerPreview();
w->ui_showMediaPreview(photo);
}
}
void hideMediaPreview() {
if (Window *w = App::wnd()) {
w->ui_hideMediaPreview();
}
}
@ -292,6 +298,10 @@ namespace Notify {
if (MainWidget *m = App::main()) m->notify_historyItemLayoutChanged(item);
}
void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout) {
if (MainWidget *m = App::main()) m->notify_inlineItemLayoutChanged(layout);
}
void handlePendingHistoryUpdate() {
if (MainWidget *m = App::main()) {
m->notify_handlePendingHistoryUpdate();

View File

@ -52,8 +52,9 @@ class ItemBase;
namespace Ui {
void showStickerPreview(DocumentData *sticker);
void hideStickerPreview();
void showMediaPreview(DocumentData *document);
void showMediaPreview(PhotoData *photo);
void hideMediaPreview();
void showLayer(LayeredWidget *box, ShowLayerOptions options = CloseOtherLayers);
void hideLayer(bool fast = false);
@ -110,6 +111,7 @@ namespace Notify {
void clipStopperHidden(ClipStopperType type);
void historyItemLayoutChanged(const HistoryItem *item);
void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
// handle pending resize() / paint() on history items
void handlePendingHistoryUpdate();

View File

@ -4452,7 +4452,7 @@ bool HistoryDocument::updateStatusText() const {
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
}
if (playing.msgId == _parent->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
if (playing == AudioMsgId(_data, _parent->fullId()) && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
if (auto voice = Get<HistoryDocumentVoice>()) {
bool was = voice->_playback;
voice->ensurePlayback(this);
@ -4486,14 +4486,14 @@ bool HistoryDocument::updateStatusText() const {
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
}
if (playing.msgId == _parent->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
if (playing == SongMsgId(_data, _parent->fullId()) && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
statusSize = -1 - (playingPosition / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency));
realDuration = playingDuration / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency);
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
} else {
statusSize = FileStatusSizeLoaded;
}
if (!showPause && playing.msgId == _parent->fullId() && App::main() && App::main()->player()->seekingSong(playing)) {
if (!showPause && (playing == SongMsgId(_data, _parent->fullId())) && App::main() && App::main()->player()->seekingSong(playing)) {
showPause = true;
}
} else {

View File

@ -6394,6 +6394,10 @@ void HistoryWidget::notify_historyItemLayoutChanged(const HistoryItem *item) {
}
}
void HistoryWidget::notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout) {
_emojiPan.notify_inlineItemLayoutChanged(layout);
}
void HistoryWidget::notify_handlePendingHistoryUpdate() {
if (hasPendingResizedItems()) {
updateListSize();

View File

@ -680,6 +680,7 @@ public:
PeerData *ui_getPeerForMouseAction();
void notify_historyItemLayoutChanged(const HistoryItem *item);
void notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
void notify_botCommandsChanged(UserData *user);
void notify_inlineBotRequesting(bool requesting);
void notify_replyMarkupUpdated(const HistoryItem *item);

View File

@ -66,15 +66,25 @@ int FileBase::content_height() const {
}
int FileBase::content_duration() const {
DocumentData *document = getShownDocument();
if (document->duration() > 0) {
return document->duration();
} else if (SongData *song = document->song()) {
if (song->duration) {
return song->duration;
if (DocumentData *document = getShownDocument()) {
if (document->duration() > 0) {
return document->duration();
} else if (SongData *song = document->song()) {
if (song->duration) {
return song->duration;
}
}
}
return 0;
return getResultDuration();
}
ImagePtr FileBase::content_thumb() const {
if (DocumentData *document = getShownDocument()) {
if (!document->thumb->isNull()) {
return document->thumb;
}
}
return getResultThumb();
}
Gif::Gif(Result *result) : FileBase(result) {
@ -186,9 +196,6 @@ void Gif::paint(Painter &p, const QRect &clip, uint32 selection, const PaintCont
p.drawSpriteLeft(deletePos, _width, st::stickerPanDelete);
p.setOpacity(1);
}
if (!document->hasRemoteLocation()) {
p.fillRect(10, 10, 30, 30, QColor(255, 0, 0));
}
}
void Gif::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
@ -477,9 +484,6 @@ void Photo::paint(Painter &p, const QRect &clip, uint32 selection, const PaintCo
} else {
p.drawPixmap(r.topLeft(), _thumb);
}
if (getShownPhoto()->full->toDelayedStorageImage()) {
p.fillRect(10, 10, 30, 30, QColor(255, 0, 0));
}
}
void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
@ -560,7 +564,7 @@ Video::Video(Result *result) : FileBase(result)
}
void Video::initDimensions() {
bool withThumb = !getShownDocument()->thumb->isNull();
bool withThumb = !content_thumb()->isNull();
_maxw = st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft;
int32 textWidth = _maxw - (withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : 0);
@ -589,7 +593,7 @@ void Video::initDimensions() {
void Video::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
int left = st::inlineThumbSize + st::inlineThumbSkip;
bool withThumb = !getShownDocument()->thumb->isNull();
bool withThumb = !content_thumb()->isNull();
if (withThumb) {
prepareThumb(st::inlineThumbSize, st::inlineThumbSize);
if (_thumb.isNull()) {
@ -636,7 +640,7 @@ void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i
}
void Video::prepareThumb(int32 width, int32 height) const {
ImagePtr thumb = getShownDocument()->thumb;
ImagePtr thumb = content_thumb();
if (thumb->loaded()) {
if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) {
int32 w = qMax(convertScale(thumb->width()), 1), h = qMax(convertScale(thumb->height()), 1);
@ -668,9 +672,11 @@ void CancelFileClickHandler::onClickImpl() const {
File::File(Result *result) : FileBase(result)
, _title(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::msgFileSize - st::inlineThumbSkip)
, _description(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::msgFileSize - st::inlineThumbSkip) {
//, _open(new OpenFileClickHandler(result))
//, _cancel(new CancelFileClickHandler(result)) {
, _description(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::msgFileSize - st::inlineThumbSkip)
, _open(new OpenFileClickHandler(result))
, _cancel(new CancelFileClickHandler(result)) {
updateStatusText();
regDocumentItem(getShownDocument(), this);
}
void File::initDimensions() {
@ -698,7 +704,7 @@ void File::paint(Painter &p, const QRect &clip, uint32 selection, const PaintCon
_animation->radial.start(document->progress());
}
}
bool showPause = false;// updateStatusText(parent);
bool showPause = updateStatusText();
bool radial = isRadialAnimation(context->ms);
QRect iconCircle = rtlrect(0, st::inlineRowMargin, st::msgFileSize, st::msgFileSize, _width);
@ -715,28 +721,26 @@ void File::paint(Painter &p, const QRect &clip, uint32 selection, const PaintCon
p.drawEllipse(iconCircle);
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
if (radial) {
QRect radialCircle(iconCircle.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
_animation->radial.draw(p, radialCircle, st::msgFileRadialLine, st::msgInBg);
}
style::sprite icon;
//if (bool showPause = false) {
// icon = st::msgFileInPause;
//} else if (radial || content_loading()) {
// icon = st::msgFileInCancel;
//} else if (loaded) {
// //if (_data->song() || _data->voice()) {
// icon = st::msgFileInPlay;
// //} else if (_data->isImage()) {
// // icon = st::msgFileInImage;
// //} else {
// // icon = st::msgFileInFile;
// //}
//} else {
// icon = st::msgFileInDownload;
//}
if (document->isImage()) {
icon = st::msgFileInImage;
} else if (document->voice() || document->song()) {
icon = st::msgFileInPlay;
if (showPause) {
icon = st::msgFileInPause;
} else if (radial || document->loading()) {
icon = st::msgFileInCancel;
} else if (document->loaded()) {
if (document->isImage()) {
icon = st::msgFileInImage;
} else if (document->voice() || document->song()) {
icon = st::msgFileInPlay;
} else {
icon = st::msgFileInFile;
}
} else {
icon = st::msgFileInFile;
icon = st::msgFileInDownload;
}
p.drawSpriteCenter(iconCircle, icon);
@ -747,7 +751,12 @@ void File::paint(Painter &p, const QRect &clip, uint32 selection, const PaintCon
_title.drawLeftElided(p, left, titleTop, _width - left, _width);
p.setPen(st::inlineDescriptionFg);
_description.drawLeftElided(p, left, descriptionTop, _width - left, _width);
if (_statusText.isEmpty()) {
_description.drawLeftElided(p, left, descriptionTop, _width - left, _width);
} else {
p.setFont(st::normalFont);
p.drawTextLeft(left, descriptionTop, _width, _statusText);
}
if (!context->lastRow) {
p.fillRect(rtlrect(left, _height - st::inlineRowBorder, _width - left, st::inlineRowBorder, _width), st::inlineRowBorderFg);
@ -767,17 +776,24 @@ void File::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, in
void File::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
if (p == _open || p == _cancel) {
if (active && !getShownDocument()->loaded()) {
if (active) {
ensureAnimation();
_animation->a_thumbOver.start(1);
_animation->_a_thumbOver.start();
} else if (!active && _animation) {
} else {
if (!_animation) {
ensureAnimation();
_animation->a_thumbOver = anim::fvalue(1, 1);
}
_animation->a_thumbOver.start(0);
_animation->_a_thumbOver.start();
}
_animation->_a_thumbOver.start();
}
}
File::~File() {
unregDocumentItem(getShownDocument(), this);
}
void File::step_thumbOver(float64 ms, bool timer) {
float64 dt = ms / st::msgFileOverDuration;
if (dt >= 1) {
@ -797,7 +813,7 @@ void File::step_radial(uint64 ms, bool timer) {
Ui::repaintInlineItem(this);
} else {
DocumentData *document = getShownDocument();
_animation->radial.update(document->progress(), document->loaded(), ms);
_animation->radial.update(document->progress(), !document->loading() || document->loaded(), ms);
if (!_animation->radial.animating()) {
checkAnimationFinished();
}
@ -820,6 +836,83 @@ void File::checkAnimationFinished() {
}
}
bool File::updateStatusText() const {
bool showPause = false;
int32 statusSize = 0, realDuration = 0;
DocumentData *document = getShownDocument();
if (document->status == FileDownloadFailed || document->status == FileUploadFailed) {
statusSize = FileStatusSizeFailed;
} else if (document->status == FileUploading) {
statusSize = document->uploadOffset;
} else if (document->loading()) {
statusSize = document->loadOffset();
} else if (document->loaded()) {
if (document->voice()) {
AudioMsgId playing;
AudioPlayerState playingState = AudioPlayerStopped;
int64 playingPosition = 0, playingDuration = 0;
int32 playingFrequency = 0;
if (audioPlayer()) {
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
}
if (playing == AudioMsgId(document, FullMsgId()) && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
statusSize = -1 - (playingPosition / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency));
realDuration = playingDuration / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency);
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
} else {
statusSize = FileStatusSizeLoaded;
}
} else if (document->song()) {
SongMsgId playing;
AudioPlayerState playingState = AudioPlayerStopped;
int64 playingPosition = 0, playingDuration = 0;
int32 playingFrequency = 0;
if (audioPlayer()) {
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
}
if (playing == SongMsgId(document, FullMsgId()) && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
statusSize = -1 - (playingPosition / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency));
realDuration = playingDuration / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency);
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
} else {
statusSize = FileStatusSizeLoaded;
}
if (!showPause && (playing == SongMsgId(document, FullMsgId())) && App::main() && App::main()->player()->seekingSong(playing)) {
showPause = true;
}
} else {
statusSize = FileStatusSizeLoaded;
}
} else {
statusSize = FileStatusSizeReady;
}
if (statusSize != _statusSize) {
int32 duration = document->song() ? document->song()->duration : (document->voice() ? document->voice()->duration : -1);
setStatusSize(statusSize, document->size, duration, realDuration);
}
return showPause;
}
void File::setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const {
_statusSize = newSize;
if (_statusSize == FileStatusSizeReady) {
// _statusText = (duration >= 0) ? formatDurationAndSizeText(duration, fullSize) : (duration < -1 ? formatGifAndSizeText(fullSize) : formatSizeText(fullSize));
_statusText = QString();
} else if (_statusSize == FileStatusSizeLoaded) {
// _statusText = (duration >= 0) ? formatDurationText(duration) : (duration < -1 ? qsl("GIF") : formatSizeText(fullSize));
_statusText = QString();
} else if (_statusSize == FileStatusSizeFailed) {
// _statusText = lang(lng_attach_failed);
_statusText = QString();
} else if (_statusSize >= 0) {
_statusText = formatDownloadText(_statusSize, fullSize);
} else {
_statusText = formatPlayedText(-_statusSize - 1, realDuration);
}
}
Contact::Contact(Result *result) : ItemBase(result)
, _title(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip)
, _description(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip) {

View File

@ -38,8 +38,8 @@ protected:
int content_width() const;
int content_height() const;
FileLocation content_location() const;
int content_duration() const;
ImagePtr content_thumb() const;
};
class DeleteSavedGifClickHandler : public LeftButtonClickHandler {
@ -244,16 +244,15 @@ public:
// ClickHandlerHost interface
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
~File();
private:
Text _title, _description;
ClickHandlerPtr _open, _cancel;
void step_thumbOver(float64 ms, bool timer);
void step_radial(uint64 ms, bool timer);
void ensureAnimation() const;
void checkAnimationFinished();
bool updateStatusText() const;
bool isRadialAnimation(uint64 ms) const {
if (!_animation || !_animation->radial.animating()) return false;
@ -280,6 +279,19 @@ private:
};
mutable UniquePointer<AnimationData> _animation;
Text _title, _description;
ClickHandlerPtr _open, _cancel;
// >= 0 will contain download / upload string, _statusSize = loaded bytes
// < 0 will contain played string, _statusSize = -(seconds + 1) played
// 0x7FFFFFF0 will contain status for not yet downloaded file
// 0x7FFFFFF1 will contain status for already downloaded file
// 0x7FFFFFF2 will contain status for failed to download / upload file
mutable int32 _statusSize;
mutable QString _statusText;
// duration = -1 - no duration, duration = -2 - "GIF" duration
void setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const;
};

View File

@ -67,6 +67,16 @@ DocumentData *ItemBase::getPreviewDocument() const {
return nullptr;
}
PhotoData *ItemBase::getPreviewPhoto() const {
if (_photo) {
return _photo;
}
if (_result) {
return _result->_photo;
}
return nullptr;
}
void ItemBase::preload() const {
if (_result) {
if (_result->_photo) {
@ -179,5 +189,35 @@ QString ItemBase::getResultThumbLetter() const {
return QString();
}
namespace {
NeverFreedPointer<DocumentItems> documentItemsMap;
} // namespace
const DocumentItems *documentItems() {
return documentItemsMap.data();
}
namespace internal {
void regDocumentItem(DocumentData *document, ItemBase *item) {
documentItemsMap.makeIfNull();
(*documentItemsMap)[document].insert(item);
}
void unregDocumentItem(DocumentData *document, ItemBase *item) {
if (documentItemsMap) {
auto i = documentItemsMap->find(document);
if (i != documentItemsMap->cend()) {
if (i->remove(item) && i->isEmpty()) {
documentItemsMap->erase(i);
}
}
}
}
} // namespace internal
} // namespace Layout
} // namespace InlineBots

View File

@ -37,6 +37,7 @@ public:
, lastRow(lastRow) {
}
bool paused, lastRow;
};
// this type used as a flag, we dynamic_cast<> to it
@ -73,9 +74,10 @@ public:
DocumentData *getDocument() const;
PhotoData *getPhoto() const;
// Get document (possibly from InlineBots::Result) for
// showing sticker or GIF preview.
// Get document or photo (possibly from InlineBots::Result) for
// showing sticker / GIF / photo preview by long mouse press.
DocumentData *getPreviewDocument() const;
PhotoData *getPreviewPhoto() const;
virtual void preload() const;
@ -113,5 +115,14 @@ protected:
};
using DocumentItems = QMap<DocumentData*, OrderedSet<ItemBase*>>;
const DocumentItems *documentItems();
namespace internal {
void regDocumentItem(DocumentData *document, ItemBase *item);
void unregDocumentItem(DocumentData *document, ItemBase *item);
} // namespace internal
} // namespace Layout
} // namespace InlineBots

View File

@ -129,6 +129,19 @@ UniquePointer<Result> Result::create(uint64 queryId, const MTPBotInlineResult &m
return UniquePointer<Result>();
}
// Ensure required media fields for layouts.
if (result->_type == Type::Photo) {
if (!result->_photo && result->_content_url.isEmpty()) {
return UniquePointer<Result>();
}
result->createPhoto();
} else if (result->_type == Type::File || result->_type == Type::Gif || result->_type == Type::Sticker) {
if (!result->_document && result->_content_url.isEmpty()) {
return UniquePointer<Result>();
}
result->createDocument();
}
switch (message->type()) {
case mtpc_botInlineMessageMediaAuto: {
const auto &r(message->c_botInlineMessageMediaAuto());
@ -319,8 +332,9 @@ void Result::createPhoto() {
QSize mediumsize = shrinkToKeepAspect(_width, _height, 320, 320);
ImagePtr medium = ImagePtr(mediumsize.width(), mediumsize.height());
ImagePtr full = ImagePtr(_content_url, _width, _height);
uint64 photoId = rand_value<uint64>();
_photo = App::photoSet(photoId, 0, 0, unixtime(), _thumb, medium, ImagePtr(_width, _height));
_photo = App::photoSet(photoId, 0, 0, unixtime(), _thumb, medium, full);
_photo->thumb = _thumb;
}

View File

@ -190,17 +190,14 @@ BackgroundWidget::~BackgroundWidget() {
}
}
StickerPreviewWidget::StickerPreviewWidget(QWidget *parent) : TWidget(parent)
MediaPreviewWidget::MediaPreviewWidget(QWidget *parent) : TWidget(parent)
, a_shown(0, 0)
, _a_shown(animation(this, &StickerPreviewWidget::step_shown))
, _doc(0)
, _gif(0)
, _cacheStatus(CacheNotLoaded) {
, _a_shown(animation(this, &MediaPreviewWidget::step_shown)) {
setAttribute(Qt::WA_TransparentForMouseEvents);
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
}
void StickerPreviewWidget::paintEvent(QPaintEvent *e) {
void MediaPreviewWidget::paintEvent(QPaintEvent *e) {
Painter p(this);
QRect r(e->rect());
@ -216,11 +213,11 @@ void StickerPreviewWidget::paintEvent(QPaintEvent *e) {
p.drawPixmap((width() - w) / 2, (height() - h) / 2, draw);
}
void StickerPreviewWidget::resizeEvent(QResizeEvent *e) {
void MediaPreviewWidget::resizeEvent(QResizeEvent *e) {
update();
}
void StickerPreviewWidget::step_shown(float64 ms, bool timer) {
void MediaPreviewWidget::step_shown(float64 ms, bool timer) {
float64 dt = ms / st::stickerPreviewDuration;
if (dt >= 1) {
_a_shown.stop();
@ -232,79 +229,126 @@ void StickerPreviewWidget::step_shown(float64 ms, bool timer) {
if (timer) update();
}
void StickerPreviewWidget::showPreview(DocumentData *sticker) {
if (sticker && !sticker->isAnimation() && !sticker->sticker()) sticker = 0;
if (sticker) {
_cache = QPixmap();
if (isHidden() || _a_shown.animating()) {
if (isHidden()) show();
a_shown.start(1);
_a_shown.start();
} else {
update();
}
} else if (isHidden()) {
void MediaPreviewWidget::showPreview(DocumentData *document) {
if (!document || (!document->isAnimation() && !document->sticker())) {
hidePreview();
return;
} else {
if (_gif) _cache = currentImage();
a_shown.start(0);
_a_shown.start();
}
_doc = sticker;
startShow();
_photo = nullptr;
_document = document;
resetGifAndCache();
}
void MediaPreviewWidget::showPreview(PhotoData *photo) {
if (!photo || photo->full->isNull()) {
hidePreview();
return;
}
startShow();
_photo = photo;
_document = nullptr;
resetGifAndCache();
}
void MediaPreviewWidget::startShow() {
_cache = QPixmap();
if (isHidden() || _a_shown.animating()) {
if (isHidden()) show();
a_shown.start(1);
_a_shown.start();
} else {
update();
}
}
void MediaPreviewWidget::hidePreview() {
if (isHidden()) {
return;
}
if (_gif) _cache = currentImage();
a_shown.start(0);
_a_shown.start();
_photo = nullptr;
_document = nullptr;
resetGifAndCache();
}
void MediaPreviewWidget::resetGifAndCache() {
if (_gif) {
if (gif()) {
delete _gif;
}
_gif = 0;
_gif = nullptr;
}
_cacheStatus = CacheNotLoaded;
_cachedSize = QSize();
}
void StickerPreviewWidget::hidePreview() {
showPreview(0);
}
QSize StickerPreviewWidget::currentDimensions() const {
if (!_doc) return QSize(_cache.width() / cIntRetinaFactor(), _cache.height() / cIntRetinaFactor());
QSize result(qMax(convertScale(_doc->dimensions.width()), 1), qMax(convertScale(_doc->dimensions.height()), 1));
if (gif() && _gif->ready()) {
result = QSize(qMax(convertScale(_gif->width()), 1), qMax(convertScale(_gif->height()), 1));
QSize MediaPreviewWidget::currentDimensions() const {
if (!_cachedSize.isEmpty()) {
return _cachedSize;
}
if (result.width() > st::maxStickerSize) {
result.setHeight(qMax(qRound((st::maxStickerSize * result.height()) / result.width()), 1));
result.setWidth(st::maxStickerSize);
if (!_document && !_photo) {
_cachedSize = QSize(_cache.width() / cIntRetinaFactor(), _cache.height() / cIntRetinaFactor());
return _cachedSize;
}
if (result.height() > st::maxStickerSize) {
result.setWidth(qMax(qRound((st::maxStickerSize * result.width()) / result.height()), 1));
result.setHeight(st::maxStickerSize);
QSize result, box;
if (_photo) {
result = QSize(_photo->full->width(), _photo->full->height());
box = QSize(width() - 2 * st::boxVerticalMargin, height() - 2 * st::boxVerticalMargin);
} else {
result = _document->dimensions;
if (gif() && _gif->ready()) {
result = QSize(_gif->width(), _gif->height());
}
if (_document->sticker()) {
box = QSize(st::maxStickerSize, st::maxStickerSize);
} else {
box = QSize(2 * st::maxStickerSize, 2 * st::maxStickerSize);
}
}
result = QSize(qMax(convertScale(result.width()), 1), qMax(convertScale(result.height()), 1));
if (result.width() > box.width()) {
result.setHeight(qMax((box.width() * result.height()) / result.width(), 1));
result.setWidth(box.width());
}
if (result.height() > box.height()) {
result.setWidth(qMax((box.height() * result.width()) / result.height(), 1));
result.setHeight(box.height());
}
if (_photo) {
_cachedSize = result;
}
return result;
}
QPixmap StickerPreviewWidget::currentImage() const {
if (_doc) {
if (_doc->sticker()) {
QPixmap MediaPreviewWidget::currentImage() const {
if (_document) {
if (_document->sticker()) {
if (_cacheStatus != CacheLoaded) {
_doc->checkSticker();
if (_doc->sticker()->img->isNull()) {
if (_cacheStatus != CacheThumbLoaded && _doc->thumb->loaded()) {
_document->checkSticker();
if (_document->sticker()->img->isNull()) {
if (_cacheStatus != CacheThumbLoaded && _document->thumb->loaded()) {
QSize s = currentDimensions();
_cache = _doc->thumb->pixBlurred(s.width(), s.height());
_cache = _document->thumb->pixBlurred(s.width(), s.height());
_cacheStatus = CacheThumbLoaded;
}
} else {
QSize s = currentDimensions();
_cache = _doc->sticker()->img->pix(s.width(), s.height());
_cache = _document->sticker()->img->pix(s.width(), s.height());
_cacheStatus = CacheLoaded;
}
}
} else {
_doc->automaticLoad(0);
if (_doc->loaded()) {
_document->automaticLoad(nullptr);
if (_document->loaded()) {
if (!_gif && _gif != BadClipReader) {
StickerPreviewWidget *that = const_cast<StickerPreviewWidget*>(this);
that->_gif = new ClipReader(_doc->location(), _doc->data(), func(that, &StickerPreviewWidget::clipCallback));
MediaPreviewWidget *that = const_cast<MediaPreviewWidget*>(this);
that->_gif = new ClipReader(_document->location(), _document->data(), func(that, &MediaPreviewWidget::clipCallback));
if (gif()) _gif->setAutoplay();
}
}
@ -312,17 +356,36 @@ QPixmap StickerPreviewWidget::currentImage() const {
QSize s = currentDimensions();
return _gif->current(s.width(), s.height(), s.width(), s.height(), getms());
}
if (_cacheStatus != CacheThumbLoaded && _doc->thumb->loaded()) {
if (_cacheStatus != CacheThumbLoaded && _document->thumb->loaded()) {
QSize s = currentDimensions();
_cache = _doc->thumb->pixBlurred(s.width(), s.height());
_cache = _document->thumb->pixBlurred(s.width(), s.height());
_cacheStatus = CacheThumbLoaded;
}
}
} else if (_photo) {
if (_cacheStatus != CacheLoaded) {
if (_photo->full->loaded()) {
QSize s = currentDimensions();
LOG(("DIMENSIONS: %1 %2").arg(s.width()).arg(s.height()));
_cache = _photo->full->pix(s.width(), s.height());
_cacheStatus = CacheLoaded;
} else {
if (_cacheStatus != CacheThumbLoaded && _photo->thumb->loaded()) {
QSize s = currentDimensions();
LOG(("DIMENSIONS: %1 %2").arg(s.width()).arg(s.height()));
_cache = _photo->thumb->pixBlurred(s.width(), s.height());
_cacheStatus = CacheThumbLoaded;
}
_photo->thumb->load();
_photo->full->load();
}
}
}
return _cache;
}
void StickerPreviewWidget::clipCallback(ClipReaderNotification notification) {
void MediaPreviewWidget::clipCallback(ClipReaderNotification notification) {
switch (notification) {
case ClipReaderReinit: {
if (gif() && _gif->state() == ClipError) {
@ -346,5 +409,5 @@ void StickerPreviewWidget::clipCallback(ClipReaderNotification notification) {
}
}
StickerPreviewWidget::~StickerPreviewWidget() {
MediaPreviewWidget::~MediaPreviewWidget() {
}

View File

@ -106,32 +106,36 @@ private:
BoxShadow shadow;
};
class StickerPreviewWidget : public TWidget {
class MediaPreviewWidget : public TWidget {
Q_OBJECT
public:
StickerPreviewWidget(QWidget *parent);
MediaPreviewWidget(QWidget *parent);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
void step_shown(float64 ms, bool timer);
void showPreview(DocumentData *sticker);
void showPreview(DocumentData *document);
void showPreview(PhotoData *photo);
void hidePreview();
~StickerPreviewWidget();
~MediaPreviewWidget();
private:
QSize currentDimensions() const;
QPixmap currentImage() const;
void startShow();
void resetGifAndCache();
anim::fvalue a_shown;
Animation _a_shown;
DocumentData *_doc;
ClipReader *_gif;
DocumentData *_document = nullptr;
PhotoData *_photo = nullptr;
ClipReader *_gif = nullptr;
bool gif() const {
return (!_gif || _gif == BadClipReader) ? false : true;
}
@ -143,7 +147,8 @@ private:
CacheThumbLoaded,
CacheLoaded,
};
mutable CacheStatus _cacheStatus;
mutable CacheStatus _cacheStatus = CacheNotLoaded;
mutable QPixmap _cache;
mutable QSize _cachedSize;
};

View File

@ -737,7 +737,7 @@ bool LayoutOverviewVoice::updateStatusText() const {
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
}
if (playing.msgId == _parent->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
if (playing == AudioMsgId(_data, _parent->fullId()) && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
statusSize = -1 - (playingPosition / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency));
realDuration = playingDuration / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency);
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
@ -1046,14 +1046,14 @@ bool LayoutOverviewDocument::updateStatusText() const {
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
}
if (playing.msgId == _parent->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
if (playing == SongMsgId(_data, _parent->fullId()) && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
statusSize = -1 - (playingPosition / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency));
realDuration = playingDuration / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency);
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
} else {
statusSize = FileStatusSizeLoaded;
}
if (!showPause && playing.msgId == _parent->fullId() && App::main() && App::main()->player()->seekingSong(playing)) {
if (!showPause && (playing == SongMsgId(_data, _parent->fullId())) && App::main() && App::main()->player()->seekingSong(playing)) {
showPause = true;
}
} else {

View File

@ -84,7 +84,6 @@ RoundCorners documentCorners(int32 colorIndex);
class PaintContextBase {
public:
PaintContextBase(uint64 ms, bool selecting) : ms(ms), selecting(selecting) {
}
uint64 ms;

View File

@ -19,15 +19,16 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "mainwidget.h"
#include "ui/style.h"
#include "lang.h"
#include "boxes/addcontactbox.h"
#include "fileuploader.h"
#include "application.h"
#include "window.h"
#include "settingswidget.h"
#include "mainwidget.h"
#include "inline_bots/inline_bot_layout_item.h"
#include "boxes/confirmbox.h"
#include "boxes/stickersetbox.h"
#include "boxes/contactsbox.h"
@ -838,6 +839,10 @@ void MainWidget::notify_historyItemLayoutChanged(const HistoryItem *item) {
if (overview) overview->notify_historyItemLayoutChanged(item);
}
void MainWidget::notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout) {
history.notify_inlineItemLayoutChanged(layout);
}
void MainWidget::notify_handlePendingHistoryUpdate() {
history.notify_handlePendingHistoryUpdate();
}
@ -1854,9 +1859,14 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
}
}
if (HistoryItem *item = App::histItemById(audioId.msgId)) {
if (HistoryItem *item = App::histItemById(audioId.contextId)) {
Ui::repaintHistoryItem(item);
}
if (auto items = InlineBots::Layout::documentItems()) {
for (auto item : items->value(audioId.audio)) {
Ui::repaintInlineItem(item);
}
}
}
void MainWidget::documentPlayProgress(const SongMsgId &songId) {
@ -1889,9 +1899,14 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
}
}
if (HistoryItem *item = App::histItemById(songId.msgId)) {
if (HistoryItem *item = App::histItemById(songId.contextId)) {
Ui::repaintHistoryItem(item);
}
if (auto items = InlineBots::Layout::documentItems()) {
for (auto item : items->value(songId.song)) {
Ui::repaintInlineItem(item);
}
}
}
void MainWidget::hidePlayer() {

View File

@ -465,6 +465,7 @@ public:
void notify_migrateUpdated(PeerData *peer);
void notify_clipStopperHidden(ClipStopperType type);
void notify_historyItemLayoutChanged(const HistoryItem *item);
void notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
void notify_handlePendingHistoryUpdate();
void cmd_search();

View File

@ -862,7 +862,7 @@ void MediaView::showPhoto(PhotoData *photo, PeerData *context) {
void MediaView::showDocument(DocumentData *doc, HistoryItem *context) {
_photo = 0;
_history = context ? context->history() : 0;
_history = context ? context->history() : nullptr;
if (_history) {
if (_history->peer->migrateFrom()) {
_migrated = App::history(_history->peer->migrateFrom()->id);
@ -910,7 +910,7 @@ void MediaView::displayPhoto(PhotoData *photo, HistoryItem *item) {
_zoom = 0;
_caption = Text();
if (HistoryMessage *itemMsg = item ? item->toHistoryMessage() : 0) {
if (HistoryMessage *itemMsg = item ? item->toHistoryMessage() : nullptr) {
if (HistoryPhoto *photoMsg = dynamic_cast<HistoryPhoto*>(itemMsg->getMedia())) {
_caption.setText(st::mvCaptionFont, photoMsg->getCaption(), (item->author()->isUser() && item->author()->asUser()->botInfo) ? _captionBotOptions : _captionTextOptions);
}
@ -958,7 +958,7 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
stopGif();
}
_doc = doc;
_photo = 0;
_photo = nullptr;
_current = QPixmap();
@ -1087,7 +1087,11 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
}
_x = (width() - _w) / 2;
_y = (height() - _h) / 2;
_from = item->authorOriginal();
if (_msgid && item) {
_from = item->authorOriginal();
} else {
_from = _user;
}
_full = 1;
updateControls();
if (isHidden()) {

View File

@ -2107,7 +2107,7 @@ int32 OverviewWidget::countBestScroll() const {
AudioPlayerState playingState = AudioPlayerStopped;
audioPlayer()->currentState(&playing, &playingState);
if (playing) {
int32 top = _inner.itemTop(playing.msgId);
int32 top = _inner.itemTop(playing.contextId);
if (top >= 0) {
return snap(top - int(_scroll.height() - (st::msgPadding.top() + st::mediaThumbSize + st::msgPadding.bottom())) / 2, 0, _scroll.scrollTopMax());
}

View File

@ -209,7 +209,7 @@ void PlayerWidget::mousePressEvent(QMouseEvent *e) {
updateDownTime();
}
} else if (_over == OverFull && _song) {
if (HistoryItem *item = App::histItemById(_song.msgId)) {
if (HistoryItem *item = App::histItemById(_song.contextId)) {
App::main()->showMediaOverview(item->history()->peer, OverviewMusicFiles);
}
} else if (_over == OverRepeat) {
@ -294,12 +294,12 @@ void PlayerWidget::updateControls() {
void PlayerWidget::findCurrent() {
_index = -1;
if (!_history) return;
if (!_history || !_song.contextId.msg) return;
const History::MediaOverview *o = &(_msgmigrated ? _migrated : _history)->overview[OverviewMusicFiles];
if ((_msgmigrated ? _migrated : _history)->channelId() == _song.msgId.channel) {
if ((_msgmigrated ? _migrated : _history)->channelId() == _song.contextId.channel) {
for (int i = 0, l = o->size(); i < l; ++i) {
if (o->at(i) == _song.msgId.msg) {
if (o->at(i) == _song.contextId.msg) {
_index = i;
break;
}
@ -351,9 +351,9 @@ void PlayerWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type)
if (_history && (_history->peer == peer || (_migrated && _migrated->peer == peer)) && type == OverviewMusicFiles) {
_index = -1;
History *history = _msgmigrated ? _migrated : _history;
if (history->channelId() == _song.msgId.channel) {
if (history->channelId() == _song.contextId.channel && _song.contextId.msg) {
for (int i = 0, l = history->overview[OverviewMusicFiles].size(); i < l; ++i) {
if (history->overview[OverviewMusicFiles].at(i) == _song.msgId.msg) {
if (history->overview[OverviewMusicFiles].at(i) == _song.contextId.msg) {
_index = i;
preloadNext();
break;
@ -596,7 +596,7 @@ void PlayerWidget::updateState(SongMsgId playing, AudioPlayerState playingState,
if (playing && _song != playing) {
songChanged = true;
_song = playing;
if (HistoryItem *item = App::histItemById(_song.msgId)) {
if (HistoryItem *item = App::histItemById(_song.contextId)) {
_history = item->history();
if (_history->peer->migrateFrom()) {
_migrated = App::history(_history->peer->migrateFrom()->id);
@ -608,7 +608,7 @@ void PlayerWidget::updateState(SongMsgId playing, AudioPlayerState playingState,
}
findCurrent();
} else {
_history = 0;
_history = nullptr;
_msgmigrated = false;
_index = -1;
}
@ -691,13 +691,16 @@ void PlayerWidget::updateState(SongMsgId playing, AudioPlayerState playingState,
if (wasPlaying && playingState == AudioPlayerStoppedAtEnd) {
if (_repeat) {
startPlay(_song.msgId);
if (_song.song) {
audioPlayer()->play(_song);
updateState();
}
} else {
nextPressed();
}
}
if (songChanged) {
emit playerSongChanged(_song.msgId);
emit playerSongChanged(_song.contextId);
}
}

View File

@ -19,9 +19,11 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "structs.h"
#include "ui/style.h"
#include "lang.h"
#include "inline_bots/inline_bot_layout_item.h"
#include "history.h"
#include "mainwidget.h"
#include "application.h"
@ -853,10 +855,13 @@ QString documentSaveFilename(const DocumentData *data, bool forceSavingAs = fals
void DocumentOpenClickHandler::doOpen(DocumentData *data, ActionOnLoad action) {
if (!data->date) return;
HistoryItem *item = App::hoveredLinkItem() ? App::hoveredLinkItem() : (App::contextItem() ? App::contextItem() : 0);
bool playVoice = data->voice() && audioPlayer() && item;
bool playMusic = data->song() && audioPlayer() && item;
HistoryItem *item = App::hoveredLinkItem() ? App::hoveredLinkItem() : (App::contextItem() ? App::contextItem() : nullptr);
FullMsgId msgId;
if (item) {
msgId = item->fullId();
}
bool playVoice = data->voice() && audioPlayer();
bool playMusic = data->song() && audioPlayer();
bool playAnimation = data->isAnimation() && item && item->getMedia();
const FileLocation &location(data->location(true));
if (!location.isEmpty() || (!data->data().isEmpty() && (playVoice || playMusic || playAnimation))) {
@ -864,10 +869,10 @@ void DocumentOpenClickHandler::doOpen(DocumentData *data, ActionOnLoad action) {
AudioMsgId playing;
AudioPlayerState playingState = AudioPlayerStopped;
audioPlayer()->currentState(&playing, &playingState);
if (playing.msgId == item->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
if (playing == AudioMsgId(data, msgId) && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
audioPlayer()->pauseresume(OverviewVoiceFiles);
} else {
AudioMsgId audio(data, item->fullId());
AudioMsgId audio(data, msgId);
audioPlayer()->play(audio);
if (App::main()) {
App::main()->audioPlayProgress(audio);
@ -878,10 +883,10 @@ void DocumentOpenClickHandler::doOpen(DocumentData *data, ActionOnLoad action) {
SongMsgId playing;
AudioPlayerState playingState = AudioPlayerStopped;
audioPlayer()->currentState(&playing, &playingState);
if (playing.msgId == item->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
if (playing == SongMsgId(data, msgId) && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
audioPlayer()->pauseresume(OverviewFiles);
} else {
SongMsgId song(data, item->fullId());
SongMsgId song(data, msgId);
audioPlayer()->play(song);
if (App::main()) App::main()->documentPlayProgress(song);
}
@ -896,8 +901,8 @@ void DocumentOpenClickHandler::doOpen(DocumentData *data, ActionOnLoad action) {
App::wnd()->showDocument(data, item);
}
} else if (location.accessEnable()) {
if (item && (data->isAnimation() || QImageReader(location.name()).canRead())) {
if (action == ActionOnLoadPlayInline && item->getMedia()) {
if (data->isAnimation() || QImageReader(location.name()).canRead()) {
if (action == ActionOnLoadPlayInline && item && item->getMedia()) {
item->getMedia()->playInline(item);
} else {
App::wnd()->showDocument(data, item);
@ -923,7 +928,7 @@ void DocumentOpenClickHandler::doOpen(DocumentData *data, ActionOnLoad action) {
if (filename.isEmpty()) return;
}
data->save(filename, action, item ? item->fullId() : FullMsgId());
data->save(filename, action, msgId);
}
void DocumentOpenClickHandler::onClickImpl() const {
@ -1133,17 +1138,17 @@ void DocumentData::performActionOnLoad() {
const FileLocation &loc(location(true));
QString already = loc.name();
HistoryItem *item = _actionOnLoadMsgId.msg ? App::histItemById(_actionOnLoadMsgId) : 0;
bool showImage = !isVideo() && item && (size < MediaViewImageSizeLimit);
bool playVoice = voice() && audioPlayer() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen) && item;
bool playMusic = song() && audioPlayer() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen) && item;
bool playAnimation = isAnimation() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen) && showImage && item->getMedia();
HistoryItem *item = _actionOnLoadMsgId.msg ? App::histItemById(_actionOnLoadMsgId) : nullptr;
bool showImage = !isVideo() && (size < MediaViewImageSizeLimit);
bool playVoice = voice() && audioPlayer() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen);
bool playMusic = song() && audioPlayer() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen);
bool playAnimation = isAnimation() && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen) && showImage && item && item->getMedia();
if (playVoice) {
if (loaded()) {
AudioMsgId playing;
AudioPlayerState state = AudioPlayerStopped;
audioPlayer()->currentState(&playing, &state);
if (playing.msgId == _actionOnLoadMsgId && !(state & AudioPlayerStoppedMask) && state != AudioPlayerFinishing) {
if (playing == AudioMsgId(this, _actionOnLoadMsgId) && !(state & AudioPlayerStoppedMask) && state != AudioPlayerFinishing) {
audioPlayer()->pauseresume(OverviewVoiceFiles);
} else {
audioPlayer()->play(AudioMsgId(this, _actionOnLoadMsgId));
@ -1155,10 +1160,10 @@ void DocumentData::performActionOnLoad() {
SongMsgId playing;
AudioPlayerState playingState = AudioPlayerStopped;
audioPlayer()->currentState(&playing, &playingState);
if (playing.msgId == item->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
if (playing == SongMsgId(this, _actionOnLoadMsgId) && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
audioPlayer()->pauseresume(OverviewFiles);
} else {
SongMsgId song(this, item->fullId());
SongMsgId song(this, _actionOnLoadMsgId);
audioPlayer()->play(song);
if (App::main()) App::main()->documentPlayProgress(song);
}
@ -1185,7 +1190,7 @@ void DocumentData::performActionOnLoad() {
if (App::main()) App::main()->mediaMarkRead(this);
} else if (loc.accessEnable()) {
if (showImage && QImageReader(loc.name()).canRead()) {
if (_actionOnLoad == ActionOnLoadPlayInline && item->getMedia()) {
if (_actionOnLoad == ActionOnLoadPlayInline && item && item->getMedia()) {
item->getMedia()->playInline(item);
} else {
App::wnd()->showDocument(this, item);
@ -1322,6 +1327,12 @@ void DocumentData::notifyLayoutChanged() const {
Notify::historyItemLayoutChanged(j.key());
}
}
if (auto items = InlineBots::Layout::documentItems()) {
for (auto item : items->value(const_cast<DocumentData*>(this))) {
Notify::inlineItemLayoutChanged(item);
}
}
}
VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit) {

View File

@ -1157,49 +1157,50 @@ VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit);
QByteArray documentWaveformEncode5bit(const VoiceWaveform &waveform);
struct SongMsgId {
SongMsgId() : song(0) {
SongMsgId() : song(nullptr) {
}
SongMsgId(DocumentData *song, const FullMsgId &msgId) : song(song), msgId(msgId) {
SongMsgId(DocumentData *song, const FullMsgId &msgId) : song(song), contextId(msgId) {
}
SongMsgId(DocumentData *song, ChannelId channelId, MsgId msgId) : song(song), msgId(channelId, msgId) {
SongMsgId(DocumentData *song, ChannelId channelId, MsgId msgId) : song(song), contextId(channelId, msgId) {
}
operator bool() const {
explicit operator bool() const {
return song;
}
DocumentData *song;
FullMsgId msgId;
FullMsgId contextId;
};
inline bool operator<(const SongMsgId &a, const SongMsgId &b) {
return quintptr(a.song) < quintptr(b.song) || (quintptr(a.song) == quintptr(b.song) && a.msgId < b.msgId);
return quintptr(a.song) < quintptr(b.song) || (quintptr(a.song) == quintptr(b.song) && a.contextId < b.contextId);
}
inline bool operator==(const SongMsgId &a, const SongMsgId &b) {
return a.song == b.song && a.msgId == b.msgId;
return a.song == b.song && a.contextId == b.contextId;
}
inline bool operator!=(const SongMsgId &a, const SongMsgId &b) {
return !(a == b);
}
struct AudioMsgId {
AudioMsgId() : audio(0) {
AudioMsgId() : audio(nullptr) {
}
AudioMsgId(DocumentData *audio, const FullMsgId &msgId) : audio(audio), msgId(msgId) {
AudioMsgId(DocumentData *audio, const FullMsgId &msgId) : audio(audio), contextId(msgId) {
}
AudioMsgId(DocumentData *audio, ChannelId channelId, MsgId msgId) : audio(audio), msgId(channelId, msgId) {
AudioMsgId(DocumentData *audio, ChannelId channelId, MsgId msgId) : audio(audio), contextId(channelId, msgId) {
}
operator bool() const {
explicit operator bool() const {
return audio;
}
DocumentData *audio;
FullMsgId msgId;
FullMsgId contextId;
};
inline bool operator<(const AudioMsgId &a, const AudioMsgId &b) {
return quintptr(a.audio) < quintptr(b.audio) || (quintptr(a.audio) == quintptr(b.audio) && a.msgId < b.msgId);
return quintptr(a.audio) < quintptr(b.audio) || (quintptr(a.audio) == quintptr(b.audio) && a.contextId < b.contextId);
}
inline bool operator==(const AudioMsgId &a, const AudioMsgId &b) {
return a.audio == b.audio && a.msgId == b.msgId;
return a.audio == b.audio && a.contextId == b.contextId;
}
inline bool operator!=(const AudioMsgId &a, const AudioMsgId &b) {
return !(a == b);

View File

@ -30,7 +30,7 @@ namespace {
typedef QMap<QString, Image*> LocalImages;
LocalImages localImages;
typedef QMap<QString, Image*> WebImages;
typedef QMap<QString, WebImage*> WebImages;
WebImages webImages;
Image *blank() {
@ -944,6 +944,14 @@ void DelayedStorageImage::cancel() {
WebImage::WebImage(const QString &url, QSize box) : _url(url), _box(box), _size(0), _width(0), _height(0) {
}
WebImage::WebImage(const QString &url, int width, int height) : _url(url), _size(0), _width(width), _height(height) {
}
void WebImage::setSize(int width, int height) {
_width = width;
_height = height;
}
int32 WebImage::countWidth() const {
return _width;
}
@ -954,8 +962,7 @@ int32 WebImage::countHeight() const {
void WebImage::setInformation(int32 size, int32 width, int32 height) {
_size = size;
_width = width;
_height = height;
setSize(width, height);
}
FileLoader *WebImage::createLoader(LoadFromCloudSetting fromCloud, bool autoLoading) {
@ -992,6 +999,17 @@ Image *getImage(const QString &url, QSize box) {
return i.value();
}
Image *getImage(const QString &url, int width, int height) {
QString key = url;
auto i = webImages.constFind(key);
if (i == webImages.cend()) {
i = webImages.insert(key, new WebImage(url, width, height));
} else {
i.value()->setSize(width, height);
}
return i.value();
}
Image *getImage(const QByteArray &filecontent, QByteArray format) {
return new Image(filecontent, format);
}

View File

@ -353,6 +353,9 @@ public:
// If !box.isEmpty() then resize the image to fit in this box.
WebImage(const QString &url, QSize box = QSize());
WebImage(const QString &url, int width, int height);
void setSize(int width, int height);
protected:
@ -375,6 +378,7 @@ private:
namespace internal {
Image *getImage(const QString &file, QByteArray format);
Image *getImage(const QString &url, QSize box);
Image *getImage(const QString &url, int width, int height);
Image *getImage(const QByteArray &filecontent, QByteArray format);
Image *getImage(const QPixmap &pixmap, QByteArray format);
Image *getImage(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap);
@ -390,6 +394,8 @@ public:
}
ImagePtr(const QString &url, QSize box) : Parent(internal::getImage(url, box)) {
}
ImagePtr(const QString &url, int width, int height) : Parent(internal::getImage(url, width, height)) {
}
ImagePtr(const QByteArray &filecontent, QByteArray format = QByteArray()) : Parent(internal::getImage(filecontent, format)) {
}
ImagePtr(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap) : Parent(internal::getImage(filecontent, format, pixmap)) {

View File

@ -364,23 +364,7 @@ NotifyWindow::~NotifyWindow() {
if (App::wnd()) App::wnd()->notifyShowNext(this);
}
Window::Window(QWidget *parent) : PsMainWindow(parent)
, _serviceHistoryRequest(0)
, title(0)
, _passcode(0)
, intro(0)
, main(0)
, settings(0)
, layerBg(0)
, _stickerPreview(0)
, _isActive(false)
, _connecting(0)
, _clearManager(0)
, dragging(false)
, _inactivePress(false)
, _shouldLockAt(0)
, _mediaView(0) {
Window::Window(QWidget *parent) : PsMainWindow(parent) {
icon16 = icon256.scaledToWidth(16, Qt::SmoothTransformation);
icon32 = icon256.scaledToWidth(32, Qt::SmoothTransformation);
icon64 = icon256.scaledToWidth(64, Qt::SmoothTransformation);
@ -861,21 +845,33 @@ bool Window::ui_isMediaViewShown() {
return _mediaView && !_mediaView->isHidden();
}
void Window::ui_showStickerPreview(DocumentData *sticker) {
if (!sticker || ((!sticker->isAnimation() || !sticker->loaded()) && !sticker->sticker())) return;
if (!_stickerPreview) {
_stickerPreview = new StickerPreviewWidget(this);
resizeEvent(0);
void Window::ui_showMediaPreview(DocumentData *document) {
if (!document || ((!document->isAnimation() || !document->loaded()) && !document->sticker())) return;
if (!_mediaPreview) {
_mediaPreview = MakeUnique<MediaPreviewWidget>(this);
resizeEvent(nullptr);
}
if (_stickerPreview->isHidden()) {
if (_mediaPreview->isHidden()) {
fixOrder();
}
_stickerPreview->showPreview(sticker);
_mediaPreview->showPreview(document);
}
void Window::ui_hideStickerPreview() {
if (!_stickerPreview) return;
_stickerPreview->hidePreview();
void Window::ui_showMediaPreview(PhotoData *photo) {
if (!photo) return;
if (!_mediaPreview) {
_mediaPreview = MakeUnique<MediaPreviewWidget>(this);
resizeEvent(nullptr);
}
if (_mediaPreview->isHidden()) {
fixOrder();
}
_mediaPreview->showPreview(photo);
}
void Window::ui_hideMediaPreview() {
if (!_mediaPreview) return;
_mediaPreview->hidePreview();
}
PeerData *Window::ui_getPeerForMouseAction() {
@ -1040,7 +1036,7 @@ bool Window::eventFilter(QObject *obj, QEvent *e) {
break;
case QEvent::MouseButtonRelease:
Ui::hideStickerPreview();
Ui::hideMediaPreview();
break;
case QEvent::ShortcutOverride: // handle shortcuts ourselves
@ -1249,7 +1245,7 @@ void Window::layerFinishedHide(BackgroundWidget *was) {
void Window::fixOrder() {
title->raise();
if (layerBg) layerBg->raise();
if (_stickerPreview) _stickerPreview->raise();
if (_mediaPreview) _mediaPreview->raise();
if (_connecting) _connecting->raise();
}
@ -1321,7 +1317,7 @@ void Window::resizeEvent(QResizeEvent *e) {
}
title->setGeometry(0, 0, width(), st::titleHeight);
if (layerBg) layerBg->resize(width(), height());
if (_stickerPreview) _stickerPreview->setGeometry(0, title->height(), width(), height() - title->height());
if (_mediaPreview) _mediaPreview->setGeometry(0, title->height(), width(), height() - title->height());
if (_connecting) _connecting->setGeometry(0, height() - _connecting->height(), _connecting->width(), _connecting->height());
emit resized(QSize(width(), height() - st::titleHeight));
}
@ -1921,7 +1917,6 @@ void Window::updateIsActive(int timeout) {
Window::~Window() {
notifyClearFast();
deleteAndMark(_stickerPreview);
delete _clearManager;
delete _connecting;
delete _mediaView;

View File

@ -121,7 +121,7 @@ private:
typedef QList<NotifyWindow*> NotifyWindows;
class StickerPreviewWidget;
class MediaPreviewWidget;
class Window : public PsMainWindow {
Q_OBJECT
@ -239,8 +239,9 @@ public:
void ui_showLayer(LayeredWidget *box, ShowLayerOptions options);
bool ui_isLayerShown();
bool ui_isMediaViewShown();
void ui_showStickerPreview(DocumentData *sticker);
void ui_hideStickerPreview();
void ui_showMediaPreview(DocumentData *document);
void ui_showMediaPreview(PhotoData *photo);
void ui_hideMediaPreview();
PeerData *ui_getPeerForMouseAction();
public slots:
@ -306,33 +307,33 @@ private:
typedef QPair<QString, MTPMessageMedia> DelayedServiceMsg;
QVector<DelayedServiceMsg> _delayedServiceMsgs;
mtpRequestId _serviceHistoryRequest;
mtpRequestId _serviceHistoryRequest = 0;
TitleWidget *title;
PasscodeWidget *_passcode;
IntroWidget *intro;
MainWidget *main;
SettingsWidget *settings;
BackgroundWidget *layerBg;
StickerPreviewWidget *_stickerPreview;
TitleWidget *title = nullptr;
PasscodeWidget *_passcode = nullptr;
IntroWidget *intro = nullptr;
MainWidget *main = nullptr;
SettingsWidget *settings = nullptr;
BackgroundWidget *layerBg = nullptr;
UniquePointer<MediaPreviewWidget> _mediaPreview;
QTimer _isActiveTimer;
bool _isActive;
bool _isActive = false;
ConnectingWidget *_connecting;
ConnectingWidget *_connecting = nullptr;
Local::ClearManager *_clearManager;
Local::ClearManager *_clearManager = nullptr;
void clearWidgets();
bool dragging;
bool dragging = false;
QPoint dragStart;
bool _inactivePress;
bool _inactivePress = false;
QTimer _inactiveTimer;
SingleTimer _autoLockTimer;
uint64 _shouldLockAt;
uint64 _shouldLockAt = 0;
typedef QMap<MsgId, uint64> NotifyWhenMap;
typedef QMap<History*, NotifyWhenMap> NotifyWhenMaps;
@ -355,7 +356,7 @@ private:
NotifyWindows notifyWindows;
MediaView *_mediaView;
MediaView *_mediaView = nullptr;
};
class PreLaunchWindow : public TWidget {

View File

@ -34,8 +34,8 @@ IDI_ICON1 ICON "Resources\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,9,40,124
PRODUCTVERSION 0,9,40,124
FILEVERSION 0,9,40,126
PRODUCTVERSION 0,9,40,126
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -51,10 +51,10 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileVersion", "0.9.40.124"
VALUE "FileVersion", "0.9.40.126"
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.9.40.124"
VALUE "ProductVersion", "0.9.40.126"
END
END
BLOCK "VarFileInfo"

View File

@ -3,4 +3,4 @@ AppVersionStrMajor 0.9
AppVersionStrSmall 0.9.40
AppVersionStr 0.9.40
DevChannel 0
BetaVersion 9040124
BetaVersion 9040126