mirror of https://github.com/procxx/kepka.git
merged for 0.9.16
This commit is contained in:
commit
433243fcca
|
@ -61,7 +61,7 @@ In Terminal go to **/home/user/TBuild/Libraries** and run
|
|||
sudo apt-get -y --force-yes install autoconf automake build-essential libass-dev libfreetype6-dev libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texi2html zlib1g-dev
|
||||
sudo apt-get install yasm
|
||||
|
||||
./configure --prefix=/usr/local --disable-programs --disable-pthreads --disable-doc --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=flac --enable-decoder=gif --enable-decoder=h264 --enable-decoder=h264_vdpau --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=mpeg4 --enable-decoder=mpeg4_vdpau --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wavpack --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-encoder=libopus --enable-hwaccel=h264_vaapi --enable-hwaccel=h264_vdpau --enable-hwaccel=mpeg4_vaapi --enable-hwaccel=mpeg4_vdpau --enable-parser=aac --enable-parser=aac_latm --enable-parser=flac --enable-parser=h264 --enable-parser=mpeg4video --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-demuxer=aac --enable-demuxer=flac --enable-demuxer=gif --enable-demuxer=h264 --enable-demuxer=mov --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=wav --enable-muxer=ogg --enable-muxer=opus
|
||||
./configure --prefix=/usr/local --disable-programs --disable-doc --disable-pthreads --disable-mmx --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=flac --enable-decoder=gif --enable-decoder=h264 --enable-decoder=h264_vdpau --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=mpeg4 --enable-decoder=mpeg4_vdpau --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wavpack --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-encoder=libopus --enable-hwaccel=h264_vaapi --enable-hwaccel=h264_vdpau --enable-hwaccel=mpeg4_vaapi --enable-hwaccel=mpeg4_vdpau --enable-parser=aac --enable-parser=aac_latm --enable-parser=flac --enable-parser=h264 --enable-parser=mpeg4video --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-demuxer=aac --enable-demuxer=flac --enable-demuxer=gif --enable-demuxer=h264 --enable-demuxer=mov --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=wav --enable-muxer=ogg --enable-muxer=opus
|
||||
|
||||
make
|
||||
sudo make install
|
||||
|
|
|
@ -1197,6 +1197,18 @@ msgFileRedColor: #e47272;
|
|||
msgFileYellowColor: #efc274;
|
||||
msgFileGreenColor: #61b96e;
|
||||
msgFileBlueColor: #72b1df;
|
||||
msgFileRedDark: #cd5b5e;
|
||||
msgFileYellowDark: #e6a561;
|
||||
msgFileGreenDark: #4da859;
|
||||
msgFileBlueDark: #5c9ece;
|
||||
msgFileRedOver: #c35154;
|
||||
msgFileYellowOver: #dc9c5a;
|
||||
msgFileGreenOver: #44a050;
|
||||
msgFileBlueOver: #5294c4;
|
||||
msgFileRedSelected: #9f6a82;
|
||||
msgFileYellowSelected: #b19d84;
|
||||
msgFileGreenSelected: #46a07e;
|
||||
msgFileBlueSelected: #5099d0;
|
||||
|
||||
msgFileMenuSize: size(36px, 36px);
|
||||
msgFileSize: 44px;
|
||||
|
@ -2161,6 +2173,14 @@ overviewPhotoCheck: sprite(245px, 308px, 32px, 32px);
|
|||
overviewPhotoChecked: sprite(278px, 308px, 32px, 32px);
|
||||
overviewPhotoSelectOverlay: #0a7bb03f;
|
||||
|
||||
overviewFilePadding: margins(0px, 3px, 16px, 3px);
|
||||
overviewFileSize: 70px;
|
||||
overviewFileNameTop: 7px;
|
||||
overviewFileStatusTop: 27px;
|
||||
overviewFileDateTop: 49px;
|
||||
overviewFileChecked: #2fa9e2;
|
||||
overviewFileCheck: #00000066;
|
||||
|
||||
// Mac specific
|
||||
|
||||
macAccessory: size(450, 90);
|
||||
|
@ -2346,11 +2366,12 @@ playlistPadding: 10px;
|
|||
linksSearchMargin: margins(20px, 20px, 20px, 0px);
|
||||
linksMaxWidth: 520px;
|
||||
linksLetterFont: font(24px);
|
||||
linksMargin: 5px;
|
||||
linksMargin: margins(0px, 7px, 0px, 5px);
|
||||
linksTextTop: 6px;
|
||||
linksBorder: 1px;
|
||||
linksBorderFg: #eaeaea;
|
||||
linksDateColor: #000;
|
||||
linksDateMargin: 15px;
|
||||
linksDateColor: #808080;
|
||||
linksDateMargin: margins(0px, 15px, 0px, 2px);
|
||||
|
||||
linksPhotoCheck: sprite(184px, 196px, 16px, 16px);
|
||||
linksPhotoChecked: sprite(168px, 196px, 16px, 16px);
|
||||
|
|
|
@ -708,7 +708,7 @@ void Application::checkMapVersion() {
|
|||
if (cDevVersion() && Local::oldMapVersion() < 9016) {
|
||||
// versionFeatures = QString::fromUtf8("\xe2\x80\x94 Sticker management: manually rearrange your sticker packs, pack order is now synced across all your devices\n\xe2\x80\x94 Click and hold on a sticker to preview it before sending\n\xe2\x80\x94 New context menu for chats in chats list\n\xe2\x80\x94 Support for all existing emoji");// .replace('@', qsl("@") + QChar(0x200D));
|
||||
versionFeatures = lng_new_version_text(lt_gifs_link, qsl("https://telegram.org/blog/gif-revolution"), lt_bots_link, qsl("https://telegram.org/blog/inline-bots")).trimmed();
|
||||
} else if (Local::oldMapVersion() < 9015) {
|
||||
} else if (Local::oldMapVersion() < 9016) {
|
||||
versionFeatures = lng_new_version_text(lt_gifs_link, qsl("https://telegram.org/blog/gif-revolution"), lt_bots_link, qsl("https://telegram.org/blog/inline-bots")).trimmed();
|
||||
} else {
|
||||
versionFeatures = lang(lng_new_version_minor).trimmed();
|
||||
|
|
|
@ -20,10 +20,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
static const int32 AppVersion = 9015;
|
||||
static const wchar_t *AppVersionStr = L"0.9.15";
|
||||
static const int32 AppVersion = 9016;
|
||||
static const wchar_t *AppVersionStr = L"0.9.16";
|
||||
static const bool DevVersion = false;
|
||||
#define BETA_VERSION (9015007ULL) // just comment this line to build public version
|
||||
//#define BETA_VERSION (9015008ULL) // 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";
|
||||
|
|
|
@ -1663,14 +1663,14 @@ void StickerPanInner::refreshStickers() {
|
|||
updateSelected();
|
||||
}
|
||||
|
||||
void StickerPanInner::inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, InlineRow &row, int32 &sumWidth) {
|
||||
bool StickerPanInner::inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, InlineRow &row, int32 &sumWidth) {
|
||||
LayoutInlineItem *layout = 0;
|
||||
if (savedGif) {
|
||||
layout = layoutPrepareSavedGif(savedGif, (_inlineRows.size() * MatrixRowShift) + row.items.size());
|
||||
} else if (result) {
|
||||
layout = layoutPrepareInlineResult(result, (_inlineRows.size() * MatrixRowShift) + row.items.size());
|
||||
}
|
||||
if (!layout) return;
|
||||
if (!layout) return false;
|
||||
|
||||
layout->preload();
|
||||
if (inlineRowFinalize(row, sumWidth, layout->fullLine())) {
|
||||
|
@ -1678,6 +1678,7 @@ void StickerPanInner::inlineRowsAddItem(DocumentData *savedGif, InlineResult *re
|
|||
}
|
||||
row.items.push_back(layout);
|
||||
sumWidth += layout->maxWidth();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StickerPanInner::inlineRowFinalize(InlineRow &row, int32 &sumWidth, bool force) {
|
||||
|
@ -1770,7 +1771,7 @@ LayoutInlineItem *StickerPanInner::layoutPrepareInlineResult(InlineResult *resul
|
|||
layout = new LayoutInlineGif(result, 0, false);
|
||||
} else if (result->type == qstr("photo")) {
|
||||
layout = new LayoutInlinePhoto(result, 0);
|
||||
} else if (result->type == qstr("web_player_video")) {
|
||||
} else if (result->type == qstr("video")) {
|
||||
layout = new LayoutInlineWebVideo(result);
|
||||
} else if (result->type == qstr("article")) {
|
||||
layout = new LayoutInlineArticle(result, _inlineWithThumb);
|
||||
|
@ -1901,14 +1902,14 @@ void StickerPanInner::clearInlineRowsPanel() {
|
|||
clearInlineRows(false);
|
||||
}
|
||||
|
||||
void StickerPanInner::refreshInlineRows(UserData *bot, const InlineResults &results, bool resultsDeleted) {
|
||||
int32 StickerPanInner::refreshInlineRows(UserData *bot, const InlineResults &results, bool resultsDeleted) {
|
||||
_inlineBot = bot;
|
||||
if (results.isEmpty() && (!_inlineBot || _inlineBot->username != cInlineGifBotUsername())) {
|
||||
if (resultsDeleted) {
|
||||
clearInlineRows(true);
|
||||
}
|
||||
emit emptyInlineRows();
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_showingInlineItems) {
|
||||
|
@ -1921,7 +1922,7 @@ void StickerPanInner::refreshInlineRows(UserData *bot, const InlineResults &resu
|
|||
_showingInlineItems = true;
|
||||
_showingSavedGifs = false;
|
||||
|
||||
int32 count = results.size(), from = validateExistingInlineRows(results);
|
||||
int32 count = results.size(), from = validateExistingInlineRows(results), added = 0;
|
||||
|
||||
if (count) {
|
||||
_inlineRows.reserve(count);
|
||||
|
@ -1929,7 +1930,9 @@ void StickerPanInner::refreshInlineRows(UserData *bot, const InlineResults &resu
|
|||
row.items.reserve(SavedGifsMaxPerRow);
|
||||
int32 sumWidth = 0;
|
||||
for (int32 i = from; i < count; ++i) {
|
||||
inlineRowsAddItem(0, results.at(i), row, sumWidth);
|
||||
if (inlineRowsAddItem(0, results.at(i), row, sumWidth)) {
|
||||
++added;
|
||||
}
|
||||
}
|
||||
inlineRowFinalize(row, sumWidth, true);
|
||||
}
|
||||
|
@ -1943,6 +1946,8 @@ void StickerPanInner::refreshInlineRows(UserData *bot, const InlineResults &resu
|
|||
_lastMousePos = QCursor::pos();
|
||||
updateSelected();
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
int32 StickerPanInner::validateExistingInlineRows(const InlineResults &results) {
|
||||
|
@ -3722,7 +3727,10 @@ void EmojiPan::inlineResultsDone(const MTPmessages_BotResults &result) {
|
|||
} else if (adding) {
|
||||
it.value()->nextOffset = QString();
|
||||
}
|
||||
showInlineRows(!adding);
|
||||
|
||||
if (!showInlineRows(!adding)) {
|
||||
it.value()->nextOffset = QString();
|
||||
}
|
||||
onScroll();
|
||||
}
|
||||
|
||||
|
@ -3782,7 +3790,7 @@ void EmojiPan::onEmptyInlineRows() {
|
|||
}
|
||||
}
|
||||
|
||||
bool EmojiPan::refreshInlineRows() {
|
||||
bool EmojiPan::refreshInlineRows(int32 *added) {
|
||||
bool clear = true;
|
||||
InlineCache::const_iterator i = _inlineCache.constFind(_inlineQuery);
|
||||
if (i != _inlineCache.cend()) {
|
||||
|
@ -3790,12 +3798,14 @@ bool EmojiPan::refreshInlineRows() {
|
|||
_inlineNextOffset = i.value()->nextOffset;
|
||||
}
|
||||
if (clear) prepareShowHideCache();
|
||||
s_inner.refreshInlineRows(_inlineBot, clear ? InlineResults() : i.value()->results, false);
|
||||
int32 result = s_inner.refreshInlineRows(_inlineBot, clear ? InlineResults() : i.value()->results, false);
|
||||
if (added) *added = result;
|
||||
return !clear;
|
||||
}
|
||||
|
||||
void EmojiPan::showInlineRows(bool newResults) {
|
||||
bool clear = !refreshInlineRows();
|
||||
int32 EmojiPan::showInlineRows(bool newResults) {
|
||||
int32 added = 0;
|
||||
bool clear = !refreshInlineRows(&added);
|
||||
if (newResults) s_scroll.scrollToY(0);
|
||||
|
||||
e_switch.updateText(clear ? QString() : _inlineBot->username);
|
||||
|
@ -3819,6 +3829,8 @@ void EmojiPan::showInlineRows(bool newResults) {
|
|||
onSwitch();
|
||||
}
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
void EmojiPan::recountContentMaxHeight() {
|
||||
|
|
|
@ -344,7 +344,7 @@ public:
|
|||
void refreshStickers();
|
||||
void refreshRecentStickers(bool resize = true);
|
||||
void refreshSavedGifs();
|
||||
void refreshInlineRows(UserData *bot, const InlineResults &results, bool resultsDeleted);
|
||||
int32 refreshInlineRows(UserData *bot, const InlineResults &results, bool resultsDeleted);
|
||||
void refreshRecent();
|
||||
void inlineBotChanged();
|
||||
void hideInlineRowsPanel();
|
||||
|
@ -458,7 +458,7 @@ private:
|
|||
InlineLayouts _inlineLayouts;
|
||||
LayoutInlineItem *layoutPrepareInlineResult(InlineResult *result, int32 position);
|
||||
|
||||
void inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, InlineRow &row, int32 &sumWidth);
|
||||
bool inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, InlineRow &row, int32 &sumWidth);
|
||||
bool inlineRowFinalize(InlineRow &row, int32 &sumWidth, bool force = false);
|
||||
|
||||
InlineRow &layoutInlineRow(InlineRow &row, int32 sumWidth = 0);
|
||||
|
@ -712,10 +712,10 @@ private:
|
|||
QTimer _inlineRequestTimer;
|
||||
|
||||
void inlineBotChanged();
|
||||
void showInlineRows(bool newResults);
|
||||
int32 showInlineRows(bool newResults);
|
||||
bool hideOnNoInlineResults();
|
||||
void recountContentMaxHeight();
|
||||
bool refreshInlineRows();
|
||||
bool refreshInlineRows(int32 *added = 0);
|
||||
UserData *_inlineBot;
|
||||
QString _inlineQuery, _inlineNextQuery, _inlineNextOffset;
|
||||
mtpRequestId _inlineRequestId;
|
||||
|
|
|
@ -225,7 +225,7 @@ ClipReader::ClipReader(const FileLocation &location, const QByteArray &data, Cal
|
|||
, _state(ClipReading)
|
||||
, _width(0)
|
||||
, _height(0)
|
||||
, _step(FirstFrameNotReadStep)
|
||||
, _step(WaitingForDimensionsStep)
|
||||
, _paused(0)
|
||||
, _autoplay(false)
|
||||
, _private(0) {
|
||||
|
@ -248,47 +248,69 @@ ClipReader::ClipReader(const FileLocation &location, const QByteArray &data, Cal
|
|||
_clipManagers.at(_threadIndex)->append(this, location, data);
|
||||
}
|
||||
|
||||
ClipReader::Frame *ClipReader::frameToShow() const { // 0 means not ready
|
||||
int32 step = _step.loadAcquire();
|
||||
if (step == FirstFrameNotReadStep) {
|
||||
return 0;
|
||||
} else if (step == WaitingForRequestStep) {
|
||||
return _frames;
|
||||
}
|
||||
return _frames + (((step + 1) / 2) % 3);
|
||||
}
|
||||
|
||||
ClipReader::Frame *ClipReader::frameToWrite(int32 *index) const { // 0 means not ready
|
||||
int32 step = _step.loadAcquire(), i = 0;
|
||||
if (step == WaitingForRequestStep) {
|
||||
ClipReader::Frame *ClipReader::frameToShow(int32 *index) const { // 0 means not ready
|
||||
int32 step = _step.loadAcquire(), i;
|
||||
if (step == WaitingForDimensionsStep) {
|
||||
if (index) *index = 0;
|
||||
return 0;
|
||||
} else if (step != FirstFrameNotReadStep) {
|
||||
i = (((step + 3) / 2) % 3);
|
||||
} else if (step == WaitingForRequestStep) {
|
||||
i = 0;
|
||||
} else if (step == WaitingForFirstFrameStep) {
|
||||
i = 0;
|
||||
} else {
|
||||
i = (step / 2) % 3;
|
||||
}
|
||||
if (index) *index = i;
|
||||
return _frames + i;
|
||||
}
|
||||
|
||||
ClipReader::Frame *ClipReader::frameToWriteNext(bool checkNotWriting) const {
|
||||
int32 step = _step.loadAcquire();
|
||||
if (step == FirstFrameNotReadStep || step == WaitingForRequestStep || (checkNotWriting && !(step % 2))) {
|
||||
ClipReader::Frame *ClipReader::frameToWrite(int32 *index) const { // 0 means not ready
|
||||
int32 step = _step.loadAcquire(), i;
|
||||
if (step == WaitingForDimensionsStep) {
|
||||
i = 0;
|
||||
} else if (step == WaitingForRequestStep) {
|
||||
if (index) *index = 0;
|
||||
return 0;
|
||||
} else if (step == WaitingForFirstFrameStep) {
|
||||
i = 0;
|
||||
} else {
|
||||
i = ((step + 2) / 2) % 3;
|
||||
}
|
||||
if (index) *index = i;
|
||||
return _frames + i;
|
||||
}
|
||||
|
||||
ClipReader::Frame *ClipReader::frameToWriteNext(bool checkNotWriting, int32 *index) const {
|
||||
int32 step = _step.loadAcquire(), i;
|
||||
if (step == WaitingForDimensionsStep || step == WaitingForRequestStep || (checkNotWriting && (step % 2))) {
|
||||
if (index) *index = 0;
|
||||
return 0;
|
||||
}
|
||||
return _frames + (((step + 5) / 2) % 3);
|
||||
i = ((step + 4) / 2) % 3;
|
||||
if (index) *index = i;
|
||||
return _frames + i;
|
||||
}
|
||||
|
||||
void ClipReader::moveToNextShow() const {
|
||||
int32 step = _step.loadAcquire();
|
||||
if (step % 2) {
|
||||
_step.storeRelease((step + 1) % 6);
|
||||
if (step == WaitingForDimensionsStep) {
|
||||
} else if (step == WaitingForRequestStep) {
|
||||
_step.storeRelease(WaitingForFirstFrameStep);
|
||||
} else if (step == WaitingForFirstFrameStep) {
|
||||
} else if (!(step % 2)) {
|
||||
_step.storeRelease(step + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ClipReader::moveToNextWrite() const {
|
||||
int32 step = _step.loadAcquire();
|
||||
if (!(step % 2)) {
|
||||
_step.storeRelease(step + 1);
|
||||
if (step == WaitingForDimensionsStep) {
|
||||
_step.storeRelease(WaitingForRequestStep);
|
||||
} else if (step == WaitingForRequestStep) {
|
||||
} else if (step == WaitingForFirstFrameStep) {
|
||||
_step.storeRelease(0);
|
||||
} else if (step % 2) {
|
||||
_step.storeRelease((step + 1) % 6);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,7 +335,7 @@ void ClipReader::start(int32 framew, int32 frameh, int32 outerw, int32 outerh, b
|
|||
request.outerh = outerh * factor;
|
||||
request.rounded = rounded;
|
||||
_frames[0].request = _frames[1].request = _frames[2].request = request;
|
||||
_step.storeRelease(0); // start working
|
||||
moveToNextShow();
|
||||
_clipManagers.at(_threadIndex)->start(this);
|
||||
}
|
||||
}
|
||||
|
@ -322,9 +344,8 @@ QPixmap ClipReader::current(int32 framew, int32 frameh, int32 outerw, int32 oute
|
|||
Frame *frame = frameToShow();
|
||||
t_assert(frame != 0);
|
||||
|
||||
frame->displayed = true;
|
||||
if (ms) {
|
||||
frame->when = ms;
|
||||
frame->displayed.storeRelease(1);
|
||||
if (_paused.loadAcquire()) {
|
||||
_paused.storeRelease(0);
|
||||
if (_clipManagers.size() <= _threadIndex) error();
|
||||
|
@ -332,6 +353,8 @@ QPixmap ClipReader::current(int32 framew, int32 frameh, int32 outerw, int32 oute
|
|||
_clipManagers.at(_threadIndex)->update(this);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
frame->displayed.storeRelease(-1); // displayed, but should be paused
|
||||
}
|
||||
|
||||
int32 factor(cIntRetinaFactor());
|
||||
|
@ -412,7 +435,8 @@ public:
|
|||
, _device(0)
|
||||
, _dataSize(0) {
|
||||
}
|
||||
virtual bool readNextFrame(QImage &to, bool &hasAlpha, const QSize &size) = 0;
|
||||
virtual bool readNextFrame() = 0;
|
||||
virtual bool renderFrame(QImage &to, bool &hasAlpha, const QSize &size) = 0;
|
||||
virtual int32 nextFrameDelay() = 0;
|
||||
virtual bool start(bool onlyGifv) = 0;
|
||||
virtual ~ClipReaderImplementation() {
|
||||
|
@ -459,30 +483,35 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
QImage frame; // QGifHandler always reads first to internal QImage and returns it
|
||||
if (!_reader->read(&frame)) {
|
||||
_frame = QImage(); // QGifHandler always reads first to internal QImage and returns it
|
||||
if (!_reader->read(&_frame) || _frame.isNull()) {
|
||||
return false;
|
||||
}
|
||||
--_framesLeft;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (size.isEmpty() || size == frame.size()) {
|
||||
int32 w = frame.width(), h = frame.height();
|
||||
if (to.width() == w && to.height() == h && to.format() == frame.format()) {
|
||||
if (to.byteCount() != frame.byteCount()) {
|
||||
int bpl = qMin(to.bytesPerLine(), frame.bytesPerLine());
|
||||
bool renderFrame(QImage &to, bool &hasAlpha, const QSize &size) {
|
||||
t_assert(!_frame.isNull());
|
||||
if (size.isEmpty() || size == _frame.size()) {
|
||||
int32 w = _frame.width(), h = _frame.height();
|
||||
if (to.width() == w && to.height() == h && to.format() == _frame.format()) {
|
||||
if (to.byteCount() != _frame.byteCount()) {
|
||||
int bpl = qMin(to.bytesPerLine(), _frame.bytesPerLine());
|
||||
for (int i = 0; i < h; ++i) {
|
||||
memcpy(to.scanLine(i), frame.constScanLine(i), bpl);
|
||||
memcpy(to.scanLine(i), _frame.constScanLine(i), bpl);
|
||||
}
|
||||
} else {
|
||||
memcpy(to.bits(), frame.constBits(), frame.byteCount());
|
||||
memcpy(to.bits(), _frame.constBits(), _frame.byteCount());
|
||||
}
|
||||
} else {
|
||||
to = frame.copy();
|
||||
to = _frame.copy();
|
||||
}
|
||||
} else {
|
||||
to = frame.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
to = _frame.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
hasAlpha = frame.hasAlphaChannel();
|
||||
hasAlpha = _frame.hasAlphaChannel();
|
||||
_frame = QImage();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -502,6 +531,7 @@ public:
|
|||
private:
|
||||
QImageReader *_reader;
|
||||
int32 _framesLeft, _frameDelay;
|
||||
QImage _frame;
|
||||
|
||||
bool jumpToStart() {
|
||||
if (_reader && _reader->jumpToImage(0)) {
|
||||
|
@ -540,6 +570,7 @@ public:
|
|||
, _frame(0)
|
||||
, _opened(false)
|
||||
, _hadFrame(false)
|
||||
, _frameRead(false)
|
||||
, _packetSize(0)
|
||||
, _packetData(0)
|
||||
, _packetWas(false)
|
||||
|
@ -555,7 +586,7 @@ public:
|
|||
_avpkt.size = 0;
|
||||
}
|
||||
|
||||
bool readNextFrame(QImage &to, bool &hasAlpha, const QSize &size) {
|
||||
bool readNextFrame() {
|
||||
int res;
|
||||
while (true) {
|
||||
if (_avpkt.size > 0) { // previous packet not finished
|
||||
|
@ -607,56 +638,7 @@ public:
|
|||
}
|
||||
|
||||
if (got_frame) {
|
||||
_hadFrame = true;
|
||||
|
||||
if (!_width || !_height) {
|
||||
_width = _frame->width;
|
||||
_height = _frame->height;
|
||||
if (!_width || !_height) {
|
||||
LOG(("Gif Error: Bad frame size %1").arg(logData()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QSize toSize(size.isEmpty() ? QSize(_width, _height) : size);
|
||||
if (to.isNull() || to.size() != toSize) {
|
||||
to = QImage(toSize, QImage::Format_ARGB32);
|
||||
}
|
||||
hasAlpha = (_frame->format == AV_PIX_FMT_BGRA || (_frame->format == -1 && _codecContext->pix_fmt == AV_PIX_FMT_BGRA));
|
||||
if (_frame->width == toSize.width() && _frame->height == toSize.height() && hasAlpha) {
|
||||
int32 sbpl = _frame->linesize[0], dbpl = to.bytesPerLine(), bpl = qMin(sbpl, dbpl);
|
||||
uchar *s = _frame->data[0], *d = to.bits();
|
||||
for (int32 i = 0, l = _frame->height; i < l; ++i) {
|
||||
memcpy(d + i * dbpl, s + i * sbpl, bpl);
|
||||
}
|
||||
} else {
|
||||
if ((_swsSize != toSize) || (_frame->format != -1 && _frame->format != _codecContext->pix_fmt) || !_swsContext) {
|
||||
_swsSize = toSize;
|
||||
_swsContext = sws_getCachedContext(_swsContext, _frame->width, _frame->height, AVPixelFormat(_frame->format), toSize.width(), toSize.height(), AV_PIX_FMT_BGRA, 0, 0, 0, 0);
|
||||
}
|
||||
uint8_t * toData[1] = { to.bits() };
|
||||
int toLinesize[1] = { to.bytesPerLine() };
|
||||
if ((res = sws_scale(_swsContext, _frame->data, _frame->linesize, 0, _frame->height, toData, toLinesize)) != _swsSize.height()) {
|
||||
LOG(("Gif Error: Unable to sws_scale to good size %1, height %2, should be %3").arg(logData()).arg(res).arg(_swsSize.height()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int64 duration = av_frame_get_pkt_duration(_frame);
|
||||
int64 framePts = (_frame->pkt_pts == AV_NOPTS_VALUE) ? _frame->pkt_dts : _frame->pkt_pts;
|
||||
int64 frameMs = (framePts * 1000LL * _fmtContext->streams[_streamId]->time_base.num) / _fmtContext->streams[_streamId]->time_base.den;
|
||||
_currentFrameDelay = _nextFrameDelay;
|
||||
if (_frameMs + _currentFrameDelay < frameMs) {
|
||||
_currentFrameDelay = int32(frameMs - _frameMs);
|
||||
}
|
||||
if (duration == AV_NOPTS_VALUE) {
|
||||
_nextFrameDelay = 0;
|
||||
} else {
|
||||
_nextFrameDelay = (duration * 1000LL * _fmtContext->streams[_streamId]->time_base.num) / _fmtContext->streams[_streamId]->time_base.den;
|
||||
}
|
||||
_frameMs = frameMs;
|
||||
|
||||
av_frame_unref(_frame);
|
||||
_hadFrame = _frameRead = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -681,6 +663,61 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool renderFrame(QImage &to, bool &hasAlpha, const QSize &size) {
|
||||
t_assert(_frameRead);
|
||||
_frameRead = false;
|
||||
|
||||
if (!_width || !_height) {
|
||||
_width = _frame->width;
|
||||
_height = _frame->height;
|
||||
if (!_width || !_height) {
|
||||
LOG(("Gif Error: Bad frame size %1").arg(logData()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QSize toSize(size.isEmpty() ? QSize(_width, _height) : size);
|
||||
if (to.isNull() || to.size() != toSize) {
|
||||
to = QImage(toSize, QImage::Format_ARGB32);
|
||||
}
|
||||
hasAlpha = (_frame->format == AV_PIX_FMT_BGRA || (_frame->format == -1 && _codecContext->pix_fmt == AV_PIX_FMT_BGRA));
|
||||
if (_frame->width == toSize.width() && _frame->height == toSize.height() && hasAlpha) {
|
||||
int32 sbpl = _frame->linesize[0], dbpl = to.bytesPerLine(), bpl = qMin(sbpl, dbpl);
|
||||
uchar *s = _frame->data[0], *d = to.bits();
|
||||
for (int32 i = 0, l = _frame->height; i < l; ++i) {
|
||||
memcpy(d + i * dbpl, s + i * sbpl, bpl);
|
||||
}
|
||||
} else {
|
||||
if ((_swsSize != toSize) || (_frame->format != -1 && _frame->format != _codecContext->pix_fmt) || !_swsContext) {
|
||||
_swsSize = toSize;
|
||||
_swsContext = sws_getCachedContext(_swsContext, _frame->width, _frame->height, AVPixelFormat(_frame->format), toSize.width(), toSize.height(), AV_PIX_FMT_BGRA, 0, 0, 0, 0);
|
||||
}
|
||||
uint8_t * toData[1] = { to.bits() };
|
||||
int toLinesize[1] = { to.bytesPerLine() }, res;
|
||||
if ((res = sws_scale(_swsContext, _frame->data, _frame->linesize, 0, _frame->height, toData, toLinesize)) != _swsSize.height()) {
|
||||
LOG(("Gif Error: Unable to sws_scale to good size %1, height %2, should be %3").arg(logData()).arg(res).arg(_swsSize.height()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int64 duration = av_frame_get_pkt_duration(_frame);
|
||||
int64 framePts = (_frame->pkt_pts == AV_NOPTS_VALUE) ? _frame->pkt_dts : _frame->pkt_pts;
|
||||
int64 frameMs = (framePts * 1000LL * _fmtContext->streams[_streamId]->time_base.num) / _fmtContext->streams[_streamId]->time_base.den;
|
||||
_currentFrameDelay = _nextFrameDelay;
|
||||
if (_frameMs + _currentFrameDelay < frameMs) {
|
||||
_currentFrameDelay = int32(frameMs - _frameMs);
|
||||
}
|
||||
if (duration == AV_NOPTS_VALUE) {
|
||||
_nextFrameDelay = 0;
|
||||
} else {
|
||||
_nextFrameDelay = (duration * 1000LL * _fmtContext->streams[_streamId]->time_base.num) / _fmtContext->streams[_streamId]->time_base.den;
|
||||
}
|
||||
_frameMs = frameMs;
|
||||
|
||||
av_frame_unref(_frame);
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 nextFrameDelay() {
|
||||
return _currentFrameDelay;
|
||||
}
|
||||
|
@ -776,7 +813,7 @@ private:
|
|||
AVCodecContext *_codecContext;
|
||||
int32 _streamId;
|
||||
AVFrame *_frame;
|
||||
bool _opened, _hadFrame;
|
||||
bool _opened, _hadFrame, _frameRead;
|
||||
|
||||
AVPacket _avpkt;
|
||||
int _packetSize;
|
||||
|
@ -835,9 +872,7 @@ public:
|
|||
, _frame(0)
|
||||
, _width(0)
|
||||
, _height(0)
|
||||
, _previousMs(0)
|
||||
, _currentMs(0)
|
||||
, _nextUpdateMs(0)
|
||||
, _nextFrameWhen(0)
|
||||
, _paused(false) {
|
||||
if (_data.isEmpty() && !_location->accessEnable()) {
|
||||
error();
|
||||
|
@ -851,7 +886,10 @@ public:
|
|||
return error();
|
||||
}
|
||||
if (frame() && frame()->original.isNull()) {
|
||||
if (!_implementation->readNextFrame(frame()->original, frame()->alpha, QSize())) {
|
||||
if (!_implementation->readNextFrame()) {
|
||||
return error();
|
||||
}
|
||||
if (!_implementation->renderFrame(frame()->original, frame()->alpha, QSize())) {
|
||||
return error();
|
||||
}
|
||||
_width = frame()->original.width();
|
||||
|
@ -868,23 +906,22 @@ public:
|
|||
return start(ms);
|
||||
}
|
||||
|
||||
if (!_paused && ms >= _nextUpdateMs) {
|
||||
if (!_paused && ms >= _nextFrameWhen) {
|
||||
return ClipProcessRepaint;
|
||||
}
|
||||
return ClipProcessWait;
|
||||
}
|
||||
|
||||
ClipProcessResult finishProcess(uint64 ms) {
|
||||
_previousMs = _currentMs;
|
||||
if (!prepareNextFrame()) {
|
||||
if (!readNextFrame()) {
|
||||
return error();
|
||||
}
|
||||
if (ms >= _nextUpdateMs) {
|
||||
if (!prepareNextFrame()) {
|
||||
return error();
|
||||
}
|
||||
if (ms >= _nextFrameWhen && !readNextFrame(true)) {
|
||||
return error();
|
||||
}
|
||||
if (!renderFrame()) {
|
||||
return error();
|
||||
}
|
||||
_currentMs = qMax(ms, _nextUpdateMs);
|
||||
return ClipProcessCopyFrame;
|
||||
}
|
||||
|
||||
|
@ -893,15 +930,26 @@ public:
|
|||
return qMax(delay, 5);
|
||||
}
|
||||
|
||||
bool prepareNextFrame() {
|
||||
t_assert(frame() != 0 && _request.valid());
|
||||
if (!_implementation->readNextFrame(frame()->original, frame()->alpha, QSize(_request.framew, _request.frameh))) {
|
||||
bool readNextFrame(bool keepup = false) {
|
||||
if (!_implementation->readNextFrame()) {
|
||||
return false;
|
||||
}
|
||||
_nextFrameWhen += nextFrameDelay();
|
||||
if (keepup) {
|
||||
_nextFrameWhen = qMax(_nextFrameWhen, getms());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool renderFrame() {
|
||||
t_assert(frame() != 0 && _request.valid());
|
||||
if (!_implementation->renderFrame(frame()->original, frame()->alpha, QSize(_request.framew, _request.frameh))) {
|
||||
return false;
|
||||
}
|
||||
_nextUpdateMs = _currentMs + nextFrameDelay();
|
||||
frame()->original.setDevicePixelRatio(_request.factor);
|
||||
frame()->pix = QPixmap();
|
||||
frame()->pix = _prepareFrame(_request, frame()->original, frame()->alpha, frame()->cache);
|
||||
frame()->when = _nextFrameWhen;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -962,11 +1010,12 @@ private:
|
|||
|
||||
ClipFrameRequest _request;
|
||||
struct Frame {
|
||||
Frame() : alpha(true) {
|
||||
Frame() : alpha(true), when(0) {
|
||||
}
|
||||
QPixmap pix;
|
||||
QImage original, cache;
|
||||
bool alpha;
|
||||
uint64 when;
|
||||
};
|
||||
Frame _frames[3];
|
||||
int32 _frame;
|
||||
|
@ -976,7 +1025,7 @@ private:
|
|||
|
||||
int32 _width, _height;
|
||||
|
||||
uint64 _previousMs, _currentMs, _nextUpdateMs;
|
||||
uint64 _nextFrameWhen;
|
||||
|
||||
bool _paused;
|
||||
|
||||
|
@ -1070,13 +1119,16 @@ bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcess
|
|||
if (result == ClipProcessStarted) {
|
||||
_loadLevel.fetchAndAddRelaxed(reader->_width * reader->_height - AverageGifSize);
|
||||
}
|
||||
if (!reader->_paused && (result == ClipProcessRepaint || result == ClipProcessWait)) {
|
||||
ClipReader::Frame *other = it.key()->frameToWriteNext(false);
|
||||
t_assert(other != 0);
|
||||
if (other->when && other->when + WaitBeforeGifPause < qMax(reader->_previousMs, ms)) {
|
||||
reader->_paused = true;
|
||||
it.key()->_paused.storeRelease(1);
|
||||
result = ClipProcessPaused;
|
||||
if (!reader->_paused && result == ClipProcessRepaint) {
|
||||
int32 ishowing, iprevious;
|
||||
ClipReader::Frame *showing = it.key()->frameToShow(&ishowing), *previous = it.key()->frameToWriteNext(false, &iprevious);
|
||||
t_assert(previous != 0 && showing != 0 && ishowing >= 0 && iprevious >= 0);
|
||||
if (reader->_frames[ishowing].when > 0 && showing->displayed.loadAcquire() <= 0) { // current frame was not shown
|
||||
if (reader->_frames[ishowing].when + WaitBeforeGifPause < ms || (reader->_frames[iprevious].when && previous->displayed.loadAcquire() <= 0)) {
|
||||
reader->_paused = true;
|
||||
it.key()->_paused.storeRelease(1);
|
||||
result = ClipProcessPaused;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result == ClipProcessStarted || result == ClipProcessCopyFrame) {
|
||||
|
@ -1085,14 +1137,17 @@ bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcess
|
|||
frame->clear();
|
||||
frame->pix = reader->frame()->pix;
|
||||
frame->original = reader->frame()->original;
|
||||
frame->displayed = false;
|
||||
it.key()->moveToNextWrite();
|
||||
frame->displayed.storeRelease(0);
|
||||
if (result == ClipProcessStarted) {
|
||||
reader->_nextFrameWhen = ms;
|
||||
it.key()->moveToNextWrite();
|
||||
emit callback(it.key(), it.key()->threadIndex(), ClipReaderReinit);
|
||||
}
|
||||
} else if (result == ClipProcessPaused) {
|
||||
it.key()->moveToNextWrite();
|
||||
emit callback(it.key(), it.key()->threadIndex(), ClipReaderReinit);
|
||||
} else if (result == ClipProcessRepaint) {
|
||||
it.key()->moveToNextWrite();
|
||||
emit callback(it.key(), it.key()->threadIndex(), ClipReaderRepaint);
|
||||
}
|
||||
return true;
|
||||
|
@ -1174,7 +1229,7 @@ void ClipReadManager::process() {
|
|||
return;
|
||||
}
|
||||
ms = getms();
|
||||
i.value() = reader->_nextUpdateMs ? reader->_nextUpdateMs : (ms + 86400 * 1000ULL);
|
||||
i.value() = reader->_nextFrameWhen ? reader->_nextFrameWhen : (ms + 86400 * 1000ULL);
|
||||
}
|
||||
if (!reader->_paused && i.value() < minms) {
|
||||
minms = i.value();
|
||||
|
@ -1224,7 +1279,7 @@ MTPDocumentAttribute clipReadAnimatedAttributes(const QString &fname, const QByt
|
|||
FFMpegReaderImplementation *reader = new FFMpegReaderImplementation(&localloc, &localdata);
|
||||
if (reader->start(true)) {
|
||||
bool hasAlpha = false;
|
||||
if (reader->readNextFrame(cover, hasAlpha, QSize())) {
|
||||
if (reader->readNextFrame() && reader->renderFrame(cover, hasAlpha, QSize())) {
|
||||
if (cover.width() > 0 && cover.height() > 0 && cover.width() < cover.height() * 10 && cover.height() < cover.width() * 10) {
|
||||
if (hasAlpha) {
|
||||
QImage cacheForResize;
|
||||
|
|
|
@ -497,8 +497,9 @@ enum ClipReaderNotification {
|
|||
};
|
||||
|
||||
enum ClipReaderSteps {
|
||||
FirstFrameNotReadStep = -2,
|
||||
WaitingForRequestStep = -1,
|
||||
WaitingForDimensionsStep = -3, // before ClipReaderPrivate read the first image and got the original frame size
|
||||
WaitingForRequestStep = -2, // before ClipReader got the original frame size and prepared the frame request
|
||||
WaitingForFirstFrameStep = -1, // before ClipReaderPrivate got the frame request and started waiting for the 1-2 delay
|
||||
};
|
||||
|
||||
class ClipReaderPrivate;
|
||||
|
@ -528,7 +529,7 @@ public:
|
|||
}
|
||||
bool currentDisplayed() const {
|
||||
Frame *frame = frameToShow();
|
||||
return frame ? frame->displayed : true;
|
||||
return frame ? (frame->displayed.loadAcquire() != 0) : true;
|
||||
}
|
||||
bool paused() const {
|
||||
return _paused.loadAcquire();
|
||||
|
@ -542,7 +543,8 @@ public:
|
|||
|
||||
ClipState state() const;
|
||||
bool started() const {
|
||||
return _step.loadAcquire() >= 0;
|
||||
int32 step = _step.loadAcquire();
|
||||
return (step == WaitingForFirstFrameStep) || (step >= 0);
|
||||
}
|
||||
bool ready() const;
|
||||
|
||||
|
@ -561,7 +563,7 @@ private:
|
|||
|
||||
mutable QAtomicInt _step; // -2, -1 - init, 0-5 - work, show ((state + 1) / 2) % 3 state, write ((state + 3) / 2) % 3
|
||||
struct Frame {
|
||||
Frame() : displayed(false), when(0) {
|
||||
Frame() : displayed(false) {
|
||||
}
|
||||
void clear() {
|
||||
pix = QPixmap();
|
||||
|
@ -570,13 +572,12 @@ private:
|
|||
QPixmap pix;
|
||||
QImage original;
|
||||
ClipFrameRequest request;
|
||||
bool displayed;
|
||||
uint64 when;
|
||||
QAtomicInt displayed;
|
||||
};
|
||||
mutable Frame _frames[3];
|
||||
Frame *frameToShow() const; // 0 means not ready
|
||||
Frame *frameToShow(int32 *index = 0) const; // 0 means not ready
|
||||
Frame *frameToWrite(int32 *index = 0) const; // 0 means not ready
|
||||
Frame *frameToWriteNext(bool check) const;
|
||||
Frame *frameToWriteNext(bool check, int32 *index = 0) const;
|
||||
void moveToNextShow() const;
|
||||
void moveToNextWrite() const;
|
||||
|
||||
|
|
|
@ -1392,7 +1392,9 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo
|
|||
case mtpc_messageMediaUnsupported:
|
||||
default: badMedia = 1; break;
|
||||
}
|
||||
if (badMedia) {
|
||||
if (false && badMedia == 1) {
|
||||
// QString text(lng_message_unsupported(lt_link, qsl("https://desktop.telegram.org")));
|
||||
} else if (badMedia) {
|
||||
result = new HistoryServiceMsg(this, block, m.vid.v, date(m.vdate), lang((badMedia == 2) ? lng_message_empty : lng_media_unsupported), m.vflags.v, 0, m.has_from_id() ? m.vfrom_id.v : 0);
|
||||
} else {
|
||||
if ((m.has_fwd_date() && m.vfwd_date.v > 0) || (m.has_fwd_from_id() && peerFromMTP(m.vfwd_from_id) != 0)) {
|
||||
|
@ -3352,11 +3354,16 @@ void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
|
|||
p.setOpacity(radialOpacity);
|
||||
style::sprite icon;
|
||||
if (radial || _data->loading()) {
|
||||
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
|
||||
DelayedStorageImage *delayed = _data->full->toDelayedStorageImage();
|
||||
if (!delayed || !delayed->location().isNull()) {
|
||||
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
|
||||
}
|
||||
} else {
|
||||
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
|
||||
}
|
||||
p.drawSpriteCenter(inner, icon);
|
||||
if (!icon.isEmpty()) {
|
||||
p.drawSpriteCenter(inner, icon);
|
||||
}
|
||||
if (radial) {
|
||||
p.setOpacity(1);
|
||||
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
||||
|
@ -3401,8 +3408,15 @@ void HistoryPhoto::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x
|
|||
if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) {
|
||||
if (_data->uploading()) {
|
||||
lnk = _cancell;
|
||||
} else if (_data->loaded()) {
|
||||
lnk = _openl;
|
||||
} else if (_data->loading()) {
|
||||
DelayedStorageImage *delayed = _data->full->toDelayedStorageImage();
|
||||
if (!delayed || !delayed->location().isNull()) {
|
||||
lnk = _cancell;
|
||||
}
|
||||
} else {
|
||||
lnk = _data->loaded() ? _openl : (_data->loading() ? _cancell : _savel);
|
||||
lnk = _savel;
|
||||
}
|
||||
if (_caption.isEmpty() && parent->getMedia() == this) {
|
||||
int32 fullRight = skipx + width, fullBottom = skipy + height;
|
||||
|
@ -4561,11 +4575,15 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
|
|||
if (_data->loaded() && !radial) {
|
||||
icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
|
||||
} else if (radial || _data->loading()) {
|
||||
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
|
||||
if (parent->id > 0) {
|
||||
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
|
||||
}
|
||||
} else {
|
||||
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
|
||||
}
|
||||
p.drawSpriteCenter(inner, icon);
|
||||
if (!icon.isEmpty()) {
|
||||
p.drawSpriteCenter(inner, icon);
|
||||
}
|
||||
if (radial) {
|
||||
p.setOpacity(1);
|
||||
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
||||
|
@ -4762,6 +4780,16 @@ void HistorySticker::initDimensions(const HistoryItem *parent) {
|
|||
_height = _minh;
|
||||
}
|
||||
|
||||
int32 HistorySticker::resize(int32 width, const HistoryItem *parent) { // return new height
|
||||
_width = qMin(width, _maxw);
|
||||
if (const HistoryReply *reply = toHistoryReply(parent)) {
|
||||
int32 usew = _maxw - st::msgReplyPadding.left() - reply->replyToWidth();
|
||||
int32 rw = _width - usew - st::msgReplyPadding.left() - st::msgReplyPadding.left() - st::msgReplyPadding.right();
|
||||
reply->resizeVia(rw);
|
||||
}
|
||||
return _height;
|
||||
}
|
||||
|
||||
void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
|
||||
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||
|
||||
|
@ -5958,7 +5986,7 @@ void ViaInlineBotLink::onClick(Qt::MouseButton button) const {
|
|||
HistoryMessageVia::HistoryMessageVia(int32 userId)
|
||||
: bot(App::userLoaded(peerFromUser(userId)))
|
||||
, width(0)
|
||||
, fullWidth(st::msgServiceNameFont->width(qsl("via @") + bot->username))
|
||||
, maxWidth(st::msgServiceNameFont->width(qsl("via @") + bot->username))
|
||||
, lnk(new ViaInlineBotLink(bot)) {
|
||||
}
|
||||
|
||||
|
@ -5967,13 +5995,21 @@ bool HistoryMessageVia::isNull() const {
|
|||
}
|
||||
|
||||
void HistoryMessageVia::resize(int32 availw) {
|
||||
if (width < fullWidth && availw > width) {
|
||||
if (availw < fullWidth) {
|
||||
if (width < maxWidth && availw > width) {
|
||||
if (availw < maxWidth) {
|
||||
text = st::msgServiceNameFont->elided(qsl("via @") + bot->username, availw);
|
||||
width = st::msgServiceNameFont->width(text);
|
||||
} else {
|
||||
text = qsl("via @") + bot->username;
|
||||
width = fullWidth;
|
||||
width = maxWidth;
|
||||
}
|
||||
} else if (availw < width) {
|
||||
if (availw > 0) {
|
||||
text = st::msgServiceNameFont->elided(qsl("via @") + bot->username, availw);
|
||||
width = st::msgServiceNameFont->width(text);
|
||||
} else {
|
||||
text = QString();
|
||||
width = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6165,9 +6201,9 @@ void HistoryMessage::initDimensions() {
|
|||
if (maxw > _maxw) _maxw = maxw;
|
||||
_minh += _media->minHeight();
|
||||
}
|
||||
if (via()) {
|
||||
if (st::msgPadding.left() + via()->fullWidth + st::msgPadding.right() > _maxw) {
|
||||
_maxw = st::msgPadding.left() + via()->fullWidth + st::msgPadding.right() > _maxw;
|
||||
if (!_media && !displayFromName() && via() && !toHistoryForwarded()) {
|
||||
if (st::msgPadding.left() + via()->maxWidth + st::msgPadding.right() > _maxw) {
|
||||
_maxw = st::msgPadding.left() + via()->maxWidth + st::msgPadding.right();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -6200,8 +6236,11 @@ void HistoryMessage::countPositionAndSize(int32 &left, int32 &width) const {
|
|||
|
||||
void HistoryMessage::fromNameUpdated() const {
|
||||
if (!_media && displayFromName()) {
|
||||
int32 _namew = st::msgPadding.left() + _from->nameText.maxWidth() + st::msgPadding.right();
|
||||
if (_namew > _maxw) _maxw = _namew;
|
||||
int32 namew = st::msgPadding.left() + _from->nameText.maxWidth() + st::msgPadding.right();
|
||||
if (via() && !toHistoryForwarded()) {
|
||||
namew += st::msgServiceFont->spacew + via()->maxWidth;
|
||||
}
|
||||
if (namew > _maxw) _maxw = namew;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6437,7 +6476,7 @@ void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 m
|
|||
}
|
||||
|
||||
if (_from->nameVersion > _fromVersion) {
|
||||
fromNameUpdated();
|
||||
// fromNameUpdated();
|
||||
_fromVersion = _from->nameVersion;
|
||||
}
|
||||
|
||||
|
@ -6464,6 +6503,10 @@ void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 m
|
|||
p.setPen(_from->color);
|
||||
}
|
||||
_from->nameText.drawElided(p, r.left() + st::msgPadding.left(), r.top() + st::msgPadding.top(), width - st::msgPadding.left() - st::msgPadding.right());
|
||||
if (via() && !toHistoryForwarded() && width > st::msgPadding.left() + st::msgPadding.right() + _from->nameText.maxWidth() + st::msgServiceFont->spacew) {
|
||||
p.setPen(selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg));
|
||||
p.drawText(r.left() + st::msgPadding.left() + _from->nameText.maxWidth() + st::msgServiceFont->spacew, r.top() + st::msgPadding.top() + st::msgServiceFont->ascent, via()->text);
|
||||
}
|
||||
r.setTop(r.top() + st::msgNameFont->height);
|
||||
}
|
||||
|
||||
|
@ -6495,15 +6538,15 @@ void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 m
|
|||
|
||||
void HistoryMessage::drawMessageText(Painter &p, QRect trect, uint32 selection) const {
|
||||
bool outbg = out() && !fromChannel(), selected = (selection == FullSelection);
|
||||
if (via()) {
|
||||
if (!displayFromName() && via() && !toHistoryForwarded()) {
|
||||
p.setFont(st::msgServiceNameFont);
|
||||
p.setPen((selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg))->p);
|
||||
p.setPen(selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg));
|
||||
p.drawTextLeft(trect.left(), trect.top(), _history->width, via()->text);
|
||||
trect.setY(trect.y() + st::msgServiceNameFont->height);
|
||||
}
|
||||
|
||||
p.setPen(st::msgColor->p);
|
||||
p.setFont(st::msgFont->f);
|
||||
p.setPen(st::msgColor);
|
||||
p.setFont(st::msgFont);
|
||||
uint16 selectedFrom = (selection == FullSelection) ? 0 : (selection >> 16) & 0xFFFF;
|
||||
uint16 selectedTo = (selection == FullSelection) ? 0 : selection & 0xFFFF;
|
||||
_text.draw(p, trect.x(), trect.y(), trect.width(), Qt::AlignLeft, 0, -1, selectedFrom, selectedTo);
|
||||
|
@ -6549,8 +6592,10 @@ int32 HistoryMessage::resize(int32 width) {
|
|||
} else {
|
||||
_height += st::msgNameFont->height;
|
||||
}
|
||||
}
|
||||
if (via()) {
|
||||
if (via() && !toHistoryForwarded()) {
|
||||
via()->resize(width - st::msgPadding.left() - st::msgPadding.right() - _from->nameText.maxWidth() - st::msgServiceFont->spacew);
|
||||
}
|
||||
} else if (via() && !toHistoryForwarded()) {
|
||||
via()->resize(width - st::msgPadding.left() - st::msgPadding.right());
|
||||
if (emptyText() && !displayFromName()) {
|
||||
_height += st::msgPadding.top() + st::msgNameFont->height + st::mediaHeaderSkip;
|
||||
|
@ -6612,9 +6657,15 @@ void HistoryMessage::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32
|
|||
if (drawBubble()) {
|
||||
QRect r(left, st::msgMargin.top(), width, _height - st::msgMargin.top() - st::msgMargin.bottom());
|
||||
if (displayFromName()) { // from user left name
|
||||
if (x >= r.left() + st::msgPadding.left() && y >= r.top() + st::msgPadding.top() && y < r.top() + st::msgPadding.top() + st::msgNameFont->height && x < r.left() + r.width() - st::msgPadding.right() && x < r.left() + st::msgPadding.left() + _from->nameText.maxWidth()) {
|
||||
lnk = _from->lnk;
|
||||
return;
|
||||
if (y >= r.top() + st::msgPadding.top() && y < r.top() + st::msgPadding.top() + st::msgNameFont->height) {
|
||||
if (x >= r.left() + st::msgPadding.left() && x < r.left() + r.width() - st::msgPadding.right() && x < r.left() + st::msgPadding.left() + _from->nameText.maxWidth()) {
|
||||
lnk = _from->lnk;
|
||||
return;
|
||||
}
|
||||
if (via() && !toHistoryForwarded() && x >= r.left() + st::msgPadding.left() + _from->nameText.maxWidth() + st::msgServiceFont->spacew && x < r.left() + st::msgPadding.left() + _from->nameText.maxWidth() + st::msgServiceFont->spacew + via()->width) {
|
||||
lnk = via()->lnk;
|
||||
return;
|
||||
}
|
||||
}
|
||||
r.setTop(r.top() + st::msgNameFont->height);
|
||||
}
|
||||
|
@ -6629,7 +6680,7 @@ void HistoryMessage::getStateFromMessageText(TextLinkPtr &lnk, HistoryCursorStat
|
|||
|
||||
QRect trect(r.marginsAdded(-st::msgPadding));
|
||||
|
||||
if (via()) {
|
||||
if (!displayFromName() && via() && !toHistoryForwarded()) {
|
||||
if (x >= trect.left() && y >= trect.top() && y < trect.top() + st::msgNameFont->height && x < trect.left() + via()->width) {
|
||||
lnk = via()->lnk;
|
||||
return;
|
||||
|
@ -6678,8 +6729,7 @@ void HistoryMessage::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x,
|
|||
QRect r(left, st::msgMargin.top(), width, _height - st::msgMargin.top() - st::msgMargin.bottom());
|
||||
if (displayFromName()) { // from user left name
|
||||
r.setTop(r.top() + st::msgNameFont->height);
|
||||
}
|
||||
if (via()) {
|
||||
} else if (via() && !toHistoryForwarded()) {
|
||||
r.setTop(r.top() + st::msgNameFont->height);
|
||||
}
|
||||
QRect trect(r.marginsAdded(-st::msgPadding));
|
||||
|
@ -6765,12 +6815,16 @@ void HistoryForwarded::initDimensions() {
|
|||
HistoryMessage::initDimensions();
|
||||
if (!_media) {
|
||||
int32 _namew = st::msgPadding.left() + fromWidth + fwdFromName.maxWidth() + st::msgPadding.right();
|
||||
if (via()) {
|
||||
_namew += st::msgServiceFont->spacew + via()->maxWidth;
|
||||
}
|
||||
if (_namew > _maxw) _maxw = _namew;
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryForwarded::fwdNameUpdated() const {
|
||||
fwdFromName.setText(st::msgServiceNameFont, App::peerName(fwdFrom), _textNameOptions);
|
||||
QString fwdName((via() && fwdFrom->isUser()) ? fwdFrom->asUser()->firstName : App::peerName(fwdFrom));
|
||||
fwdFromName.setText(st::msgServiceNameFont, fwdName, _textNameOptions);
|
||||
}
|
||||
|
||||
void HistoryForwarded::draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const {
|
||||
|
@ -6788,10 +6842,17 @@ void HistoryForwarded::drawForwardedFrom(Painter &p, int32 x, int32 y, int32 w,
|
|||
p.setPen((selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg))->p);
|
||||
p.setFont(serviceFont);
|
||||
|
||||
if (w >= fromWidth) {
|
||||
if (via() && w > fromWidth + fwdFromName.maxWidth() + serviceFont->spacew) {
|
||||
p.drawText(x, y + serviceFont->ascent, lang(lng_forwarded_from));
|
||||
|
||||
p.setFont(serviceName->f);
|
||||
p.setFont(serviceName);
|
||||
fwdFromName.draw(p, x + fromWidth, y, w - fromWidth);
|
||||
|
||||
p.drawText(x + fromWidth + fwdFromName.maxWidth() + serviceFont->spacew, y + serviceFont->ascent, via()->text);
|
||||
} else if (w > fromWidth) {
|
||||
p.drawText(x, y + serviceFont->ascent, lang(lng_forwarded_from));
|
||||
|
||||
p.setFont(serviceName);
|
||||
fwdFromName.drawElided(p, x + fromWidth, y, w - fromWidth);
|
||||
} else {
|
||||
p.drawText(x, y + serviceFont->ascent, serviceFont->elided(lang(lng_forwarded_from), w));
|
||||
|
@ -6810,11 +6871,14 @@ int32 HistoryForwarded::resize(int32 width) {
|
|||
HistoryMessage::resize(width);
|
||||
if (drawBubble()) {
|
||||
if (displayForwardedFrom()) {
|
||||
if (emptyText() && !displayFromName() && !via()) {
|
||||
if (emptyText() && !displayFromName()) {
|
||||
_height += st::msgPadding.top() + st::msgServiceNameFont->height + st::mediaHeaderSkip;
|
||||
} else {
|
||||
_height += st::msgServiceNameFont->height;
|
||||
}
|
||||
if (via()) {
|
||||
via()->resize(width - st::msgPadding.left() - st::msgPadding.right() - fromWidth - fwdFromName.maxWidth() - st::msgServiceFont->spacew);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _height;
|
||||
|
@ -6876,6 +6940,8 @@ void HistoryForwarded::getForwardedState(TextLinkPtr &lnk, HistoryCursorState &s
|
|||
state = HistoryDefaultCursorState;
|
||||
if (x >= fromWidth && x < w && x < fromWidth + fwdFromName.maxWidth()) {
|
||||
lnk = fwdFrom->lnk;
|
||||
} else if (via() && x >= fromWidth + fwdFromName.maxWidth() + st::msgServiceFont->spacew && x < w && x < fromWidth + fwdFromName.maxWidth() + st::msgServiceFont->spacew + via()->maxWidth) {
|
||||
lnk = via()->lnk;
|
||||
} else {
|
||||
lnk = TextLinkPtr();
|
||||
}
|
||||
|
@ -6910,7 +6976,8 @@ HistoryReply::HistoryReply(History *history, HistoryBlock *block, const MTPDmess
|
|||
, replyToMsgId(msg.vreply_to_msg_id.v)
|
||||
, replyToMsg(0)
|
||||
, replyToVersion(0)
|
||||
, _maxReplyWidth(0) {
|
||||
, _maxReplyWidth(0)
|
||||
, _replyToVia(0) {
|
||||
if (!updateReplyTo() && App::api()) {
|
||||
App::api()->requestReplyTo(this, history->peer->asChannel(), replyToMsgId);
|
||||
}
|
||||
|
@ -6921,7 +6988,8 @@ HistoryReply::HistoryReply(History *history, HistoryBlock *block, MsgId msgId, i
|
|||
, replyToMsgId(replyTo)
|
||||
, replyToMsg(0)
|
||||
, replyToVersion(0)
|
||||
, _maxReplyWidth(0) {
|
||||
, _maxReplyWidth(0)
|
||||
, _replyToVia(0) {
|
||||
if (!updateReplyTo() && App::api()) {
|
||||
App::api()->requestReplyTo(this, history->peer->asChannel(), replyToMsgId);
|
||||
}
|
||||
|
@ -6932,7 +7000,8 @@ HistoryReply::HistoryReply(History *history, HistoryBlock *block, MsgId msgId, i
|
|||
, replyToMsgId(replyTo)
|
||||
, replyToMsg(0)
|
||||
, replyToVersion(0)
|
||||
, _maxReplyWidth(0) {
|
||||
, _maxReplyWidth(0)
|
||||
, _replyToVia(0) {
|
||||
if (!updateReplyTo() && App::api()) {
|
||||
App::api()->requestReplyTo(this, history->peer->asChannel(), replyToMsgId);
|
||||
}
|
||||
|
@ -6952,6 +7021,9 @@ void HistoryReply::initDimensions() {
|
|||
HistoryMessage::initDimensions();
|
||||
if (!_media) {
|
||||
int32 replyw = st::msgPadding.left() + _maxReplyWidth - st::msgReplyPadding.left() - st::msgReplyPadding.right() + st::msgPadding.right();
|
||||
if (replyToVia()) {
|
||||
replyw += st::msgServiceFont->spacew + via()->maxWidth;
|
||||
}
|
||||
if (replyw > _maxw) _maxw = replyw;
|
||||
}
|
||||
}
|
||||
|
@ -6959,6 +7031,7 @@ void HistoryReply::initDimensions() {
|
|||
bool HistoryReply::updateReplyTo(bool force) {
|
||||
if (replyToMsg || !replyToMsgId) return true;
|
||||
replyToMsg = App::histItemById(channelId(), replyToMsgId);
|
||||
|
||||
if (replyToMsg) {
|
||||
App::historyRegReply(this, replyToMsg);
|
||||
replyToText.setText(st::msgFont, replyToMsg->inReplyText(), _textDlgOptions);
|
||||
|
@ -6966,6 +7039,11 @@ bool HistoryReply::updateReplyTo(bool force) {
|
|||
replyToNameUpdated();
|
||||
|
||||
replyToLnk = TextLinkPtr(new MessageLink(replyToMsg->history()->peer->id, replyToMsg->id));
|
||||
if (!replyToMsg->toHistoryForwarded()) {
|
||||
if (UserData *bot = replyToMsg->viaBot()) {
|
||||
_replyToVia = new HistoryMessageVia(peerToUser(bot->id));
|
||||
}
|
||||
}
|
||||
} else if (force) {
|
||||
replyToMsgId = 0;
|
||||
}
|
||||
|
@ -6978,12 +7056,17 @@ bool HistoryReply::updateReplyTo(bool force) {
|
|||
|
||||
void HistoryReply::replyToNameUpdated() const {
|
||||
if (replyToMsg) {
|
||||
replyToName.setText(st::msgServiceNameFont, App::peerName(replyToMsg->from()), _textNameOptions);
|
||||
QString name = (replyToVia() && replyToMsg->from()->isUser()) ? replyToMsg->from()->asUser()->firstName : App::peerName(replyToMsg->from());
|
||||
replyToName.setText(st::msgServiceNameFont, name, _textNameOptions);
|
||||
replyToVersion = replyToMsg->from()->nameVersion;
|
||||
bool hasPreview = replyToMsg->getMedia() ? replyToMsg->getMedia()->hasReplyPreview() : false;
|
||||
int32 previewSkip = hasPreview ? (st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x()) : 0;
|
||||
int32 w = replyToName.maxWidth();
|
||||
if (replyToVia()) {
|
||||
w += st::msgServiceFont->spacew + replyToVia()->maxWidth;
|
||||
}
|
||||
|
||||
_maxReplyWidth = previewSkip + qMax(replyToName.maxWidth(), qMin(replyToText.maxWidth(), 4 * replyToName.maxWidth()));
|
||||
_maxReplyWidth = previewSkip + qMax(w, qMin(replyToText.maxWidth(), 4 * w));
|
||||
} else {
|
||||
_maxReplyWidth = st::msgDateFont->width(lang(replyToMsgId ? lng_profile_loading : lng_deleted_message));
|
||||
}
|
||||
|
@ -7056,6 +7139,10 @@ void HistoryReply::drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selec
|
|||
p.setPen(selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg));
|
||||
}
|
||||
replyToName.drawLeftElided(p, x + st::msgReplyBarSkip + previewSkip, y + st::msgReplyPadding.top(), w - st::msgReplyBarSkip - previewSkip, w + 2 * x);
|
||||
if (replyToVia() && w > st::msgReplyBarSkip + previewSkip + replyToName.maxWidth() + st::msgServiceFont->spacew) {
|
||||
p.setFont(st::msgServiceFont);
|
||||
p.drawText(x + st::msgReplyBarSkip + previewSkip + replyToName.maxWidth() + st::msgServiceFont->spacew, y + st::msgReplyPadding.top() + st::msgServiceFont->ascent, replyToVia()->text);
|
||||
}
|
||||
|
||||
HistoryMessage *replyToAsMsg = replyToMsg->toHistoryMessage();
|
||||
if (likeService) {
|
||||
|
@ -7094,10 +7181,23 @@ int32 HistoryReply::resize(int32 width) {
|
|||
} else {
|
||||
_height += st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();
|
||||
}
|
||||
if (replyToVia()) {
|
||||
bool hasPreview = replyToMsg->getMedia() ? replyToMsg->getMedia()->hasReplyPreview() : false;
|
||||
int previewSkip = hasPreview ? (st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x()) : 0;
|
||||
replyToVia()->resize(width - st::msgPadding.left() - st::msgPadding.right() - st::msgReplyBarSkip + previewSkip + replyToName.maxWidth() + st::msgServiceFont->spacew);
|
||||
}
|
||||
}
|
||||
return _height;
|
||||
}
|
||||
|
||||
void HistoryReply::resizeVia(int32 w) const {
|
||||
if (!replyToVia()) return;
|
||||
|
||||
bool hasPreview = replyToMsg->getMedia() ? replyToMsg->getMedia()->hasReplyPreview() : false;
|
||||
int previewSkip = hasPreview ? (st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x()) : 0;
|
||||
replyToVia()->resize(w - st::msgReplyBarSkip - previewSkip - replyToName.maxWidth() - st::msgServiceFont->spacew);
|
||||
}
|
||||
|
||||
bool HistoryReply::hasPoint(int32 x, int32 y) const {
|
||||
if (drawBubble()) {
|
||||
int32 left = 0, width = 0;
|
||||
|
@ -7186,6 +7286,7 @@ HistoryReply::~HistoryReply() {
|
|||
} else if (replyToMsgId && App::api()) {
|
||||
App::api()->itemRemoved(this);
|
||||
}
|
||||
deleteAndMark(_replyToVia);
|
||||
}
|
||||
|
||||
void HistoryServiceMsg::setMessageByAction(const MTPmessageAction &action) {
|
||||
|
|
|
@ -1680,6 +1680,7 @@ public:
|
|||
}
|
||||
|
||||
void initDimensions(const HistoryItem *parent);
|
||||
int32 resize(int32 width, const HistoryItem *parent);
|
||||
|
||||
void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
|
||||
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const;
|
||||
|
@ -1979,7 +1980,7 @@ public:
|
|||
|
||||
UserData *bot;
|
||||
QString text;
|
||||
int32 width, fullWidth;
|
||||
int32 width, maxWidth;
|
||||
TextLinkPtr lnk;
|
||||
|
||||
};
|
||||
|
@ -2164,7 +2165,7 @@ public:
|
|||
}
|
||||
QString selectedText(uint32 selection) const;
|
||||
bool displayForwardedFrom() const {
|
||||
return (!_media || !_media->isDisplayed() || !_media->hideForwardedFrom());
|
||||
return via() || !_media || !_media->isDisplayed() || !_media->hideForwardedFrom();
|
||||
}
|
||||
|
||||
HistoryForwarded *toHistoryForwarded() {
|
||||
|
@ -2207,6 +2208,7 @@ public:
|
|||
void drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selected, bool likeService = false) const;
|
||||
void drawMessageText(Painter &p, QRect trect, uint32 selection) const;
|
||||
int32 resize(int32 width);
|
||||
void resizeVia(int32 w) const;
|
||||
bool hasPoint(int32 x, int32 y) const;
|
||||
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const;
|
||||
void getStateFromMessageText(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const QRect &r) const;
|
||||
|
@ -2234,6 +2236,10 @@ protected:
|
|||
mutable Text replyToName, replyToText;
|
||||
mutable int32 replyToVersion;
|
||||
mutable int32 _maxReplyWidth;
|
||||
HistoryMessageVia *_replyToVia;
|
||||
HistoryMessageVia *replyToVia() const {
|
||||
return (_replyToVia && !_replyToVia->isNull()) ? _replyToVia : 0;
|
||||
}
|
||||
int32 toWidth;
|
||||
|
||||
};
|
||||
|
|
|
@ -2630,6 +2630,8 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
, _migrated(0)
|
||||
, _history(0)
|
||||
, _histInited(false)
|
||||
, _lastScroll(0)
|
||||
, _lastScrolled(0)
|
||||
, _toHistoryEnd(this, st::historyToEnd)
|
||||
, _collapseComments(this)
|
||||
, _attachMention(this)
|
||||
|
@ -2722,6 +2724,9 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
connect(audioCapture(), SIGNAL(onDone(QByteArray,qint32)), this, SLOT(onRecordDone(QByteArray,qint32)));
|
||||
}
|
||||
|
||||
_updateHistoryItems.setSingleShot(true);
|
||||
connect(&_updateHistoryItems, SIGNAL(timeout()), this, SLOT(onUpdateHistoryItems()));
|
||||
|
||||
_scrollTimer.setSingleShot(false);
|
||||
|
||||
_sendActionStopTimer.setSingleShot(true);
|
||||
|
@ -3508,6 +3513,8 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
|||
_scroll.setWidget(_list);
|
||||
_list->show();
|
||||
|
||||
_updateHistoryItems.stop();
|
||||
|
||||
if (_history->lastWidth || _history->isReadyFor(_showAtMsgId, _fixedInScrollMsgId, _fixedInScrollMsgTop)) {
|
||||
_fixedInScrollMsgId = 0;
|
||||
_fixedInScrollMsgTop = 0;
|
||||
|
@ -4360,6 +4367,11 @@ void HistoryWidget::onListScroll() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (st != _lastScroll) {
|
||||
_lastScrolled = getms();
|
||||
_lastScroll = st;
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onVisibleChanged() {
|
||||
|
@ -4407,8 +4419,9 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
|
|||
_saveDraftStart = getms();
|
||||
onDraftSave();
|
||||
|
||||
onCheckMentionDropdown();
|
||||
if (!_attachMention.isHidden()) _attachMention.hideStart();
|
||||
if (!_attachType.isHidden()) _attachType.hideStart();
|
||||
if (!_emojiPan.isHidden()) _emojiPan.hideStart();
|
||||
|
||||
if (replyTo < 0) cancelReply(lastKeyboardUsed);
|
||||
if (_previewData && _previewData->pendingTill) previewCancel();
|
||||
|
@ -5834,7 +5847,23 @@ bool HistoryWidget::isItemVisible(HistoryItem *item) {
|
|||
|
||||
void HistoryWidget::ui_repaintHistoryItem(const HistoryItem *item) {
|
||||
if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) {
|
||||
_list->repaintItem(item);
|
||||
uint64 ms = getms();
|
||||
if (_lastScrolled + 100 <= ms) {
|
||||
_list->repaintItem(item);
|
||||
} else {
|
||||
_updateHistoryItems.start(_lastScrolled + 100 - ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onUpdateHistoryItems() {
|
||||
if (!_list) return;
|
||||
|
||||
uint64 ms = getms();
|
||||
if (_lastScrolled + 100 <= ms) {
|
||||
_list->update();
|
||||
} else {
|
||||
_updateHistoryItems.start(_lastScrolled + 100 - ms);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6459,8 +6488,9 @@ void HistoryWidget::onInlineResultSend(InlineResult *result, UserData *bot) {
|
|||
Local::writeRecentHashtagsAndBots();
|
||||
}
|
||||
|
||||
onCheckMentionDropdown();
|
||||
if (!_attachMention.isHidden()) _attachMention.hideStart();
|
||||
if (!_attachType.isHidden()) _attachType.hideStart();
|
||||
if (!_emojiPan.isHidden()) _emojiPan.hideStart();
|
||||
|
||||
_field.setFocus();
|
||||
}
|
||||
|
|
|
@ -682,6 +682,8 @@ public slots:
|
|||
void onRecordDone(QByteArray result, qint32 samples);
|
||||
void onRecordUpdate(qint16 level, qint32 samples);
|
||||
|
||||
void onUpdateHistoryItems();
|
||||
|
||||
private:
|
||||
|
||||
MsgId _replyToId;
|
||||
|
@ -771,6 +773,10 @@ private:
|
|||
History *_migrated, *_history;
|
||||
bool _histInited; // initial updateListSize() called
|
||||
|
||||
int32 _lastScroll;
|
||||
uint64 _lastScrolled;
|
||||
QTimer _updateHistoryItems; // gifs optimization
|
||||
|
||||
IconedButton _toHistoryEnd;
|
||||
CollapseButton _collapseComments;
|
||||
|
||||
|
|
|
@ -193,6 +193,21 @@ style::color documentColor(int32 colorIndex) {
|
|||
return colors[colorIndex & 3];
|
||||
}
|
||||
|
||||
style::color documentDarkColor(int32 colorIndex) {
|
||||
static style::color colors[] = { st::msgFileBlueDark, st::msgFileGreenDark, st::msgFileRedDark, st::msgFileYellowDark };
|
||||
return colors[colorIndex & 3];
|
||||
}
|
||||
|
||||
style::color documentOverColor(int32 colorIndex) {
|
||||
static style::color colors[] = { st::msgFileBlueOver, st::msgFileGreenOver, st::msgFileRedOver, st::msgFileYellowOver };
|
||||
return colors[colorIndex & 3];
|
||||
}
|
||||
|
||||
style::color documentSelectedColor(int32 colorIndex) {
|
||||
static style::color colors[] = { st::msgFileBlueSelected, st::msgFileGreenSelected, st::msgFileRedSelected, st::msgFileYellowSelected };
|
||||
return colors[colorIndex & 3];
|
||||
}
|
||||
|
||||
style::sprite documentCorner(int32 colorIndex) {
|
||||
static style::sprite corners[] = { st::msgFileBlue, st::msgFileGreen, st::msgFileRed, st::msgFileYellow };
|
||||
return corners[colorIndex & 3];
|
||||
|
@ -285,14 +300,14 @@ LayoutOverviewDate::LayoutOverviewDate(const QDate &date, bool month)
|
|||
|
||||
void LayoutOverviewDate::initDimensions() {
|
||||
_maxw = st::normalFont->width(_text);
|
||||
_minh = st::linksDateMargin + st::normalFont->height + st::linksDateMargin + st::linksBorder;
|
||||
_minh = st::linksDateMargin.top() + st::normalFont->height + st::linksDateMargin.bottom() + st::linksBorder;
|
||||
}
|
||||
|
||||
void LayoutOverviewDate::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
if (clip.intersects(QRect(0, st::linksDateMargin, _width, st::normalFont->height))) {
|
||||
if (clip.intersects(QRect(0, st::linksDateMargin.top(), _width, st::normalFont->height))) {
|
||||
p.setPen(st::linksDateColor);
|
||||
p.setFont(st::normalFont);
|
||||
p.drawTextLeft(0, st::linksDateMargin, _width, _text);
|
||||
p.setFont(st::semiboldFont);
|
||||
p.drawTextLeft(0, st::linksDateMargin.top(), _width, _text);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -629,12 +644,24 @@ void LayoutOverviewAudio::paint(Painter &p, const QRect &clip, uint32 selection,
|
|||
if (clip.intersects(rtlrect(nameleft, statustop, namewidth, st::normalFont->height, _width))) {
|
||||
p.setFont(st::normalFont);
|
||||
p.setPen(selected ? st::mediaInFgSelected : st::mediaInFg);
|
||||
int32 unreadx = nameleft;
|
||||
if (_statusSize == FileStatusSizeLoaded || _statusSize == FileStatusSizeReady) {
|
||||
textstyleSet(&(selected ? st::mediaInStyleSelected : st::mediaInStyle));
|
||||
_details.drawLeftElided(p, nameleft, statustop, namewidth, _width);
|
||||
textstyleRestore();
|
||||
unreadx += _details.maxWidth();
|
||||
} else {
|
||||
p.drawTextLeft(nameleft, statustop, _width, _statusText);
|
||||
int32 statusw = st::normalFont->width(_statusText);
|
||||
p.drawTextLeft(nameleft, statustop, _width, _statusText, statusw);
|
||||
unreadx += statusw;
|
||||
}
|
||||
if (_parent->isMediaUnread() && unreadx + st::mediaUnreadSkip + st::mediaUnreadSize <= _width) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(selected ? st::msgFileInBgSelected : st::msgFileInBg);
|
||||
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing, true);
|
||||
p.drawEllipse(rtlrect(unreadx + st::mediaUnreadSkip, statustop + st::mediaUnreadTop, st::mediaUnreadSize, st::mediaUnreadSize, _width));
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -715,6 +742,7 @@ LayoutOverviewDocument::LayoutOverviewDocument(DocumentData *document, HistoryIt
|
|||
, _data(document)
|
||||
, _msgl(new MessageLink(parent))
|
||||
, _namel(new DocumentOpenLink(_data))
|
||||
, _thumbForLoaded(false)
|
||||
, _name(documentName(_data))
|
||||
, _date(langDateTime(date(_data->date)))
|
||||
, _namew(st::semiboldFont->width(_name))
|
||||
|
@ -728,17 +756,17 @@ LayoutOverviewDocument::LayoutOverviewDocument(DocumentData *document, HistoryIt
|
|||
_data->thumb->load();
|
||||
int32 tw = _data->thumb->width(), th = _data->thumb->height();
|
||||
if (tw > th) {
|
||||
_thumbw = (tw * st::msgFileThumbSize) / th;
|
||||
_thumbw = (tw * st::overviewFileSize) / th;
|
||||
} else {
|
||||
_thumbw = st::msgFileThumbSize;
|
||||
_thumbw = st::overviewFileSize;
|
||||
}
|
||||
} else {
|
||||
_thumbw = 0;
|
||||
}
|
||||
|
||||
_extw = st::semiboldFont->width(_ext);
|
||||
if (_extw > st::msgFileThumbSize - st::msgFileExtPadding * 2) {
|
||||
_ext = st::semiboldFont->elided(_ext, st::msgFileThumbSize - st::msgFileExtPadding * 2, Qt::ElideMiddle);
|
||||
if (_extw > st::overviewFileSize - st::msgFileExtPadding * 2) {
|
||||
_ext = st::semiboldFont->elided(_ext, st::overviewFileSize - st::msgFileExtPadding * 2, Qt::ElideMiddle);
|
||||
_extw = st::semiboldFont->width(_ext);
|
||||
}
|
||||
}
|
||||
|
@ -748,7 +776,7 @@ void LayoutOverviewDocument::initDimensions() {
|
|||
if (_data->song()) {
|
||||
_minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom();
|
||||
} else {
|
||||
_minh = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom() + st::lineWidth;
|
||||
_minh = st::overviewFilePadding.top() + st::overviewFileSize + st::overviewFilePadding.bottom() + st::lineWidth;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -817,39 +845,40 @@ void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selecti
|
|||
p.drawSpriteCenter(inner, icon);
|
||||
}
|
||||
} else {
|
||||
nameleft = st::msgFileThumbSize + st::msgFileThumbPadding.right();
|
||||
nametop = st::linksBorder + st::msgFileThumbNameTop;
|
||||
statustop = st::linksBorder + st::msgFileThumbStatusTop;
|
||||
datetop = st::linksBorder + st::msgFileThumbLinkTop;
|
||||
nameleft = st::overviewFileSize + st::overviewFilePadding.right();
|
||||
nametop = st::linksBorder + st::overviewFileNameTop;
|
||||
statustop = st::linksBorder + st::overviewFileStatusTop;
|
||||
datetop = st::linksBorder + st::overviewFileDateTop;
|
||||
|
||||
QRect shadow(rtlrect(nameleft, 0, _width - nameleft, st::linksBorder, _width));
|
||||
if (clip.intersects(shadow)) {
|
||||
p.fillRect(clip.intersected(shadow), st::linksBorderFg);
|
||||
const OverviewPaintContext *pcontext = context->toOverviewPaintContext();
|
||||
t_assert(pcontext != 0);
|
||||
QRect border(rtlrect(nameleft, 0, _width - nameleft, st::linksBorder, _width));
|
||||
if (!pcontext->isAfterDate && clip.intersects(border)) {
|
||||
p.fillRect(clip.intersected(border), st::linksBorderFg);
|
||||
}
|
||||
|
||||
QRect rthumb(rtlrect(0, st::linksBorder + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width));
|
||||
QRect rthumb(rtlrect(0, st::linksBorder + st::overviewFilePadding.top(), st::overviewFileSize, st::overviewFileSize, _width));
|
||||
if (clip.intersects(rthumb)) {
|
||||
if (wthumb) {
|
||||
if (_data->thumb->loaded()) {
|
||||
QPixmap thumb = loaded ? _data->thumb->pixSingle(_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize) : _data->thumb->pixBlurredSingle(_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize);
|
||||
p.drawPixmap(rthumb.topLeft(), thumb);
|
||||
if (_thumb.isNull() || loaded != _thumbForLoaded) {
|
||||
_thumbForLoaded = loaded;
|
||||
_thumb = _data->thumb->pixNoCache(_thumbw, 0, true, !_thumbForLoaded, false, st::overviewFileSize, st::overviewFileSize);
|
||||
}
|
||||
p.drawPixmap(rthumb.topLeft(), _thumb);
|
||||
} else {
|
||||
App::roundRect(p, rthumb, st::black, BlackCorners);
|
||||
p.fillRect(rthumb, st::black);
|
||||
}
|
||||
} else {
|
||||
App::roundRect(p, rthumb, documentColor(_colorIndex), documentCorners(_colorIndex));
|
||||
if (!radial && loaded) {
|
||||
style::sprite icon = documentCorner(_colorIndex);
|
||||
p.drawSprite(rthumb.topLeft() + QPoint(rtl() ? 0 : (rthumb.width() - icon.pxWidth()), 0), icon);
|
||||
if (!_ext.isEmpty()) {
|
||||
p.setFont(st::semiboldFont);
|
||||
p.setPen(st::white);
|
||||
p.drawText(rthumb.left() + (rthumb.width() - _extw) / 2, rthumb.top() + st::msgFileExtTop + st::semiboldFont->ascent, _ext);
|
||||
}
|
||||
p.fillRect(rthumb, documentColor(_colorIndex));
|
||||
if (!radial && loaded && !_ext.isEmpty()) {
|
||||
p.setFont(st::semiboldFont);
|
||||
p.setPen(st::white);
|
||||
p.drawText(rthumb.left() + (rthumb.width() - _extw) / 2, rthumb.top() + st::msgFileExtTop + st::semiboldFont->ascent, _ext);
|
||||
}
|
||||
}
|
||||
if (selected) {
|
||||
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
|
||||
p.fillRect(rthumb, textstyleCurrent()->selectOverlay);
|
||||
}
|
||||
|
||||
if (radial || (!loaded && !_data->loading())) {
|
||||
|
@ -858,15 +887,19 @@ void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selecti
|
|||
float64 radialOpacity = (radial && loaded && !_data->uploading()) ? _radial->opacity() : 1;
|
||||
p.setPen(Qt::NoPen);
|
||||
if (selected) {
|
||||
p.setBrush(st::msgDateImgBgSelected);
|
||||
p.setBrush(wthumb ? st::msgDateImgBgSelected : documentSelectedColor(_colorIndex));
|
||||
} else if (_a_iconOver.animating()) {
|
||||
_a_iconOver.step(context->ms);
|
||||
float64 over = a_iconOver.current();
|
||||
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
|
||||
p.setBrush(st::black);
|
||||
if (wthumb) {
|
||||
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
|
||||
p.setBrush(st::black);
|
||||
} else {
|
||||
p.setBrush(style::interpolate(documentDarkColor(_colorIndex), documentOverColor(_colorIndex), over));
|
||||
}
|
||||
} else {
|
||||
bool over = textlnkDrawOver(_data->loading() ? _cancell : _savel);
|
||||
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
|
||||
p.setBrush(over ? (wthumb ? st::msgDateImgBgOver : documentOverColor(_colorIndex)) : (wthumb ? st::msgDateImgBg : documentDarkColor(_colorIndex)));
|
||||
}
|
||||
p.setOpacity(radialOpacity * p.opacity());
|
||||
|
||||
|
@ -890,10 +923,10 @@ void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selecti
|
|||
}
|
||||
}
|
||||
}
|
||||
if (selected) {
|
||||
p.drawSprite(rthumb.topLeft() + QPoint(rtl() ? 0 : (rthumb.width() - st::linksPhotoChecked.pxWidth()), rthumb.height() - st::linksPhotoChecked.pxHeight()), st::linksPhotoChecked);
|
||||
} else if (context->selecting) {
|
||||
p.drawSprite(rthumb.topLeft() + QPoint(rtl() ? 0 : (rthumb.width() - st::linksPhotoCheck.pxWidth()), rthumb.height() - st::linksPhotoCheck.pxHeight()), st::linksPhotoCheck);
|
||||
if (selected || context->selecting) {
|
||||
QRect check(rthumb.topLeft() + QPoint(rtl() ? 0 : (rthumb.width() - st::defaultCheckbox.diameter), rthumb.height() - st::defaultCheckbox.diameter), QSize(st::defaultCheckbox.diameter, st::defaultCheckbox.diameter));
|
||||
p.fillRect(check, selected ? st::overviewFileChecked : st::overviewFileCheck);
|
||||
p.drawSpriteCenter(check, st::defaultCheckbox.checkIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -946,12 +979,12 @@ void LayoutOverviewDocument::getState(TextLinkPtr &link, HistoryCursorState &cur
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
nameleft = st::msgFileThumbSize + st::msgFileThumbPadding.right();
|
||||
nametop = st::linksBorder + st::msgFileThumbNameTop;
|
||||
statustop = st::linksBorder + st::msgFileThumbStatusTop;
|
||||
datetop = st::linksBorder + st::msgFileThumbLinkTop;
|
||||
nameleft = st::overviewFileSize + st::overviewFilePadding.right();
|
||||
nametop = st::linksBorder + st::overviewFileNameTop;
|
||||
statustop = st::linksBorder + st::overviewFileStatusTop;
|
||||
datetop = st::linksBorder + st::overviewFileDateTop;
|
||||
|
||||
QRect rthumb(rtlrect(0, st::linksBorder + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width));
|
||||
QRect rthumb(rtlrect(0, st::linksBorder + st::overviewFilePadding.top(), st::overviewFileSize, st::overviewFileSize, _width));
|
||||
|
||||
if (rthumb.contains(x, y)) {
|
||||
link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _savel);
|
||||
|
@ -1150,7 +1183,7 @@ void LayoutOverviewLink::initDimensions() {
|
|||
_minh += qMin(3 * st::normalFont->height, _text.countHeight(_maxw - st::dlgPhotoSize - st::dlgPhotoPadding));
|
||||
}
|
||||
_minh += _links.size() * st::normalFont->height;
|
||||
_minh = qMax(_minh, int32(st::dlgPhotoSize)) + st::linksMargin * 2 + st::linksBorder;
|
||||
_minh = qMax(_minh, int32(st::dlgPhotoSize)) + st::linksMargin.top() + st::linksMargin.bottom() + st::linksBorder;
|
||||
}
|
||||
|
||||
int32 LayoutOverviewLink::resizeGetHeight(int32 width) {
|
||||
|
@ -1168,12 +1201,12 @@ int32 LayoutOverviewLink::resizeGetHeight(int32 width) {
|
|||
_height += qMin(3 * st::normalFont->height, _text.countHeight(_width - st::dlgPhotoSize - st::dlgPhotoPadding));
|
||||
}
|
||||
_height += _links.size() * st::normalFont->height;
|
||||
_height = qMax(_height, int32(st::dlgPhotoSize)) + st::linksMargin * 2 + st::linksBorder;
|
||||
_height = qMax(_height, int32(st::dlgPhotoSize)) + st::linksMargin.top() + st::linksMargin.bottom() + st::linksBorder;
|
||||
return _height;
|
||||
}
|
||||
|
||||
void LayoutOverviewLink::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
int32 left = st::dlgPhotoSize + st::dlgPhotoPadding, top = st::linksMargin + st::linksBorder, w = _width - left;
|
||||
int32 left = st::dlgPhotoSize + st::dlgPhotoPadding, top = st::linksMargin.top() + st::linksBorder, w = _width - left;
|
||||
if (clip.intersects(rtlrect(0, top, st::dlgPhotoSize, st::dlgPhotoSize, _width))) {
|
||||
if (_page && _page->photo) {
|
||||
QPixmap pix;
|
||||
|
@ -1213,6 +1246,8 @@ void LayoutOverviewLink::paint(Painter &p, const QRect &clip, uint32 selection,
|
|||
|
||||
if (!_title.isEmpty() && _text.isEmpty() && _links.size() == 1) {
|
||||
top += (st::dlgPhotoSize - st::semiboldFont->height - st::normalFont->height) / 2;
|
||||
} else {
|
||||
top = st::linksTextTop;
|
||||
}
|
||||
|
||||
p.setPen(st::black);
|
||||
|
@ -1241,13 +1276,16 @@ void LayoutOverviewLink::paint(Painter &p, const QRect &clip, uint32 selection,
|
|||
top += st::normalFont->height;
|
||||
}
|
||||
|
||||
if (clip.intersects(rtlrect(left, 0, w, st::linksBorder, _width))) {
|
||||
p.fillRect(clip.intersected(rtlrect(left, 0, w, st::linksBorder, _width)), st::linksBorderFg);
|
||||
const OverviewPaintContext *pcontext = context->toOverviewPaintContext();
|
||||
t_assert(pcontext != 0);
|
||||
QRect border(rtlrect(left, 0, w, st::linksBorder, _width));
|
||||
if (!pcontext->isAfterDate && clip.intersects(border)) {
|
||||
p.fillRect(clip.intersected(border), st::linksBorderFg);
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutOverviewLink::getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const {
|
||||
int32 left = st::dlgPhotoSize + st::dlgPhotoPadding, top = st::linksMargin + st::linksBorder, w = _width - left;
|
||||
int32 left = st::dlgPhotoSize + st::dlgPhotoPadding, top = st::linksMargin.top() + st::linksBorder, w = _width - left;
|
||||
if (rtlrect(0, top, st::dlgPhotoSize, st::dlgPhotoSize, _width).contains(x, y)) {
|
||||
link = _photol;
|
||||
return;
|
||||
|
@ -1809,6 +1847,7 @@ void LayoutInlinePhoto::content_forget() {
|
|||
|
||||
LayoutInlineWebVideo::LayoutInlineWebVideo(InlineResult *result) : LayoutInlineItem(result, 0, 0)
|
||||
, _send(new SendInlineItemLink())
|
||||
, _link(result->content_url.isEmpty() ? 0 : linkFromUrl(result->content_url))
|
||||
, _title(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip)
|
||||
, _description(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip) {
|
||||
if (_result->duration) {
|
||||
|
@ -1866,8 +1905,13 @@ void LayoutInlineWebVideo::paint(Painter &p, const QRect &clip, uint32 selection
|
|||
}
|
||||
|
||||
void LayoutInlineWebVideo::getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const {
|
||||
if (x >= 0 && x < _width && y >= 0 && y < _height) {
|
||||
if (x >= 0 && x < st::inlineThumbSize && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::inlineThumbSize) {
|
||||
link = _link;
|
||||
return;
|
||||
}
|
||||
if (x >= st::inlineThumbSize + st::inlineThumbSkip && x < _width && y >= 0 && y < _height) {
|
||||
link = _send;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1896,6 +1940,7 @@ void LayoutInlineWebVideo::prepareThumb(int32 width, int32 height) const {
|
|||
LayoutInlineArticle::LayoutInlineArticle(InlineResult *result, bool withThumb) : LayoutInlineItem(result, 0, 0)
|
||||
, _send(new SendInlineItemLink())
|
||||
, _url(result->url.isEmpty() ? 0 : linkFromUrl(result->url))
|
||||
, _link(result->content_url.isEmpty() ? 0 : linkFromUrl(result->content_url))
|
||||
, _withThumb(withThumb)
|
||||
, _title(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip)
|
||||
, _description(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip) {
|
||||
|
@ -1995,7 +2040,12 @@ void LayoutInlineArticle::paint(Painter &p, const QRect &clip, uint32 selection,
|
|||
}
|
||||
|
||||
void LayoutInlineArticle::getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const {
|
||||
if (x >= 0 && x < _width && y >= 0 && y < _height) {
|
||||
int32 left = _withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : 0;
|
||||
if (x >= 0 && x < left - st::inlineThumbSkip && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::inlineThumbSize) {
|
||||
link = _link;
|
||||
return;
|
||||
}
|
||||
if (x >= left && x < _width && y >= 0 && y < _height) {
|
||||
if (_url) {
|
||||
int32 left = st::inlineThumbSize + st::inlineThumbSkip;
|
||||
int32 titleHeight = qMin(_title.countHeight(_width - left), st::semiboldFont->height * 2);
|
||||
|
@ -2007,6 +2057,7 @@ void LayoutInlineArticle::getState(TextLinkPtr &link, HistoryCursorState &cursor
|
|||
}
|
||||
}
|
||||
link = _send;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,9 +75,13 @@ QString formatPlayedText(qint64 played, qint64 duration);
|
|||
QString documentName(DocumentData *document);
|
||||
int32 documentColorIndex(DocumentData *document, QString &ext);
|
||||
style::color documentColor(int32 colorIndex);
|
||||
style::color documentDarkColor(int32 colorIndex);
|
||||
style::color documentOverColor(int32 colorIndex);
|
||||
style::color documentSelectedColor(int32 colorIndex);
|
||||
style::sprite documentCorner(int32 colorIndex);
|
||||
RoundCorners documentCorners(int32 colorIndex);
|
||||
|
||||
class OverviewPaintContext;
|
||||
class InlinePaintContext;
|
||||
class PaintContext {
|
||||
public:
|
||||
|
@ -86,6 +90,10 @@ public:
|
|||
}
|
||||
uint64 ms;
|
||||
bool selecting;
|
||||
|
||||
virtual const OverviewPaintContext *toOverviewPaintContext() const {
|
||||
return 0;
|
||||
}
|
||||
virtual const InlinePaintContext *toInlinePaintContext() const {
|
||||
return 0;
|
||||
}
|
||||
|
@ -257,6 +265,17 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
class OverviewPaintContext : public PaintContext {
|
||||
public:
|
||||
OverviewPaintContext(uint64 ms, bool selecting) : PaintContext(ms, selecting), isAfterDate(false) {
|
||||
}
|
||||
const OverviewPaintContext *toOverviewPaintContext() const {
|
||||
return this;
|
||||
}
|
||||
bool isAfterDate;
|
||||
|
||||
};
|
||||
|
||||
class OverviewItemInfo {
|
||||
public:
|
||||
OverviewItemInfo() : _top(0) {
|
||||
|
@ -267,7 +286,7 @@ public:
|
|||
void setTop(int32 top) {
|
||||
_top = top;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
int32 _top;
|
||||
|
||||
|
@ -276,7 +295,7 @@ private:
|
|||
class LayoutOverviewDate : public LayoutItem {
|
||||
public:
|
||||
LayoutOverviewDate(const QDate &date, bool month);
|
||||
|
||||
|
||||
virtual void initDimensions();
|
||||
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||
|
||||
|
@ -426,6 +445,9 @@ private:
|
|||
DocumentData *_data;
|
||||
TextLinkPtr _msgl, _namel;
|
||||
|
||||
mutable bool _thumbForLoaded;
|
||||
mutable QPixmap _thumb;
|
||||
|
||||
QString _name, _date, _ext;
|
||||
int32 _namew, _datew, _extw;
|
||||
int32 _thumbw, _colorIndex;
|
||||
|
@ -492,7 +514,7 @@ class LayoutInlineItem : public LayoutItem {
|
|||
public:
|
||||
|
||||
LayoutInlineItem(InlineResult *result, DocumentData *doc, PhotoData *photo);
|
||||
|
||||
|
||||
virtual void setPosition(int32 position);
|
||||
int32 position() const;
|
||||
|
||||
|
@ -644,7 +666,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
TextLinkPtr _send;
|
||||
TextLinkPtr _send, _link;
|
||||
|
||||
mutable QPixmap _thumb;
|
||||
Text _title, _description;
|
||||
|
@ -667,7 +689,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
TextLinkPtr _send, _url;
|
||||
TextLinkPtr _send, _url, _link;
|
||||
|
||||
bool _withThumb;
|
||||
mutable QPixmap _thumb;
|
||||
|
|
|
@ -834,7 +834,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
|
|||
p.setClipRect(r);
|
||||
}
|
||||
uint64 ms = getms();
|
||||
PaintContext context(ms, _selMode);
|
||||
OverviewPaintContext context(ms, _selMode);
|
||||
|
||||
if (_history->overview[_type].isEmpty() && (!_migrated || !_history->overviewLoaded(_type) || _migrated->overview[_type].isEmpty())) {
|
||||
QPoint dogPos((_width - st::msgDogImg.pxWidth()) / 2, ((height() - st::msgDogImg.pxHeight()) * 4) / 9);
|
||||
|
@ -887,6 +887,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
|
|||
if (_reversed) curY = _height - curY;
|
||||
if (_marginTop + curY >= r.y() + r.height()) break;
|
||||
|
||||
context.isAfterDate = (j > 0) ? !_items.at(j - 1)->toLayoutMediaItem() : false;
|
||||
p.translate(0, curY - y);
|
||||
_items.at(i)->paint(p, r.translated(-_rowsLeft, -_marginTop - curY), itemSelectedValue(i), &context);
|
||||
y = curY;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.9.15</string>
|
||||
<string>0.9.16</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
|
|
@ -34,8 +34,8 @@ IDI_ICON1 ICON "SourceFiles\\art\\icon256.ico"
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,9,15,7
|
||||
PRODUCTVERSION 0,9,15,7
|
||||
FILEVERSION 0,9,16,0
|
||||
PRODUCTVERSION 0,9,16,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -51,10 +51,10 @@ BEGIN
|
|||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||
VALUE "FileVersion", "0.9.15.7"
|
||||
VALUE "FileVersion", "0.9.16.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2013"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "0.9.15.7"
|
||||
VALUE "ProductVersion", "0.9.16.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -1701,7 +1701,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.9.15;
|
||||
CURRENT_PROJECT_VERSION = 0.9.16;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
|
@ -1720,7 +1720,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CURRENT_PROJECT_VERSION = 0.9.15;
|
||||
CURRENT_PROJECT_VERSION = 0.9.16;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = fast;
|
||||
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
|
||||
|
@ -1747,10 +1747,10 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.9.15;
|
||||
CURRENT_PROJECT_VERSION = 0.9.16;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DYLIB_COMPATIBILITY_VERSION = 0.9;
|
||||
DYLIB_CURRENT_VERSION = 0.9.15;
|
||||
DYLIB_CURRENT_VERSION = 0.9.16;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
|
@ -1882,10 +1882,10 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.9.15;
|
||||
CURRENT_PROJECT_VERSION = 0.9.16;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DYLIB_COMPATIBILITY_VERSION = 0.9;
|
||||
DYLIB_CURRENT_VERSION = 0.9.15;
|
||||
DYLIB_CURRENT_VERSION = 0.9.16;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AppVersion 9015
|
||||
AppVersion 9016
|
||||
AppVersionStrMajor 0.9
|
||||
AppVersionStrSmall 0.9.15
|
||||
AppVersionStr 0.9.15
|
||||
AppVersionStrSmall 0.9.16
|
||||
AppVersionStr 0.9.16
|
||||
DevChannel 0
|
||||
BetaVersion 9015007
|
||||
BetaVersion 0 9015008
|
||||
|
|
Loading…
Reference in New Issue