mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-03 21:32:16 +00:00
voice messages moved to documents with waveforms
This commit is contained in:
parent
ffa588bf5d
commit
189d0e8de3
@ -1286,6 +1286,15 @@ msgFileRadialLine: 3px;
|
||||
|
||||
msgVideoSize: size(320px, 240px);
|
||||
|
||||
msgWaveformBar: 2px;
|
||||
msgWaveformSkip: 1px;
|
||||
msgWaveformMin: 2px;
|
||||
msgWaveformMax: 20px;
|
||||
msgWaveformInActive: #59b6eb;
|
||||
msgWaveformInInactive: #deeaf1;
|
||||
msgWaveformOutActive: #78c67f;
|
||||
msgWaveformOutInactive: #c4e8c5;
|
||||
|
||||
sendPadding: 9px;
|
||||
btnSend: flatButton(btnDefFlat) {
|
||||
color: btnYesColor;
|
||||
@ -1386,7 +1395,7 @@ btnRecordAudio: sprite(379px, 390px, 16px, 24px);
|
||||
btnRecordAudioActive: sprite(379px, 366px, 16px, 24px);
|
||||
recordSignalColor: #f17077;
|
||||
recordSignalMin: 5px;
|
||||
recordSignalMax: 10px;
|
||||
recordSignalMax: 12px;
|
||||
recordCancel: #aaa;
|
||||
recordCancelActive: #ec6466;
|
||||
recordFont: font(13px);
|
||||
|
@ -48,7 +48,6 @@ namespace {
|
||||
|
||||
PhotosData photosData;
|
||||
VideosData videosData;
|
||||
AudiosData audiosData;
|
||||
DocumentsData documentsData;
|
||||
|
||||
typedef QHash<QString, ImageLinkData*> ImageLinksData;
|
||||
@ -65,7 +64,6 @@ namespace {
|
||||
|
||||
PhotoItems photoItems;
|
||||
VideoItems videoItems;
|
||||
AudioItems audioItems;
|
||||
DocumentItems documentItems;
|
||||
WebPageItems webPageItems;
|
||||
SharedContactItems sharedContactItems;
|
||||
@ -1293,22 +1291,6 @@ namespace App {
|
||||
return App::videoSet(video.vid.v, convert, video.vaccess_hash.v, video.vdate.v, video.vduration.v, video.vw.v, video.vh.v, App::image(video.vthumb), video.vdc_id.v, video.vsize.v);
|
||||
}
|
||||
|
||||
AudioData *feedAudio(const MTPaudio &audio, AudioData *convert) {
|
||||
switch (audio.type()) {
|
||||
case mtpc_audio: {
|
||||
return feedAudio(audio.c_audio(), convert);
|
||||
} break;
|
||||
case mtpc_audioEmpty: {
|
||||
return App::audioSet(audio.c_audioEmpty().vid.v, convert, 0, 0, QString(), 0, 0, 0);
|
||||
} break;
|
||||
}
|
||||
return App::audio(0);
|
||||
}
|
||||
|
||||
AudioData *feedAudio(const MTPDaudio &audio, AudioData *convert) {
|
||||
return App::audioSet(audio.vid.v, convert, audio.vaccess_hash.v, audio.vdate.v, qs(audio.vmime_type), audio.vduration.v, audio.vdc_id.v, audio.vsize.v);
|
||||
}
|
||||
|
||||
DocumentData *feedDocument(const MTPdocument &document, const QPixmap &thumb) {
|
||||
switch (document.type()) {
|
||||
case mtpc_document: {
|
||||
@ -1568,56 +1550,6 @@ namespace App {
|
||||
return result;
|
||||
}
|
||||
|
||||
AudioData *audio(const AudioId &audio) {
|
||||
AudiosData::const_iterator i = ::audiosData.constFind(audio);
|
||||
if (i == ::audiosData.cend()) {
|
||||
i = ::audiosData.insert(audio, new AudioData(audio));
|
||||
}
|
||||
return i.value();
|
||||
}
|
||||
|
||||
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) {
|
||||
if (convert) {
|
||||
if (convert->id != audio) {
|
||||
AudiosData::iterator i = ::audiosData.find(convert->id);
|
||||
if (i != ::audiosData.cend() && i.value() == convert) {
|
||||
::audiosData.erase(i);
|
||||
}
|
||||
convert->id = audio;
|
||||
convert->status = FileReady;
|
||||
}
|
||||
if (date) {
|
||||
convert->access = access;
|
||||
convert->date = date;
|
||||
convert->mime = mime;
|
||||
convert->duration = duration;
|
||||
convert->dc = dc;
|
||||
convert->size = size;
|
||||
}
|
||||
}
|
||||
AudiosData::const_iterator i = ::audiosData.constFind(audio);
|
||||
AudioData *result;
|
||||
if (i == ::audiosData.cend()) {
|
||||
if (convert) {
|
||||
result = convert;
|
||||
} else {
|
||||
result = new AudioData(audio, access, date, mime, duration, dc, size);
|
||||
}
|
||||
::audiosData.insert(audio, result);
|
||||
} else {
|
||||
result = i.value();
|
||||
if (result != convert && date) {
|
||||
result->access = access;
|
||||
result->date = date;
|
||||
result->mime = mime;
|
||||
result->duration = duration;
|
||||
result->dc = dc;
|
||||
result->size = size;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DocumentData *document(const DocumentId &document) {
|
||||
DocumentsData::const_iterator i = ::documentsData.constFind(document);
|
||||
if (i == ::documentsData.cend()) {
|
||||
@ -1795,9 +1727,6 @@ namespace App {
|
||||
for (VideosData::const_iterator i = ::videosData.cbegin(), e = ::videosData.cend(); i != e; ++i) {
|
||||
i.value()->forget();
|
||||
}
|
||||
for (AudiosData::const_iterator i = ::audiosData.cbegin(), e = ::audiosData.cend(); i != e; ++i) {
|
||||
i.value()->forget();
|
||||
}
|
||||
for (DocumentsData::const_iterator i = ::documentsData.cbegin(), e = ::documentsData.cend(); i != e; ++i) {
|
||||
i.value()->forget();
|
||||
}
|
||||
@ -1955,10 +1884,6 @@ namespace App {
|
||||
delete *i;
|
||||
}
|
||||
::videosData.clear();
|
||||
for (AudiosData::const_iterator i = ::audiosData.cbegin(), e = ::audiosData.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
::audiosData.clear();
|
||||
for (DocumentsData::const_iterator i = ::documentsData.cbegin(), e = ::documentsData.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
@ -1977,7 +1902,6 @@ namespace App {
|
||||
cSetReportSpamStatuses(ReportSpamStatuses());
|
||||
::photoItems.clear();
|
||||
::videoItems.clear();
|
||||
::audioItems.clear();
|
||||
::documentItems.clear();
|
||||
::webPageItems.clear();
|
||||
::sharedContactItems.clear();
|
||||
@ -2392,22 +2316,6 @@ namespace App {
|
||||
return ::videosData;
|
||||
}
|
||||
|
||||
void regAudioItem(AudioData *data, HistoryItem *item) {
|
||||
::audioItems[data].insert(item, NullType());
|
||||
}
|
||||
|
||||
void unregAudioItem(AudioData*data, HistoryItem *item) {
|
||||
::audioItems[data].remove(item);
|
||||
}
|
||||
|
||||
const AudioItems &audioItems() {
|
||||
return ::audioItems;
|
||||
}
|
||||
|
||||
const AudiosData &audiosData() {
|
||||
return ::audiosData;
|
||||
}
|
||||
|
||||
void regDocumentItem(DocumentData *data, HistoryItem *item) {
|
||||
::documentItems[data].insert(item, NullType());
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ class FileUploader;
|
||||
typedef QMap<HistoryItem*, NullType> HistoryItemsMap;
|
||||
typedef QHash<PhotoData*, HistoryItemsMap> PhotoItems;
|
||||
typedef QHash<VideoData*, HistoryItemsMap> VideoItems;
|
||||
typedef QHash<AudioData*, HistoryItemsMap> AudioItems;
|
||||
typedef QHash<DocumentData*, HistoryItemsMap> DocumentItems;
|
||||
typedef QHash<WebPageData*, HistoryItemsMap> WebPageItems;
|
||||
typedef QHash<int32, HistoryItemsMap> SharedContactItems;
|
||||
@ -45,7 +44,6 @@ typedef QHash<ClipReader*, HistoryItem*> GifItems;
|
||||
|
||||
typedef QHash<PhotoId, PhotoData*> PhotosData;
|
||||
typedef QHash<VideoId, VideoData*> VideosData;
|
||||
typedef QHash<AudioId, AudioData*> AudiosData;
|
||||
typedef QHash<DocumentId, DocumentData*> DocumentsData;
|
||||
|
||||
struct ReplyMarkup {
|
||||
@ -107,8 +105,6 @@ namespace App {
|
||||
PhotoData *feedPhoto(const MTPPhoto &photo, PhotoData *convert = 0);
|
||||
PhotoData *feedPhoto(const MTPDphoto &photo, PhotoData *convert = 0);
|
||||
VideoData *feedVideo(const MTPDvideo &video, VideoData *convert = 0);
|
||||
AudioData *feedAudio(const MTPaudio &audio, AudioData *convert = 0);
|
||||
AudioData *feedAudio(const MTPDaudio &audio, AudioData *convert = 0);
|
||||
DocumentData *feedDocument(const MTPdocument &document, const QPixmap &thumb);
|
||||
DocumentData *feedDocument(const MTPdocument &document, DocumentData *convert = 0);
|
||||
DocumentData *feedDocument(const MTPDdocument &document, DocumentData *convert = 0);
|
||||
@ -138,8 +134,6 @@ namespace App {
|
||||
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
|
||||
VideoData *video(const VideoId &video);
|
||||
VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size);
|
||||
AudioData *audio(const AudioId &audio);
|
||||
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size);
|
||||
DocumentData *document(const DocumentId &document);
|
||||
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation);
|
||||
WebPageData *webPage(const WebPageId &webPage);
|
||||
@ -219,11 +213,6 @@ namespace App {
|
||||
const VideoItems &videoItems();
|
||||
const VideosData &videosData();
|
||||
|
||||
void regAudioItem(AudioData *data, HistoryItem *item);
|
||||
void unregAudioItem(AudioData*data, HistoryItem *item);
|
||||
const AudioItems &audioItems();
|
||||
const AudiosData &audiosData();
|
||||
|
||||
void regDocumentItem(DocumentData *data, HistoryItem *item);
|
||||
void unregDocumentItem(DocumentData *data, HistoryItem *item);
|
||||
const DocumentItems &documentItems();
|
||||
|
@ -1039,7 +1039,7 @@ void AppClass::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId) {
|
||||
int32 filesize = 0;
|
||||
QByteArray data;
|
||||
|
||||
ReadyLocalMedia ready(PreparePhoto, file, filename, filesize, data, id, id, qsl("jpg"), peerId, photo, MTP_audioEmpty(MTP_long(0)), photoThumbs, MTP_documentEmpty(MTP_long(0)), jpeg, false, false, 0);
|
||||
ReadyLocalMedia ready(PreparePhoto, file, filename, filesize, data, id, id, qsl("jpg"), peerId, photo, photoThumbs, MTP_documentEmpty(MTP_long(0)), jpeg, false, false, 0);
|
||||
|
||||
connect(App::uploader(), SIGNAL(photoReady(const FullMsgId&, const MTPInputFile&)), App::app(), SLOT(photoUpdated(const FullMsgId&, const MTPInputFile&)), Qt::UniqueConnection);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,7 +56,7 @@ public:
|
||||
void play(const AudioMsgId &audio, int64 position = 0);
|
||||
void play(const SongMsgId &song, int64 position = 0);
|
||||
void pauseresume(MediaOverviewType type, bool fast = false);
|
||||
void seek(int64 position); // type == OverviewDocuments
|
||||
void seek(int64 position); // type == OverviewFiles
|
||||
void stop(MediaOverviewType type);
|
||||
|
||||
void stopAndClear();
|
||||
@ -201,8 +201,8 @@ signals:
|
||||
void captureOnStart();
|
||||
void captureOnStop(bool needResult);
|
||||
|
||||
void onDone(QByteArray data, qint32 samples);
|
||||
void onUpdate(qint16 level, qint32 samples);
|
||||
void onDone(QByteArray data, VoiceWaveform waveform, qint32 samples);
|
||||
void onUpdate(quint16 level, qint32 samples);
|
||||
void onError();
|
||||
|
||||
private:
|
||||
@ -338,8 +338,8 @@ public:
|
||||
signals:
|
||||
|
||||
void error();
|
||||
void update(qint16 level, qint32 samples);
|
||||
void done(QByteArray data, qint32 samples);
|
||||
void update(quint16 level, qint32 samples);
|
||||
void done(QByteArray data, VoiceWaveform waveform, qint32 samples);
|
||||
|
||||
public slots:
|
||||
|
||||
@ -360,3 +360,4 @@ private:
|
||||
};
|
||||
|
||||
MTPDocumentAttribute audioReadSongAttributes(const QString &fname, const QByteArray &data, QImage &cover, QByteArray &coverBytes, QByteArray &coverFormat);
|
||||
VoiceWaveform audioCountWaveform(const FileLocation &file, const QByteArray &data);
|
||||
|
@ -313,9 +313,11 @@ void AutoDownloadBox::onSave() {
|
||||
bool enabledGroups = ((cAutoDownloadAudio() & dbiadNoGroups) && !(autoDownloadAudio & dbiadNoGroups));
|
||||
cSetAutoDownloadAudio(autoDownloadAudio);
|
||||
if (enabledPrivate || enabledGroups) {
|
||||
const AudiosData &data(App::audiosData());
|
||||
for (AudiosData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||
i.value()->automaticLoadSettingsChanged();
|
||||
const DocumentsData &data(App::documentsData());
|
||||
for (DocumentsData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||
if (i.value()->voice()) {
|
||||
i.value()->automaticLoadSettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
@ -328,7 +330,9 @@ void AutoDownloadBox::onSave() {
|
||||
if (enabledPrivate || enabledGroups) {
|
||||
const DocumentsData &data(App::documentsData());
|
||||
for (DocumentsData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||
i.value()->automaticLoadSettingsChanged();
|
||||
if (i.value()->isAnimation()) {
|
||||
i.value()->automaticLoadSettingsChanged();
|
||||
}
|
||||
}
|
||||
Notify::automaticLoadSettingsChangedGif();
|
||||
}
|
||||
|
@ -118,6 +118,8 @@ enum {
|
||||
AudioVoiceMsgInMemory = 2 * 1024 * 1024, // 2 Mb audio is hold in memory and auto loaded
|
||||
AudioPauseDeviceTimeout = 3000, // pause in 3 secs after playing is over
|
||||
|
||||
WaveformSamplesCount = 100,
|
||||
|
||||
StickerInMemory = 2 * 1024 * 1024, // 2 Mb stickers hold in memory, auto loaded and displayed inline
|
||||
StickerMaxSize = 2048, // 2048x2048 is a max image size for sticker
|
||||
|
||||
|
@ -32,7 +32,7 @@ FileUploader::FileUploader() : sentSize(0) {
|
||||
void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &media) {
|
||||
if (media.type == PreparePhoto) {
|
||||
App::feedPhoto(media.photo, media.photoThumbs);
|
||||
} else if (media.type == PrepareDocument) {
|
||||
} else if (media.type == PrepareDocument || media.type == PrepareAudio) {
|
||||
DocumentData *document;
|
||||
if (media.photoThumbs.isEmpty()) {
|
||||
document = App::feedDocument(media.document);
|
||||
@ -40,13 +40,12 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
|
||||
document = App::feedDocument(media.document, media.photoThumbs.begin().value());
|
||||
}
|
||||
document->status = FileUploading;
|
||||
if (!media.data.isEmpty()) {
|
||||
document->setData(media.data);
|
||||
}
|
||||
if (!media.file.isEmpty()) {
|
||||
document->setLocation(FileLocation(StorageFilePartial, media.file));
|
||||
}
|
||||
} else if (media.type == PrepareAudio) {
|
||||
AudioData *audio = App::feedAudio(media.audio);
|
||||
audio->status = FileUploading;
|
||||
audio->setData(media.data);
|
||||
}
|
||||
queue.insert(msgId, File(media));
|
||||
sendNext();
|
||||
@ -56,7 +55,7 @@ void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file)
|
||||
if (file->type == PreparePhoto) {
|
||||
PhotoData *photo = App::feedPhoto(file->photo, file->photoThumbs);
|
||||
photo->uploadingData = new PhotoData::UploadingData(file->partssize);
|
||||
} else if (file->type == PrepareDocument) {
|
||||
} else if (file->type == PrepareDocument || file->type == PrepareAudio) {
|
||||
DocumentData *document;
|
||||
if (file->thumb.isNull()) {
|
||||
document = App::feedDocument(file->document);
|
||||
@ -64,13 +63,12 @@ void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file)
|
||||
document = App::feedDocument(file->document, file->thumb);
|
||||
}
|
||||
document->status = FileUploading;
|
||||
if (!file->content.isEmpty()) {
|
||||
document->setData(file->content);
|
||||
}
|
||||
if (!file->filepath.isEmpty()) {
|
||||
document->setLocation(FileLocation(StorageFilePartial, file->filepath));
|
||||
}
|
||||
} else if (file->type == PrepareAudio) {
|
||||
AudioData *audio = App::feedAudio(file->audio);
|
||||
audio->status = FileUploading;
|
||||
audio->setData(file->content);
|
||||
}
|
||||
queue.insert(msgId, File(file));
|
||||
sendNext();
|
||||
@ -87,12 +85,6 @@ void FileUploader::currentFailed() {
|
||||
doc->status = FileUploadFailed;
|
||||
}
|
||||
emit documentFailed(j.key());
|
||||
} else if (j->type() == PrepareAudio) {
|
||||
AudioData *audio = App::audio(j->id());
|
||||
if (audio->status == FileUploading) {
|
||||
audio->status = FileUploadFailed;
|
||||
}
|
||||
emit audioFailed(j.key());
|
||||
}
|
||||
queue.erase(j);
|
||||
}
|
||||
@ -133,7 +125,7 @@ void FileUploader::sendNext() {
|
||||
if (!uploading.msg) {
|
||||
uploading = i.key();
|
||||
} else if (i == queue.end()) {
|
||||
i = queue.begin();
|
||||
i = queue.begin();
|
||||
uploading = i.key();
|
||||
}
|
||||
int todc = 0;
|
||||
@ -150,7 +142,7 @@ void FileUploader::sendNext() {
|
||||
if (requestsSent.isEmpty() && docRequestsSent.isEmpty()) {
|
||||
if (i->type() == PreparePhoto) {
|
||||
emit photoReady(uploading, MTP_inputFile(MTP_long(i->id()), MTP_int(i->partsCount), MTP_string(i->filename()), MTP_string(i->file ? i->file->filemd5 : i->media.jpeg_md5)));
|
||||
} else if (i->type() == PrepareDocument) {
|
||||
} else if (i->type() == PrepareDocument || i->type() == PrepareAudio) {
|
||||
QByteArray docMd5(32, Qt::Uninitialized);
|
||||
hashMd5Hex(i->md5Hash.result(), docMd5.data());
|
||||
|
||||
@ -160,12 +152,6 @@ void FileUploader::sendNext() {
|
||||
} else {
|
||||
emit documentReady(uploading, doc);
|
||||
}
|
||||
} else if (i->type() == PrepareAudio) {
|
||||
QByteArray audioMd5(32, Qt::Uninitialized);
|
||||
hashMd5Hex(i->md5Hash.result(), audioMd5.data());
|
||||
|
||||
MTPInputFile audio = (i->docSize > UseBigFilesFrom) ? MTP_inputFileBig(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename())) : MTP_inputFile(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename()), MTP_string(audioMd5));
|
||||
emit audioReady(uploading, audio);
|
||||
}
|
||||
queue.remove(uploading);
|
||||
uploading = FullMsgId();
|
||||
@ -212,7 +198,7 @@ void FileUploader::sendNext() {
|
||||
i->docSentParts++;
|
||||
} else {
|
||||
UploadFileParts::iterator part = parts.begin();
|
||||
|
||||
|
||||
mtpRequestId requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(partsOfId), MTP_int(part.key()), MTP_string(part.value())), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
requestsSent.insert(requestId, part.value());
|
||||
dcMap.insert(requestId, todc);
|
||||
@ -303,7 +289,7 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
||||
photo->uploadingData->offset = k->fileSentSize;
|
||||
}
|
||||
emit photoProgress(k.key());
|
||||
} else if (k->type() == PrepareDocument) {
|
||||
} else if (k->type() == PrepareDocument || k->type() == PrepareAudio) {
|
||||
DocumentData *doc = App::document(k->id());
|
||||
if (doc->uploading()) {
|
||||
doc->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
||||
@ -312,15 +298,6 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
||||
}
|
||||
}
|
||||
emit documentProgress(k.key());
|
||||
} else if (k->type() == PrepareAudio) {
|
||||
AudioData *audio = App::audio(k->id());
|
||||
if (audio->uploading()) {
|
||||
audio->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
||||
if (audio->uploadOffset > audio->size) {
|
||||
audio->uploadOffset = audio->size;
|
||||
}
|
||||
}
|
||||
emit audioProgress(k.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,15 +51,12 @@ signals:
|
||||
void photoReady(const FullMsgId &msgId, const MTPInputFile &file);
|
||||
void documentReady(const FullMsgId &msgId, const MTPInputFile &file);
|
||||
void thumbDocumentReady(const FullMsgId &msgId, const MTPInputFile &file, const MTPInputFile &thumb);
|
||||
void audioReady(const FullMsgId &msgId, const MTPInputFile &file);
|
||||
|
||||
void photoProgress(const FullMsgId &msgId);
|
||||
void documentProgress(const FullMsgId &msgId);
|
||||
void audioProgress(const FullMsgId &msgId);
|
||||
|
||||
void photoFailed(const FullMsgId &msgId);
|
||||
void documentFailed(const FullMsgId &msgId);
|
||||
void audioFailed(const FullMsgId &msgId);
|
||||
|
||||
private:
|
||||
|
||||
@ -138,7 +135,7 @@ private:
|
||||
QMap<mtpRequestId, int32> dcMap;
|
||||
uint32 sentSize;
|
||||
uint32 sentSizes[MTPUploadSessionsCount];
|
||||
|
||||
|
||||
FullMsgId uploading, _paused;
|
||||
Queue queue;
|
||||
Queue uploaded;
|
||||
|
@ -352,8 +352,8 @@ bool History::updateTyping(uint64 ms, bool force) {
|
||||
switch (sendActions.begin().value().type) {
|
||||
case SendActionRecordVideo: newTypingStr = peer->isUser() ? lang(lng_send_action_record_video) : lng_user_action_record_video(lt_user, sendActions.begin().key()->firstName); break;
|
||||
case SendActionUploadVideo: newTypingStr = peer->isUser() ? lang(lng_send_action_upload_video) : lng_user_action_upload_video(lt_user, sendActions.begin().key()->firstName); break;
|
||||
case SendActionRecordAudio: newTypingStr = peer->isUser() ? lang(lng_send_action_record_audio) : lng_user_action_record_audio(lt_user, sendActions.begin().key()->firstName); break;
|
||||
case SendActionUploadAudio: newTypingStr = peer->isUser() ? lang(lng_send_action_upload_audio) : lng_user_action_upload_audio(lt_user, sendActions.begin().key()->firstName); break;
|
||||
case SendActionRecordVoice: newTypingStr = peer->isUser() ? lang(lng_send_action_record_audio) : lng_user_action_record_audio(lt_user, sendActions.begin().key()->firstName); break;
|
||||
case SendActionUploadVoice: newTypingStr = peer->isUser() ? lang(lng_send_action_upload_audio) : lng_user_action_upload_audio(lt_user, sendActions.begin().key()->firstName); break;
|
||||
case SendActionUploadPhoto: newTypingStr = peer->isUser() ? lang(lng_send_action_upload_photo) : lng_user_action_upload_photo(lt_user, sendActions.begin().key()->firstName); break;
|
||||
case SendActionUploadFile: newTypingStr = peer->isUser() ? lang(lng_send_action_upload_file) : lng_user_action_upload_file(lt_user, sendActions.begin().key()->firstName); break;
|
||||
case SendActionChooseLocation: newTypingStr = peer->isUser() ? lang(lng_send_action_geo_location) : lng_user_action_geo_location(lt_user, sendActions.begin().key()->firstName); break;
|
||||
@ -1249,8 +1249,8 @@ void Histories::regSendAction(History *history, UserData *user, const MTPSendMes
|
||||
case mtpc_sendMessageTypingAction: history->typing[user] = ms + 6000; break;
|
||||
case mtpc_sendMessageRecordVideoAction: history->sendActions.insert(user, SendAction(SendActionRecordVideo, ms + 6000)); break;
|
||||
case mtpc_sendMessageUploadVideoAction: history->sendActions.insert(user, SendAction(SendActionUploadVideo, ms + 6000, action.c_sendMessageUploadVideoAction().vprogress.v)); break;
|
||||
case mtpc_sendMessageRecordAudioAction: history->sendActions.insert(user, SendAction(SendActionRecordAudio, ms + 6000)); break;
|
||||
case mtpc_sendMessageUploadAudioAction: history->sendActions.insert(user, SendAction(SendActionUploadAudio, ms + 6000, action.c_sendMessageUploadAudioAction().vprogress.v)); break;
|
||||
case mtpc_sendMessageRecordAudioAction: history->sendActions.insert(user, SendAction(SendActionRecordVoice, ms + 6000)); break;
|
||||
case mtpc_sendMessageUploadAudioAction: history->sendActions.insert(user, SendAction(SendActionUploadVoice, ms + 6000, action.c_sendMessageUploadAudioAction().vprogress.v)); break;
|
||||
case mtpc_sendMessageUploadPhotoAction: history->sendActions.insert(user, SendAction(SendActionUploadPhoto, ms + 6000, action.c_sendMessageUploadPhotoAction().vprogress.v)); break;
|
||||
case mtpc_sendMessageUploadDocumentAction: history->sendActions.insert(user, SendAction(SendActionUploadFile, ms + 6000, action.c_sendMessageUploadDocumentAction().vprogress.v)); break;
|
||||
case mtpc_sendMessageGeoLocationAction: history->sendActions.insert(user, SendAction(SendActionChooseLocation, ms + 6000)); break;
|
||||
@ -1369,13 +1369,6 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo
|
||||
default: badMedia = 1; break;
|
||||
}
|
||||
break;
|
||||
case mtpc_messageMediaAudio:
|
||||
switch (m.vmedia.c_messageMediaAudio().vaudio.type()) {
|
||||
case mtpc_audio: break;
|
||||
case mtpc_audioEmpty: badMedia = 2; break;
|
||||
default: badMedia = 1; break;
|
||||
}
|
||||
break;
|
||||
case mtpc_messageMediaDocument:
|
||||
switch (m.vmedia.c_messageMediaDocument().vdocument.type()) {
|
||||
case mtpc_document: break;
|
||||
@ -3060,18 +3053,14 @@ namespace {
|
||||
return result;
|
||||
}
|
||||
|
||||
int32 audioMaxStatusWidth(AudioData *audio) {
|
||||
int32 result = st::normalFont->width(formatDownloadText(audio->size, audio->size));
|
||||
result = qMax(result, st::normalFont->width(formatPlayedText(audio->duration, audio->duration)));
|
||||
result = qMax(result, st::normalFont->width(formatDurationAndSizeText(audio->duration, audio->size)));
|
||||
return result;
|
||||
}
|
||||
|
||||
int32 documentMaxStatusWidth(DocumentData *document) {
|
||||
int32 result = st::normalFont->width(formatDownloadText(document->size, document->size));
|
||||
if (SongData *song = document->song()) {
|
||||
result = qMax(result, st::normalFont->width(formatPlayedText(song->duration, song->duration)));
|
||||
result = qMax(result, st::normalFont->width(formatDurationAndSizeText(song->duration, document->size)));
|
||||
} else if (VoiceData *voice = document->voice()) {
|
||||
result = qMax(result, st::normalFont->width(formatPlayedText(voice->duration, voice->duration)));
|
||||
result = qMax(result, st::normalFont->width(formatDurationAndSizeText(voice->duration, document->size)));
|
||||
} else {
|
||||
result = qMax(result, st::normalFont->width(formatSizeText(document->size)));
|
||||
}
|
||||
@ -3785,291 +3774,151 @@ ImagePtr HistoryVideo::replyPreview() {
|
||||
return _data->replyPreview;
|
||||
}
|
||||
|
||||
HistoryAudio::HistoryAudio(const MTPDaudio &audio) : HistoryFileMedia()
|
||||
, _data(App::feedAudio(audio)) {
|
||||
setLinks(new AudioOpenLink(_data), new AudioOpenLink(_data), new AudioCancelLink(_data));
|
||||
|
||||
setStatusSize(FileStatusSizeReady);
|
||||
HistoryDocumentVoicePlayback::HistoryDocumentVoicePlayback(const HistoryDocument *that)
|
||||
: _position(0)
|
||||
, a_progress(0., 0.)
|
||||
, _a_progress(animation(const_cast<HistoryDocument*>(that), &HistoryDocument::step_voiceProgress)) {
|
||||
}
|
||||
|
||||
HistoryAudio::HistoryAudio(const HistoryAudio &other) : HistoryFileMedia()
|
||||
, _data(other._data) {
|
||||
setLinks(new AudioOpenLink(_data), new AudioOpenLink(_data), new AudioCancelLink(_data));
|
||||
|
||||
setStatusSize(other._statusSize);
|
||||
}
|
||||
|
||||
void HistoryAudio::initDimensions(const HistoryItem *parent) {
|
||||
_maxw = st::msgFileMinWidth;
|
||||
|
||||
int32 tleft = 0, tright = 0;
|
||||
|
||||
tleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right();
|
||||
tright = st::msgFileThumbPadding.left();
|
||||
_maxw = qMax(_maxw, tleft + audioMaxStatusWidth(_data) + int(st::mediaUnreadSkip + st::mediaUnreadSize) + parent->skipBlockWidth() + st::msgPadding.right());
|
||||
|
||||
_maxw = qMax(tleft + st::semiboldFont->width(lang(lng_media_audio)) + tright, _maxw);
|
||||
_maxw = qMin(_maxw, int(st::msgMaxWidth));
|
||||
|
||||
_height = _minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom();
|
||||
}
|
||||
|
||||
void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
|
||||
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||
|
||||
_data->automaticLoad(parent);
|
||||
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
|
||||
|
||||
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
|
||||
|
||||
if (displayLoading) {
|
||||
ensureAnimation(parent);
|
||||
if (!_animation->radial.animating()) {
|
||||
_animation->radial.start(_data->progress());
|
||||
}
|
||||
}
|
||||
bool showPause = updateStatusText(parent);
|
||||
bool radial = isRadialAnimation(ms);
|
||||
|
||||
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0;
|
||||
|
||||
nameleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right();
|
||||
nametop = st::msgFileNameTop;
|
||||
nameright = st::msgFilePadding.left();
|
||||
statustop = st::msgFileStatusTop;
|
||||
|
||||
QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width));
|
||||
p.setPen(Qt::NoPen);
|
||||
if (selected) {
|
||||
p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected);
|
||||
} else if (isThumbAnimation(ms)) {
|
||||
float64 over = _animation->a_thumbOver.current();
|
||||
p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over));
|
||||
} else {
|
||||
bool over = textlnkDrawOver(_data->loading() ? _cancell : _savel);
|
||||
p.setBrush(outbg ? (over ? st::msgFileOutBgOver : st::msgFileOutBg) : (over ? st::msgFileInBgOver : st::msgFileInBg));
|
||||
}
|
||||
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||
p.drawEllipse(inner);
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||
|
||||
if (radial) {
|
||||
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
||||
style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg));
|
||||
_animation->radial.draw(p, rinner, st::msgFileRadialLine, bg);
|
||||
}
|
||||
|
||||
style::sprite icon;
|
||||
if (showPause) {
|
||||
icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause);
|
||||
} else if (radial || _data->loading()) {
|
||||
icon = outbg ? (selected ? st::msgFileOutCancelSelected : st::msgFileOutCancel) : (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
|
||||
} else if (loaded) {
|
||||
icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
|
||||
} else {
|
||||
icon = outbg ? (selected ? st::msgFileOutDownloadSelected : st::msgFileOutDownload) : (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
|
||||
}
|
||||
p.drawSpriteCenter(inner, icon);
|
||||
|
||||
int32 namewidth = _width - nameleft - nameright;
|
||||
|
||||
p.setFont(st::semiboldFont);
|
||||
p.setPen(st::black);
|
||||
p.drawTextLeft(nameleft, nametop, _width, lang(lng_media_audio));
|
||||
|
||||
style::color status(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg));
|
||||
p.setFont(st::normalFont);
|
||||
p.setPen(status);
|
||||
p.drawTextLeft(nameleft, statustop, _width, _statusText);
|
||||
|
||||
if (parent->isMediaUnread()) {
|
||||
int32 w = st::normalFont->width(_statusText);
|
||||
if (w + st::mediaUnreadSkip + st::mediaUnreadSize <= namewidth) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(outbg ? (selected ? st::msgFileOutBgSelected : st::msgFileOutBg) : (selected ? st::msgFileInBgSelected : st::msgFileInBg));
|
||||
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing, true);
|
||||
p.drawEllipse(rtlrect(nameleft + w + st::mediaUnreadSkip, statustop + st::mediaUnreadTop, st::mediaUnreadSize, st::mediaUnreadSize, _width));
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||
}
|
||||
void HistoryDocumentVoice::ensurePlayback(const HistoryDocument *that) const {
|
||||
if (!_playback) {
|
||||
_playback = new HistoryDocumentVoicePlayback(that);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryAudio::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const {
|
||||
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||
|
||||
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
|
||||
bool loaded = _data->loaded();
|
||||
|
||||
bool showPause = updateStatusText(parent);
|
||||
|
||||
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0;
|
||||
|
||||
QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width));
|
||||
if ((_data->loading() || _data->status == FileUploading || !loaded) && inner.contains(x, y)) {
|
||||
lnk = (_data->loading() || _data->status == FileUploading) ? _cancell : _savel;
|
||||
return;
|
||||
void HistoryDocumentVoice::checkPlaybackFinished() const {
|
||||
if (_playback && !_playback->_a_progress.animating()) {
|
||||
delete _playback;
|
||||
_playback = 0;
|
||||
}
|
||||
|
||||
if (x >= 0 && y >= 0 && x < _width && y < _height && _data->access && !_data->loading()) {
|
||||
lnk = _openl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const QString HistoryAudio::inDialogsText() const {
|
||||
return lang(lng_in_dlg_audio);
|
||||
}
|
||||
|
||||
const QString HistoryAudio::inHistoryText() const {
|
||||
return qsl("[ ") + lang(lng_in_dlg_audio) + qsl(" ]");
|
||||
}
|
||||
|
||||
void HistoryAudio::regItem(HistoryItem *item) {
|
||||
App::regAudioItem(_data, item);
|
||||
}
|
||||
|
||||
void HistoryAudio::unregItem(HistoryItem *item) {
|
||||
App::unregAudioItem(_data, item);
|
||||
}
|
||||
|
||||
void HistoryAudio::updateFrom(const MTPMessageMedia &media, HistoryItem *parent) {
|
||||
if (media.type() == mtpc_messageMediaAudio) {
|
||||
App::feedAudio(media.c_messageMediaAudio().vaudio, _data);
|
||||
if (!_data->data().isEmpty()) {
|
||||
Local::writeAudio(mediaKey(AudioFileLocation, _data->dc, _data->id), _data->data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryAudio::setStatusSize(int32 newSize, qint64 realDuration) const {
|
||||
HistoryFileMedia::setStatusSize(newSize, _data->size, _data->duration, realDuration);
|
||||
}
|
||||
|
||||
bool HistoryAudio::updateStatusText(const HistoryItem *parent) const {
|
||||
bool showPause = false;
|
||||
int32 statusSize = 0, realDuration = 0;
|
||||
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
|
||||
statusSize = FileStatusSizeFailed;
|
||||
} else if (_data->status == FileUploading) {
|
||||
statusSize = _data->uploadOffset;
|
||||
} else if (_data->loading()) {
|
||||
statusSize = _data->loadOffset();
|
||||
} else if (_data->loaded()) {
|
||||
AudioMsgId playing;
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
int64 playingPosition = 0, playingDuration = 0;
|
||||
int32 playingFrequency = 0;
|
||||
if (audioPlayer()) {
|
||||
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
|
||||
}
|
||||
|
||||
if (playing.msgId == 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;
|
||||
}
|
||||
} else {
|
||||
statusSize = FileStatusSizeReady;
|
||||
}
|
||||
if (statusSize != _statusSize) {
|
||||
setStatusSize(statusSize, realDuration);
|
||||
}
|
||||
return showPause;
|
||||
}
|
||||
|
||||
HistoryDocument::HistoryDocument(DocumentData *document, const QString &caption, const HistoryItem *parent) : HistoryFileMedia()
|
||||
, _data(document)
|
||||
, _linksavel(new DocumentSaveLink(_data))
|
||||
, _linkcancell(new DocumentCancelLink(_data))
|
||||
, _name(documentName(_data))
|
||||
, _namew(st::semiboldFont->width(_name))
|
||||
, _caption(st::msgFileMinWidth - st::msgPadding.left() - st::msgPadding.right()) {
|
||||
setLinks(new DocumentOpenLink(_data), new DocumentSaveLink(_data), new DocumentCancelLink(_data));
|
||||
, _parent(0)
|
||||
, _data(document) {
|
||||
create(!caption.isEmpty());
|
||||
if (HistoryDocumentNamed *named = Get<HistoryDocumentNamed>()) {
|
||||
named->_name = documentName(_data);
|
||||
named->_namew = st::semiboldFont->width(named->_name);
|
||||
}
|
||||
|
||||
setLinks(new DocumentOpenLink(_data), _data->voice() ? (ITextLink*)(new VoiceSaveLink(_data)) : new DocumentSaveLink(_data), new DocumentCancelLink(_data));
|
||||
|
||||
setStatusSize(FileStatusSizeReady);
|
||||
|
||||
if (!caption.isEmpty()) {
|
||||
_caption.setText(st::msgFont, caption + parent->skipBlock(), itemTextNoMonoOptions(parent));
|
||||
if (HistoryDocumentCaptioned *captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
captioned->_caption.setText(st::msgFont, caption + parent->skipBlock(), itemTextNoMonoOptions(parent));
|
||||
}
|
||||
}
|
||||
|
||||
HistoryDocument::HistoryDocument(const HistoryDocument &other) : HistoryFileMedia()
|
||||
, _data(other._data)
|
||||
, _linksavel(new DocumentSaveLink(_data))
|
||||
, _linkcancell(new DocumentCancelLink(_data))
|
||||
, _name(other._name)
|
||||
, _namew(other._namew)
|
||||
, _thumbw(other._thumbw)
|
||||
, _caption(other._caption) {
|
||||
setLinks(new DocumentOpenLink(_data), new DocumentSaveLink(_data), new DocumentCancelLink(_data));
|
||||
, _parent(0)
|
||||
, _data(other._data) {
|
||||
const HistoryDocumentCaptioned *captioned = other.Get<HistoryDocumentCaptioned>();
|
||||
create(captioned != 0);
|
||||
if (HistoryDocumentNamed *named = Get<HistoryDocumentNamed>()) {
|
||||
if (const HistoryDocumentNamed *oin = other.Get<HistoryDocumentNamed>()) {
|
||||
named->_name = oin->_name;
|
||||
named->_namew = oin->_namew;
|
||||
} else {
|
||||
named->_name = documentName(_data);
|
||||
named->_namew = st::semiboldFont->width(named->_name);
|
||||
}
|
||||
}
|
||||
|
||||
setLinks(new DocumentOpenLink(_data), _data->voice() ? (ITextLink*)(new VoiceSaveLink(_data)) : new DocumentSaveLink(_data), new DocumentCancelLink(_data));
|
||||
|
||||
setStatusSize(other._statusSize);
|
||||
|
||||
if (captioned) {
|
||||
Get<HistoryDocumentCaptioned>()->_caption = captioned->_caption;
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryDocument::create(bool caption) {
|
||||
uint64 mask;
|
||||
if (_data->voice()) {
|
||||
mask = HistoryDocumentVoice::Bit();
|
||||
} else {
|
||||
mask = HistoryDocumentNamed::Bit();
|
||||
if (caption) {
|
||||
mask |= HistoryDocumentCaptioned::Bit();
|
||||
}
|
||||
if (!_data->song() && !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height()) {
|
||||
mask |= HistoryDocumentThumbed::Bit();
|
||||
}
|
||||
}
|
||||
UpdateInterfaces(mask);
|
||||
if (HistoryDocumentThumbed *thumbed = Get<HistoryDocumentThumbed>()) {
|
||||
thumbed->_linksavel.reset(new DocumentSaveLink(_data));
|
||||
thumbed->_linkcancell.reset(new DocumentCancelLink(_data));
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryDocument::initDimensions(const HistoryItem *parent) {
|
||||
if (_caption.hasSkipBlock()) {
|
||||
_caption.setSkipBlock(parent->skipBlockWidth(), parent->skipBlockHeight());
|
||||
_parent = parent;
|
||||
|
||||
HistoryDocumentCaptioned *captioned = Get<HistoryDocumentCaptioned>();
|
||||
if (captioned && captioned->_caption.hasSkipBlock()) {
|
||||
captioned->_caption.setSkipBlock(parent->skipBlockWidth(), parent->skipBlockHeight());
|
||||
}
|
||||
|
||||
if (withThumb()) {
|
||||
HistoryDocumentThumbed *thumbed = Get<HistoryDocumentThumbed>();
|
||||
if (thumbed) {
|
||||
_data->thumb->load();
|
||||
int32 tw = _data->thumb->width(), th = _data->thumb->height();
|
||||
if (tw > th) {
|
||||
_thumbw = (tw * st::msgFileThumbSize) / th;
|
||||
thumbed->_thumbw = (tw * st::msgFileThumbSize) / th;
|
||||
} else {
|
||||
_thumbw = st::msgFileThumbSize;
|
||||
thumbed->_thumbw = st::msgFileThumbSize;
|
||||
}
|
||||
} else {
|
||||
_thumbw = 0;
|
||||
}
|
||||
|
||||
_maxw = st::msgFileMinWidth;
|
||||
|
||||
int32 tleft = 0, tright = 0;
|
||||
bool wthumb = withThumb();
|
||||
if (wthumb) {
|
||||
if (thumbed) {
|
||||
tleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right();
|
||||
tright = st::msgFileThumbPadding.left();
|
||||
_maxw = qMax(_maxw, tleft + documentMaxStatusWidth(_data) + tright);
|
||||
} else {
|
||||
tleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right();
|
||||
tright = st::msgFileThumbPadding.left();
|
||||
_maxw = qMax(_maxw, tleft + documentMaxStatusWidth(_data) + parent->skipBlockWidth() + st::msgPadding.right());
|
||||
int32 unread = _data->voice() ? (st::mediaUnreadSkip + st::mediaUnreadSize) : 0;
|
||||
_maxw = qMax(_maxw, tleft + documentMaxStatusWidth(_data) + unread + parent->skipBlockWidth() + st::msgPadding.right());
|
||||
}
|
||||
|
||||
_maxw = qMax(tleft + _namew + tright, _maxw);
|
||||
_maxw = qMin(_maxw, int(st::msgMaxWidth));
|
||||
if (HistoryDocumentNamed *named = Get<HistoryDocumentNamed>()) {
|
||||
_maxw = qMax(tleft + named->_namew + tright, _maxw);
|
||||
_maxw = qMin(_maxw, int(st::msgMaxWidth));
|
||||
}
|
||||
|
||||
if (wthumb) {
|
||||
if (thumbed) {
|
||||
_minh = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
|
||||
} else {
|
||||
_minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom();
|
||||
}
|
||||
|
||||
if (_caption.isEmpty()) {
|
||||
_height = _minh;
|
||||
if (captioned) {
|
||||
_minh += captioned->_caption.countHeight(_maxw - st::msgPadding.left() - st::msgPadding.right()) + st::msgPadding.bottom();
|
||||
} else {
|
||||
_minh += _caption.countHeight(_maxw - st::msgPadding.left() - st::msgPadding.right()) + st::msgPadding.bottom();
|
||||
_height = _minh;
|
||||
}
|
||||
}
|
||||
|
||||
int32 HistoryDocument::resize(int32 width, const HistoryItem *parent) {
|
||||
if (_caption.isEmpty()) {
|
||||
HistoryDocumentCaptioned *captioned = Get<HistoryDocumentCaptioned>();
|
||||
if (!captioned) {
|
||||
return HistoryFileMedia::resize(width, parent);
|
||||
}
|
||||
|
||||
_width = qMin(width, _maxw);
|
||||
bool wthumb = withThumb();
|
||||
if (wthumb) {
|
||||
if (Get<HistoryDocumentThumbed>()) {
|
||||
_height = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
|
||||
} else {
|
||||
_height = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom();
|
||||
}
|
||||
_height += _caption.countHeight(_width - st::msgPadding.left() - st::msgPadding.right()) + st::msgPadding.bottom();
|
||||
_height += captioned->_caption.countHeight(_width - st::msgPadding.left() - st::msgPadding.right()) + st::msgPadding.bottom();
|
||||
|
||||
return _height;
|
||||
}
|
||||
@ -4094,8 +3943,7 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
|
||||
bool radial = isRadialAnimation(ms);
|
||||
|
||||
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0, bottom = 0;
|
||||
bool wthumb = withThumb();
|
||||
if (wthumb) {
|
||||
if (const HistoryDocumentThumbed *thumbed = Get<HistoryDocumentThumbed>()) {
|
||||
nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right();
|
||||
nametop = st::msgFileThumbNameTop;
|
||||
nameright = st::msgFileThumbPadding.left();
|
||||
@ -4104,7 +3952,7 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
|
||||
bottom = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
|
||||
|
||||
QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width));
|
||||
QPixmap thumb = loaded ? _data->thumb->pixSingle(_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize) : _data->thumb->pixBlurredSingle(_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize);
|
||||
QPixmap thumb = loaded ? _data->thumb->pixSingle(thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize) : _data->thumb->pixBlurredSingle(thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize);
|
||||
p.drawPixmap(rthumb.topLeft(), thumb);
|
||||
if (selected) {
|
||||
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
|
||||
@ -4148,11 +3996,11 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
|
||||
}
|
||||
|
||||
if (_data->status != FileUploadFailed) {
|
||||
const TextLinkPtr &lnk((_data->loading() || _data->status == FileUploading) ? _linkcancell : _linksavel);
|
||||
const TextLinkPtr &lnk((_data->loading() || _data->status == FileUploading) ? thumbed->_linkcancell : thumbed->_linksavel);
|
||||
bool over = textlnkDrawOver(lnk);
|
||||
p.setFont(over ? st::semiboldFont->underline() : st::semiboldFont);
|
||||
p.setPen(outbg ? (selected ? st::msgFileThumbLinkOutFgSelected : st::msgFileThumbLinkOutFg) : (selected ? st::msgFileThumbLinkInFgSelected : st::msgFileThumbLinkInFg));
|
||||
p.drawTextLeft(nameleft, linktop, _width, _link, _linkw);
|
||||
p.drawTextLeft(nameleft, linktop, _width, thumbed->_link, thumbed->_linkw);
|
||||
}
|
||||
} else {
|
||||
nameleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right();
|
||||
@ -4189,7 +4037,7 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
|
||||
} else if (radial || _data->loading()) {
|
||||
icon = outbg ? (selected ? st::msgFileOutCancelSelected : st::msgFileOutCancel) : (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
|
||||
} else if (loaded) {
|
||||
if (_data->song()) {
|
||||
if (_data->song() || _data->voice()) {
|
||||
icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
|
||||
} else if (_data->isImage()) {
|
||||
icon = outbg ? (selected ? st::msgFileOutImageSelected : st::msgFileOutImage) : (selected ? st::msgFileInImageSelected : st::msgFileInImage);
|
||||
@ -4203,12 +4051,70 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
|
||||
}
|
||||
int32 namewidth = _width - nameleft - nameright;
|
||||
|
||||
p.setFont(st::semiboldFont);
|
||||
p.setPen(st::black);
|
||||
if (namewidth < _namew) {
|
||||
p.drawTextLeft(nameleft, nametop, _width, st::semiboldFont->elided(_name, namewidth));
|
||||
} else {
|
||||
p.drawTextLeft(nameleft, nametop, _width, _name, _namew);
|
||||
if (const HistoryDocumentVoice *voice = Get<HistoryDocumentVoice>()) {
|
||||
const VoiceWaveform *wf = 0;
|
||||
uchar norm_value = 0;
|
||||
if (_data->voice()) {
|
||||
wf = &_data->voice()->waveform;
|
||||
if (wf->isEmpty()) {
|
||||
wf = 0;
|
||||
if (loaded) {
|
||||
Local::countVoiceWaveform(_data);
|
||||
}
|
||||
} else if (wf->at(0) < 0) {
|
||||
wf = 0;
|
||||
} else {
|
||||
norm_value = _data->voice()->wavemax;
|
||||
}
|
||||
}
|
||||
float64 prg = voice->_playback ? voice->_playback->a_progress.current() : 0;
|
||||
|
||||
// rescale waveform by going in waveform.size * bar_count 1D grid
|
||||
style::color active(outbg ? st::msgWaveformOutActive : st::msgWaveformInActive);
|
||||
style::color inactive(outbg ? st::msgWaveformOutInactive : st::msgWaveformInInactive);
|
||||
int32 wf_size = wf ? wf->size() : WaveformSamplesCount, availw = int32(namewidth + st::msgWaveformSkip), activew = qRound(availw * prg);
|
||||
int32 bar_count = qMin(availw / int32(st::msgWaveformBar + st::msgWaveformSkip), wf_size);
|
||||
uchar max_value = 0;
|
||||
int32 max_delta = st::msgWaveformMax - st::msgWaveformMin, bottom = st::msgFilePadding.top() + st::msgWaveformMax;
|
||||
p.setPen(Qt::NoPen);
|
||||
for (uint32 i = 0, bar_x = 0, sum_i = 0; i < wf_size; ++i) {
|
||||
uchar value = wf ? wf->at(i) : 0;
|
||||
if (sum_i + bar_count >= wf_size) { // draw bar
|
||||
sum_i = sum_i + bar_count - wf_size;
|
||||
if (sum_i < (bar_count + 1) / 2) {
|
||||
if (max_value < value) max_value = value;
|
||||
}
|
||||
int32 bar_value = ((max_value * max_delta) + ((norm_value + 1) / 2)) / (norm_value + 1);
|
||||
|
||||
if (bar_x >= activew) {
|
||||
p.fillRect(nameleft + bar_x, bottom - bar_value, st::msgWaveformBar, st::msgWaveformMin + bar_value, inactive);
|
||||
} else if (bar_x + st::msgWaveformBar <= activew) {
|
||||
p.fillRect(nameleft + bar_x, bottom - bar_value, st::msgWaveformBar, st::msgWaveformMin + bar_value, active);
|
||||
} else {
|
||||
p.fillRect(nameleft + bar_x, bottom - bar_value, activew - bar_x, st::msgWaveformMin + bar_value, active);
|
||||
p.fillRect(nameleft + activew, bottom - bar_value, st::msgWaveformBar - (activew - bar_x), st::msgWaveformMin + bar_value, inactive);
|
||||
}
|
||||
bar_x += st::msgWaveformBar + st::msgWaveformSkip;
|
||||
|
||||
if (sum_i < (bar_count + 1) / 2) {
|
||||
max_value = 0;
|
||||
} else {
|
||||
max_value = value;
|
||||
}
|
||||
} else {
|
||||
if (max_value < value) max_value = value;
|
||||
|
||||
sum_i += bar_count;
|
||||
}
|
||||
}
|
||||
} else if (const HistoryDocumentNamed *named = Get<HistoryDocumentNamed>()) {
|
||||
p.setFont(st::semiboldFont);
|
||||
p.setPen(st::black);
|
||||
if (namewidth < named->_namew) {
|
||||
p.drawTextLeft(nameleft, nametop, _width, st::semiboldFont->elided(named->_name, namewidth));
|
||||
} else {
|
||||
p.drawTextLeft(nameleft, nametop, _width, named->_name, named->_namew);
|
||||
}
|
||||
}
|
||||
|
||||
style::color status(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg));
|
||||
@ -4216,9 +4122,21 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
|
||||
p.setPen(status);
|
||||
p.drawTextLeft(nameleft, statustop, _width, _statusText);
|
||||
|
||||
if (!_caption.isEmpty()) {
|
||||
if (parent->isMediaUnread()) {
|
||||
int32 w = st::normalFont->width(_statusText);
|
||||
if (w + st::mediaUnreadSkip + st::mediaUnreadSize <= namewidth) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(outbg ? (selected ? st::msgFileOutBgSelected : st::msgFileOutBg) : (selected ? st::msgFileInBgSelected : st::msgFileInBg));
|
||||
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing, true);
|
||||
p.drawEllipse(rtlrect(nameleft + w + st::mediaUnreadSkip, statustop + st::mediaUnreadTop, st::mediaUnreadSize, st::mediaUnreadSize, _width));
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (const HistoryDocumentCaptioned *captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
p.setPen(st::black);
|
||||
_caption.draw(p, st::msgPadding.left(), bottom, captionw);
|
||||
captioned->_caption.draw(p, st::msgPadding.left(), bottom, captionw);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4231,8 +4149,7 @@ void HistoryDocument::getState(TextLinkPtr &lnk, HistoryCursorState &state, int3
|
||||
bool showPause = updateStatusText(parent);
|
||||
|
||||
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0, bottom = 0;
|
||||
bool wthumb = withThumb();
|
||||
if (wthumb) {
|
||||
if (const HistoryDocumentThumbed *thumbed = Get<HistoryDocumentThumbed>()) {
|
||||
nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right();
|
||||
linktop = st::msgFileThumbLinkTop;
|
||||
bottom = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
|
||||
@ -4245,8 +4162,8 @@ void HistoryDocument::getState(TextLinkPtr &lnk, HistoryCursorState &state, int3
|
||||
}
|
||||
|
||||
if (_data->status != FileUploadFailed) {
|
||||
if (rtlrect(nameleft, linktop, _linkw, st::semiboldFont->height, _width).contains(x, y)) {
|
||||
lnk = (_data->loading() || _data->uploading()) ? _linkcancell : _linksavel;
|
||||
if (rtlrect(nameleft, linktop, thumbed->_linkw, st::semiboldFont->height, _width).contains(x, y)) {
|
||||
lnk = (_data->loading() || _data->uploading()) ? thumbed->_linkcancell : thumbed->_linksavel;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -4261,14 +4178,14 @@ void HistoryDocument::getState(TextLinkPtr &lnk, HistoryCursorState &state, int3
|
||||
}
|
||||
|
||||
int32 height = _height;
|
||||
if (!_caption.isEmpty()) {
|
||||
if (const HistoryDocumentCaptioned *captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
if (y >= bottom) {
|
||||
bool inText = false;
|
||||
_caption.getState(lnk, inText, x - st::msgPadding.left(), y - bottom, _width - st::msgPadding.left() - st::msgPadding.right());
|
||||
captioned->_caption.getState(lnk, inText, x - st::msgPadding.left(), y - bottom, _width - st::msgPadding.left() - st::msgPadding.right());
|
||||
state = inText ? HistoryInTextCursorState : HistoryDefaultCursorState;
|
||||
return;
|
||||
}
|
||||
height -= _caption.countHeight(_width - st::msgPadding.left() - st::msgPadding.right()) + st::msgPadding.bottom();
|
||||
height -= captioned->_caption.countHeight(_width - st::msgPadding.left() - st::msgPadding.right()) + st::msgPadding.bottom();
|
||||
}
|
||||
if (x >= 0 && y >= 0 && x < _width && y < height && !_data->loading() && !_data->uploading() && _data->access) {
|
||||
lnk = _openl;
|
||||
@ -4277,28 +4194,53 @@ void HistoryDocument::getState(TextLinkPtr &lnk, HistoryCursorState &state, int3
|
||||
}
|
||||
|
||||
const QString HistoryDocument::inDialogsText() const {
|
||||
return (_name.isEmpty() ? lang(lng_in_dlg_file) : _name) + (_caption.isEmpty() ? QString() : (' ' + _caption.original(0, 0xFFFF, Text::ExpandLinksNone)));
|
||||
QString result;
|
||||
if (Get<HistoryDocumentVoice>()) {
|
||||
result = lang(lng_in_dlg_audio);
|
||||
} else {
|
||||
const HistoryDocumentNamed *named = Get<HistoryDocumentNamed>();
|
||||
result = (!named || named->_name.isEmpty()) ? lang(lng_in_dlg_file) : named->_name;
|
||||
}
|
||||
if (const HistoryDocumentCaptioned *captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
if (!captioned->_caption.isEmpty()) {
|
||||
result.append(' ').append(captioned->_caption.original(0, 0xFFFF, Text::ExpandLinksNone));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const QString HistoryDocument::inHistoryText() const {
|
||||
return qsl("[ ") + lang(lng_in_dlg_file) + (_name.isEmpty() ? QString() : (qsl(" : ") + _name)) + (_caption.isEmpty() ? QString() : (qsl(", ") + _caption.original(0, 0xFFFF, Text::ExpandLinksAll))) + qsl(" ]");
|
||||
QString result = qsl("[ ") + lang(Get<HistoryDocumentVoice>() ? lng_in_dlg_audio : lng_in_dlg_file);
|
||||
if (const HistoryDocumentNamed *named = Get<HistoryDocumentNamed>()) {
|
||||
if (!named->_name.isEmpty()) {
|
||||
result.append(qsl(" : ")).append(named->_name);
|
||||
}
|
||||
}
|
||||
if (const HistoryDocumentCaptioned *captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
if (!captioned->_caption.isEmpty()) {
|
||||
result.append(qsl(", ")).append(captioned->_caption.original(0, 0xFFFF, Text::ExpandLinksAll));
|
||||
}
|
||||
}
|
||||
return result.append(qsl(" ]"));
|
||||
}
|
||||
|
||||
void HistoryDocument::setStatusSize(int32 newSize, qint64 realDuration) const {
|
||||
HistoryFileMedia::setStatusSize(newSize, _data->size, _data->song() ? _data->song()->duration : -1, realDuration);
|
||||
|
||||
if (_statusSize == FileStatusSizeReady) {
|
||||
_link = lang(lng_media_download).toUpper();
|
||||
} else if (_statusSize == FileStatusSizeLoaded) {
|
||||
_link = lang(lng_media_open_with).toUpper();
|
||||
} else if (_statusSize == FileStatusSizeFailed) {
|
||||
_link = lang(lng_media_download).toUpper();
|
||||
} else if (_statusSize >= 0) {
|
||||
_link = lang(lng_media_cancel).toUpper();
|
||||
} else {
|
||||
_link = lang(lng_media_open_with).toUpper();
|
||||
int32 duration = _data->song() ? _data->song()->duration : (_data->voice() ? _data->voice()->duration : -1);
|
||||
HistoryFileMedia::setStatusSize(newSize, _data->size, duration, realDuration);
|
||||
if (const HistoryDocumentThumbed *thumbed = Get<HistoryDocumentThumbed>()) {
|
||||
if (_statusSize == FileStatusSizeReady) {
|
||||
thumbed->_link = lang(lng_media_download).toUpper();
|
||||
} else if (_statusSize == FileStatusSizeLoaded) {
|
||||
thumbed->_link = lang(lng_media_open_with).toUpper();
|
||||
} else if (_statusSize == FileStatusSizeFailed) {
|
||||
thumbed->_link = lang(lng_media_download).toUpper();
|
||||
} else if (_statusSize >= 0) {
|
||||
thumbed->_link = lang(lng_media_cancel).toUpper();
|
||||
} else {
|
||||
thumbed->_link = lang(lng_media_open_with).toUpper();
|
||||
}
|
||||
thumbed->_linkw = st::semiboldFont->width(thumbed->_link);
|
||||
}
|
||||
_linkw = st::semiboldFont->width(_link);
|
||||
}
|
||||
|
||||
bool HistoryDocument::updateStatusText(const HistoryItem *parent) const {
|
||||
@ -4311,7 +4253,41 @@ bool HistoryDocument::updateStatusText(const HistoryItem *parent) const {
|
||||
} else if (_data->loading()) {
|
||||
statusSize = _data->loadOffset();
|
||||
} else if (_data->loaded()) {
|
||||
if (_data->song()) {
|
||||
if (_data->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.msgId == parent->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||
if (const HistoryDocumentVoice *voice = Get<HistoryDocumentVoice>()) {
|
||||
bool was = voice->_playback;
|
||||
voice->ensurePlayback(this);
|
||||
if (!was || playingPosition != voice->_playback->_position) {
|
||||
float64 prg = playingDuration ? snap(float64(playingPosition) / playingDuration, 0., 1.) : 0.;
|
||||
if (voice->_playback->_position < playingPosition) {
|
||||
voice->_playback->a_progress.start(prg);
|
||||
} else {
|
||||
voice->_playback->a_progress = anim::fvalue(0., prg);
|
||||
}
|
||||
voice->_playback->_position = playingPosition;
|
||||
voice->_playback->_a_progress.start();
|
||||
}
|
||||
}
|
||||
|
||||
statusSize = -1 - (playingPosition / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency));
|
||||
realDuration = playingDuration / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency);
|
||||
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
|
||||
} else {
|
||||
statusSize = FileStatusSizeLoaded;
|
||||
if (const HistoryDocumentVoice *voice = Get<HistoryDocumentVoice>()) {
|
||||
voice->checkPlaybackFinished();
|
||||
}
|
||||
}
|
||||
} else if (_data->song()) {
|
||||
SongMsgId playing;
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
int64 playingPosition = 0, playingDuration = 0;
|
||||
@ -4342,6 +4318,21 @@ bool HistoryDocument::updateStatusText(const HistoryItem *parent) const {
|
||||
return showPause;
|
||||
}
|
||||
|
||||
void HistoryDocument::step_voiceProgress(float64 ms, bool timer) {
|
||||
if (HistoryDocumentVoice *voice = Get<HistoryDocumentVoice>()) {
|
||||
if (voice->_playback) {
|
||||
float64 dt = ms / (2 * AudioVoiceMsgUpdateView);
|
||||
if (dt >= 1) {
|
||||
voice->_playback->_a_progress.stop();
|
||||
voice->_playback->a_progress.finish();
|
||||
} else {
|
||||
voice->_playback->a_progress.update(qMin(dt, 1.), anim::linear);
|
||||
}
|
||||
if (timer) Ui::repaintHistoryItem(_parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryDocument::regItem(HistoryItem *item) {
|
||||
App::regDocumentItem(_data, item);
|
||||
}
|
||||
@ -4353,6 +4344,13 @@ void HistoryDocument::unregItem(HistoryItem *item) {
|
||||
void HistoryDocument::updateFrom(const MTPMessageMedia &media, HistoryItem *parent) {
|
||||
if (media.type() == mtpc_messageMediaDocument) {
|
||||
App::feedDocument(media.c_messageMediaDocument().vdocument, _data);
|
||||
if (!_data->data().isEmpty()) {
|
||||
if (_data->voice()) {
|
||||
Local::writeAudio(mediaKey(AudioFileLocation, _data->dc, _data->id), _data->data());
|
||||
} else {
|
||||
Local::writeStickerImage(mediaKey(DocumentFileLocation, _data->dc, _data->id), _data->data());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4361,6 +4359,7 @@ ImagePtr HistoryDocument::replyPreview() {
|
||||
}
|
||||
|
||||
HistoryGif::HistoryGif(DocumentData *document, const QString &caption, const HistoryItem *parent) : HistoryFileMedia()
|
||||
, _parent(0)
|
||||
, _data(document)
|
||||
, _thumbw(1)
|
||||
, _thumbh(1)
|
||||
@ -5126,7 +5125,6 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) {
|
||||
_maxw = _minh = _height = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_lineHeight) _lineHeight = qMax(st::webPageTitleFont->height, st::webPageDescriptionFont->height);
|
||||
|
||||
if (!_openl && !_data->url.isEmpty()) _openl = TextLinkPtr(new TextLink(_data->url));
|
||||
@ -5144,7 +5142,7 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) {
|
||||
} else {
|
||||
_asArticle = true;
|
||||
}
|
||||
if (_asArticle && (_data->description.isEmpty() || (title.isEmpty() && _data->siteName.isEmpty()))) {
|
||||
if (_asArticle && _data->description.isEmpty() && title.isEmpty() && _data->siteName.isEmpty()) {
|
||||
_asArticle = false;
|
||||
}
|
||||
} else {
|
||||
@ -6121,12 +6119,6 @@ void HistoryMessage::initMedia(const MTPMessageMedia *media, QString ¤tTex
|
||||
_media = new HistoryVideo(video.vvideo.c_video(), qs(video.vcaption), this);
|
||||
}
|
||||
} break;
|
||||
case mtpc_messageMediaAudio: {
|
||||
const MTPAudio &audio(media->c_messageMediaAudio().vaudio);
|
||||
if (audio.type() == mtpc_audio) {
|
||||
_media = new HistoryAudio(audio.c_audio());
|
||||
}
|
||||
} break;
|
||||
case mtpc_messageMediaDocument: {
|
||||
const MTPDocument &document(media->c_messageMediaDocument().vdocument);
|
||||
if (document.type() == mtpc_document) {
|
||||
@ -6225,8 +6217,8 @@ void HistoryMessage::countPositionAndSize(int32 &left, int32 &width) const {
|
||||
left += (!fromChannel() && out() && !Adaptive::Wide()) ? st::msgMargin.right() : st::msgMargin.left();
|
||||
if (displayFromPhoto()) {
|
||||
left += st::msgPhotoSkip;
|
||||
} else if (!Adaptive::Wide() && !out() && !fromChannel() && st::msgPhotoSkip - (hmaxwidth - hwidth) > 0) {
|
||||
left += st::msgPhotoSkip - (hmaxwidth - hwidth);
|
||||
// } else if (!Adaptive::Wide() && !out() && !fromChannel() && st::msgPhotoSkip - (hmaxwidth - hwidth) > 0) {
|
||||
// left += st::msgPhotoSkip - (hmaxwidth - hwidth);
|
||||
}
|
||||
|
||||
width = hwidth - st::msgMargin.left() - st::msgMargin.right();
|
||||
|
@ -95,23 +95,24 @@ enum HistoryMediaType {
|
||||
MediaTypeVideo,
|
||||
MediaTypeGeo,
|
||||
MediaTypeContact,
|
||||
MediaTypeAudio,
|
||||
MediaTypeDocument,
|
||||
MediaTypeFile,
|
||||
MediaTypeGif,
|
||||
MediaTypeSticker,
|
||||
MediaTypeImageLink,
|
||||
MediaTypeWebPage,
|
||||
MediaTypeMusicFile,
|
||||
MediaTypeVoiceFile,
|
||||
|
||||
MediaTypeCount
|
||||
};
|
||||
|
||||
enum MediaOverviewType {
|
||||
OverviewPhotos,
|
||||
OverviewVideos,
|
||||
OverviewAudioDocuments,
|
||||
OverviewDocuments,
|
||||
OverviewAudios,
|
||||
OverviewLinks,
|
||||
OverviewPhotos = 0,
|
||||
OverviewVideos = 1,
|
||||
OverviewMusicFiles = 2,
|
||||
OverviewFiles = 3,
|
||||
OverviewVoiceFiles = 4,
|
||||
OverviewLinks = 5,
|
||||
|
||||
OverviewCount
|
||||
};
|
||||
@ -120,9 +121,9 @@ inline MTPMessagesFilter typeToMediaFilter(MediaOverviewType &type) {
|
||||
switch (type) {
|
||||
case OverviewPhotos: return MTP_inputMessagesFilterPhotos();
|
||||
case OverviewVideos: return MTP_inputMessagesFilterVideo();
|
||||
case OverviewAudioDocuments: return MTP_inputMessagesFilterAudioDocuments();
|
||||
case OverviewDocuments: return MTP_inputMessagesFilterDocument();
|
||||
case OverviewAudios: return MTP_inputMessagesFilterAudio();
|
||||
case OverviewMusicFiles: return MTP_inputMessagesFilterMusic();
|
||||
case OverviewFiles: return MTP_inputMessagesFilterDocument();
|
||||
case OverviewVoiceFiles: return MTP_inputMessagesFilterVoice();
|
||||
case OverviewLinks: return MTP_inputMessagesFilterUrl();
|
||||
default: type = OverviewCount; break;
|
||||
}
|
||||
@ -133,8 +134,8 @@ enum SendActionType {
|
||||
SendActionTyping,
|
||||
SendActionRecordVideo,
|
||||
SendActionUploadVideo,
|
||||
SendActionRecordAudio,
|
||||
SendActionUploadAudio,
|
||||
SendActionRecordVoice,
|
||||
SendActionUploadVoice,
|
||||
SendActionUploadPhoto,
|
||||
SendActionUploadFile,
|
||||
SendActionChooseLocation,
|
||||
@ -1205,10 +1206,11 @@ inline MediaOverviewType mediaToOverviewType(HistoryMedia *media) {
|
||||
switch (media->type()) {
|
||||
case MediaTypePhoto: return OverviewPhotos;
|
||||
case MediaTypeVideo: return OverviewVideos;
|
||||
case MediaTypeDocument: return media->getDocument()->song() ? OverviewAudioDocuments : OverviewDocuments;
|
||||
case MediaTypeGif: return media->getDocument()->isGifv() ? OverviewCount : OverviewDocuments;
|
||||
// case MediaTypeSticker: return OverviewDocuments;
|
||||
case MediaTypeAudio: return OverviewAudios;
|
||||
case MediaTypeFile: return OverviewFiles;
|
||||
case MediaTypeMusicFile: return media->getDocument()->isMusic() ? OverviewMusicFiles : OverviewFiles;
|
||||
case MediaTypeVoiceFile: return OverviewVoiceFiles;
|
||||
case MediaTypeGif: return media->getDocument()->isGifv() ? OverviewCount : OverviewFiles;
|
||||
// case MediaTypeSticker: return OverviewFiles;
|
||||
}
|
||||
return OverviewCount;
|
||||
}
|
||||
@ -1418,76 +1420,52 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class HistoryAudio : public HistoryFileMedia {
|
||||
public:
|
||||
|
||||
HistoryAudio(const MTPDaudio &audio);
|
||||
HistoryAudio(const HistoryAudio &other);
|
||||
HistoryMediaType type() const {
|
||||
return MediaTypeAudio;
|
||||
struct HistoryDocumentThumbed : public BasicInterface<HistoryDocumentThumbed> {
|
||||
HistoryDocumentThumbed(Interfaces *interfaces) : _thumbw(0), _linkw(0) {
|
||||
}
|
||||
HistoryMedia *clone() const {
|
||||
return new HistoryAudio(*this);
|
||||
TextLinkPtr _linksavel, _linkcancell;
|
||||
int32 _thumbw;
|
||||
|
||||
mutable int32 _linkw;
|
||||
mutable QString _link;
|
||||
};
|
||||
struct HistoryDocumentCaptioned : public BasicInterface<HistoryDocumentCaptioned> {
|
||||
HistoryDocumentCaptioned(Interfaces *interfaces) : _caption(st::msgFileMinWidth - st::msgPadding.left() - st::msgPadding.right()) {
|
||||
}
|
||||
|
||||
void initDimensions(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;
|
||||
|
||||
const QString inDialogsText() const;
|
||||
const QString inHistoryText() const;
|
||||
|
||||
bool uploading() const {
|
||||
return _data->uploading();
|
||||
Text _caption;
|
||||
};
|
||||
struct HistoryDocumentNamed : public BasicInterface<HistoryDocumentNamed> {
|
||||
HistoryDocumentNamed(Interfaces *interfaces) : _namew(0) {
|
||||
}
|
||||
QString _name;
|
||||
int32 _namew;
|
||||
};
|
||||
class HistoryDocument;
|
||||
struct HistoryDocumentVoicePlayback {
|
||||
HistoryDocumentVoicePlayback(const HistoryDocument *that);
|
||||
|
||||
AudioData *audio() {
|
||||
return _data;
|
||||
int32 _position;
|
||||
anim::fvalue a_progress;
|
||||
Animation _a_progress;
|
||||
};
|
||||
struct HistoryDocumentVoice : public BasicInterface<HistoryDocumentVoice> {
|
||||
HistoryDocumentVoice(Interfaces *that) : _playback(0) {
|
||||
}
|
||||
|
||||
void regItem(HistoryItem *item);
|
||||
void unregItem(HistoryItem *item);
|
||||
|
||||
void updateFrom(const MTPMessageMedia &media, HistoryItem *parent);
|
||||
|
||||
bool needsBubble(const HistoryItem *parent) const {
|
||||
return true;
|
||||
~HistoryDocumentVoice() {
|
||||
deleteAndMark(_playback);
|
||||
}
|
||||
bool customInfoLayout() const {
|
||||
return false;
|
||||
}
|
||||
QMargins bubbleMargins() const {
|
||||
return st::msgPadding;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
float64 dataProgress() const {
|
||||
return _data->progress();
|
||||
}
|
||||
bool dataFinished() const {
|
||||
return !_data->loading() && !_data->uploading();
|
||||
}
|
||||
bool dataLoaded() const {
|
||||
return _data->loaded();
|
||||
}
|
||||
|
||||
private:
|
||||
AudioData *_data;
|
||||
|
||||
void setStatusSize(int32 newSize, qint64 realDuration = 0) const;
|
||||
bool updateStatusText(const HistoryItem *parent) const; // returns showPause
|
||||
|
||||
void ensurePlayback(const HistoryDocument *interfaces) const;
|
||||
void checkPlaybackFinished() const;
|
||||
mutable HistoryDocumentVoicePlayback *_playback;
|
||||
};
|
||||
|
||||
class HistoryDocument : public HistoryFileMedia {
|
||||
class HistoryDocument : public HistoryFileMedia, public Interfaces {
|
||||
public:
|
||||
|
||||
HistoryDocument(DocumentData *document, const QString &caption, const HistoryItem *parent);
|
||||
HistoryDocument(const HistoryDocument &other);
|
||||
HistoryMediaType type() const {
|
||||
return MediaTypeDocument;
|
||||
return _data->voice() ? MediaTypeVoiceFile : (_data->song() ? MediaTypeMusicFile : MediaTypeFile);
|
||||
}
|
||||
HistoryMedia *clone() const {
|
||||
return new HistoryDocument(*this);
|
||||
@ -1506,10 +1484,6 @@ public:
|
||||
return _data->uploading();
|
||||
}
|
||||
|
||||
bool withThumb() const {
|
||||
return !_data->song() && !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height();
|
||||
}
|
||||
|
||||
DocumentData *getDocument() {
|
||||
return _data;
|
||||
}
|
||||
@ -1525,7 +1499,10 @@ public:
|
||||
ImagePtr replyPreview();
|
||||
|
||||
QString getCaption() const {
|
||||
return _caption.original();
|
||||
if (const HistoryDocumentCaptioned *captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
return captioned->_caption.original();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
bool needsBubble(const HistoryItem *parent) const {
|
||||
return true;
|
||||
@ -1534,12 +1511,14 @@ public:
|
||||
return false;
|
||||
}
|
||||
QMargins bubbleMargins() const {
|
||||
return withThumb() ? QMargins(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbPadding.left(), st::msgFileThumbPadding.bottom()) : st::msgPadding;
|
||||
return Get<HistoryDocumentThumbed>() ? QMargins(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbPadding.left(), st::msgFileThumbPadding.bottom()) : st::msgPadding;
|
||||
}
|
||||
bool hideForwardedFrom() const {
|
||||
return _data->song();
|
||||
}
|
||||
|
||||
void step_voiceProgress(float64 ms, bool timer);
|
||||
|
||||
protected:
|
||||
|
||||
float64 dataProgress() const {
|
||||
@ -1554,17 +1533,9 @@ protected:
|
||||
|
||||
private:
|
||||
|
||||
void create(bool caption);
|
||||
const HistoryItem *_parent;
|
||||
DocumentData *_data;
|
||||
TextLinkPtr _linksavel, _linkcancell;
|
||||
|
||||
QString _name;
|
||||
int32 _namew;
|
||||
int32 _thumbw;
|
||||
|
||||
mutable int32 _linkw;
|
||||
mutable QString _link;
|
||||
|
||||
Text _caption;
|
||||
|
||||
void setStatusSize(int32 newSize, qint64 realDuration = 0) const;
|
||||
bool updateStatusText(const HistoryItem *parent) const; // returns showPause
|
||||
@ -2237,7 +2208,20 @@ inline int32 newMessageFlags(PeerData *p) {
|
||||
return p->isSelf() ? 0 : (((p->isChat() || (p->isUser() && !p->asUser()->botInfo)) ? MTPDmessage::flag_unread : 0) | MTPDmessage::flag_out);
|
||||
}
|
||||
inline int32 newForwardedFlags(PeerData *p, int32 from, HistoryMessage *msg) {
|
||||
return newMessageFlags(p) | (from ? MTPDmessage::flag_from_id : 0) | (msg->via() ? MTPDmessage::flag_via_bot_id : 0) | (!p->isChannel() && msg->getMedia() && (msg->getMedia()->type() == MediaTypeAudio/* || msg->getMedia()->type() == MediaTypeVideo*/) ? MTPDmessage::flag_media_unread : 0);
|
||||
int32 result = newMessageFlags(p) | (from ? MTPDmessage::flag_from_id : 0);
|
||||
if (msg->via()) {
|
||||
result |= MTPDmessage::flag_via_bot_id;
|
||||
}
|
||||
if (!p->isChannel()) {
|
||||
if (HistoryMedia *media = msg->getMedia()) {
|
||||
if (media->type() == MediaTypeVoiceFile) {
|
||||
result |= MTPDmessage::flag_media_unread;
|
||||
// } else if (media->type() == MediaTypeVideo) {
|
||||
// result |= MTPDmessage::flag_media_unread;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class HistoryServiceMsg : public HistoryItem {
|
||||
|
@ -865,9 +865,9 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||
HistoryItem *item = App::hoveredItem() ? App::hoveredItem() : App::hoveredLinkItem();
|
||||
PhotoLink *lnkPhoto = dynamic_cast<PhotoLink*>(_contextMenuLnk.data());
|
||||
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
|
||||
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
|
||||
if (lnkPhoto || lnkVideo || lnkAudio || lnkDocument) {
|
||||
bool lnkIsAudio = lnkDocument ? lnkDocument->document()->voice() : false;
|
||||
if (lnkPhoto || lnkVideo || lnkDocument) {
|
||||
if (isUponSelected > 0) {
|
||||
_menu->addAction(lang(lng_context_copy_selected), this, SLOT(copySelectedText()))->setEnabled(true);
|
||||
}
|
||||
@ -879,17 +879,17 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||
_menu->addAction(lang(lng_context_save_image), this, SLOT(saveContextImage()))->setEnabled(true);
|
||||
_menu->addAction(lang(lng_context_copy_image), this, SLOT(copyContextImage()))->setEnabled(true);
|
||||
} else {
|
||||
if ((lnkVideo && lnkVideo->video()->loading()) || (lnkAudio && lnkAudio->audio()->loading()) || (lnkDocument && lnkDocument->document()->loading())) {
|
||||
if ((lnkVideo && lnkVideo->video()->loading()) || (lnkDocument && lnkDocument->document()->loading())) {
|
||||
_menu->addAction(lang(lng_context_cancel_download), this, SLOT(cancelContextDownload()))->setEnabled(true);
|
||||
} else {
|
||||
if (lnkDocument && lnkDocument->document()->loaded() && lnkDocument->document()->isGifv()) {
|
||||
_menu->addAction(lang(lng_context_save_gif), this, SLOT(saveContextGif()))->setEnabled(true);
|
||||
}
|
||||
if ((lnkVideo && !lnkVideo->video()->already(true).isEmpty()) || (lnkAudio && !lnkAudio->audio()->already(true).isEmpty()) || (lnkDocument && !lnkDocument->document()->already(true).isEmpty())) {
|
||||
if ((lnkVideo && !lnkVideo->video()->already(true).isEmpty()) || (lnkDocument && !lnkDocument->document()->already(true).isEmpty())) {
|
||||
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), this, SLOT(showContextInFolder()))->setEnabled(true);
|
||||
}
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_open_video : (lnkAudio ? lng_context_open_audio : lng_context_open_file)), this, SLOT(openContextFile()))->setEnabled(true);
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_save_video : (lnkAudio ? lng_context_save_audio : lng_context_save_file)), this, SLOT(saveContextFile()))->setEnabled(true);
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_open_video : (lnkIsAudio ? lng_context_open_audio : lng_context_open_file)), this, SLOT(openContextFile()))->setEnabled(true);
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_save_video : (lnkIsAudio ? lng_context_save_audio : lng_context_save_file)), this, SLOT(saveContextFile()))->setEnabled(true);
|
||||
}
|
||||
}
|
||||
if (isUponSelected > 1) {
|
||||
@ -1071,8 +1071,6 @@ void HistoryInner::copyContextImage() {
|
||||
void HistoryInner::cancelContextDownload() {
|
||||
if (VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data())) {
|
||||
lnkVideo->video()->cancel();
|
||||
} else if (AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data())) {
|
||||
lnkAudio->audio()->cancel();
|
||||
} else if (DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data())) {
|
||||
lnkDocument->document()->cancel();
|
||||
} else if (HistoryItem *item = App::contextItem()) {
|
||||
@ -1088,8 +1086,6 @@ void HistoryInner::showContextInFolder() {
|
||||
QString already;
|
||||
if (VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data())) {
|
||||
already = lnkVideo->video()->already(true);
|
||||
} else if (AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data())) {
|
||||
already = lnkAudio->audio()->already(true);
|
||||
} else if (DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data())) {
|
||||
already = lnkDocument->document()->already(true);
|
||||
} else if (HistoryItem *item = App::contextItem()) {
|
||||
@ -1106,10 +1102,8 @@ void HistoryInner::openContextFile() {
|
||||
HistoryItem *was = App::hoveredLinkItem();
|
||||
App::hoveredLinkItem(App::contextItem());
|
||||
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
|
||||
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
|
||||
if (lnkVideo) VideoOpenLink(lnkVideo->video()).onClick(Qt::LeftButton);
|
||||
if (lnkAudio) AudioOpenLink(lnkAudio->audio()).onClick(Qt::LeftButton);
|
||||
if (lnkDocument) DocumentOpenLink(lnkDocument->document()).onClick(Qt::LeftButton);
|
||||
App::hoveredLinkItem(was);
|
||||
}
|
||||
@ -1117,8 +1111,6 @@ void HistoryInner::openContextFile() {
|
||||
void HistoryInner::saveContextFile() {
|
||||
if (VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data())) {
|
||||
VideoSaveLink::doSave(lnkVideo->video(), true);
|
||||
} else if (AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data())) {
|
||||
AudioSaveLink::doSave(lnkAudio->audio(), true);
|
||||
} else if (DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data())) {
|
||||
DocumentSaveLink::doSave(lnkDocument->document(), true);
|
||||
} else if (HistoryItem *item = App::contextItem()) {
|
||||
@ -2720,8 +2712,8 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
||||
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreviewTimeout()));
|
||||
if (audioCapture()) {
|
||||
connect(audioCapture(), SIGNAL(onError()), this, SLOT(onRecordError()));
|
||||
connect(audioCapture(), SIGNAL(onUpdate(qint16,qint32)), this, SLOT(onRecordUpdate(qint16,qint32)));
|
||||
connect(audioCapture(), SIGNAL(onDone(QByteArray,qint32)), this, SLOT(onRecordDone(QByteArray,qint32)));
|
||||
connect(audioCapture(), SIGNAL(onUpdate(quint16,qint32)), this, SLOT(onRecordUpdate(quint16,qint32)));
|
||||
connect(audioCapture(), SIGNAL(onDone(QByteArray,VoiceWaveform,qint32)), this, SLOT(onRecordDone(QByteArray,VoiceWaveform,qint32)));
|
||||
}
|
||||
|
||||
_updateHistoryItems.setSingleShot(true);
|
||||
@ -3005,8 +2997,8 @@ void HistoryWidget::updateSendAction(History *history, SendActionType type, int3
|
||||
case SendActionTyping: action = MTP_sendMessageTypingAction(); break;
|
||||
case SendActionRecordVideo: action = MTP_sendMessageRecordVideoAction(); break;
|
||||
case SendActionUploadVideo: action = MTP_sendMessageUploadVideoAction(MTP_int(progress)); break;
|
||||
case SendActionRecordAudio: action = MTP_sendMessageRecordAudioAction(); break;
|
||||
case SendActionUploadAudio: action = MTP_sendMessageUploadAudioAction(MTP_int(progress)); break;
|
||||
case SendActionRecordVoice: action = MTP_sendMessageRecordAudioAction(); break;
|
||||
case SendActionUploadVoice: action = MTP_sendMessageUploadAudioAction(MTP_int(progress)); break;
|
||||
case SendActionUploadPhoto: action = MTP_sendMessageUploadPhotoAction(MTP_int(progress)); break;
|
||||
case SendActionUploadFile: action = MTP_sendMessageUploadDocumentAction(MTP_int(progress)); break;
|
||||
case SendActionChooseLocation: action = MTP_sendMessageGeoLocationAction(); break;
|
||||
@ -3055,16 +3047,16 @@ void HistoryWidget::onRecordError() {
|
||||
stopRecording(false);
|
||||
}
|
||||
|
||||
void HistoryWidget::onRecordDone(QByteArray result, qint32 samples) {
|
||||
void HistoryWidget::onRecordDone(QByteArray result, VoiceWaveform waveform, qint32 samples) {
|
||||
if (!_peer) return;
|
||||
|
||||
App::wnd()->activateWindow();
|
||||
int32 duration = samples / AudioVoiceMsgFrequency;
|
||||
_fileLoader.addTask(new FileLoadTask(result, duration, FileLoadTo(_peer->id, _broadcast.checked(), replyToId())));
|
||||
_fileLoader.addTask(new FileLoadTask(result, duration, waveform, FileLoadTo(_peer->id, _broadcast.checked(), replyToId())));
|
||||
cancelReply(lastForceReplyReplied());
|
||||
}
|
||||
|
||||
void HistoryWidget::onRecordUpdate(qint16 level, qint32 samples) {
|
||||
void HistoryWidget::onRecordUpdate(quint16 level, qint32 samples) {
|
||||
if (!_recording) {
|
||||
return;
|
||||
}
|
||||
@ -3077,7 +3069,7 @@ void HistoryWidget::onRecordUpdate(qint16 level, qint32 samples) {
|
||||
}
|
||||
updateField();
|
||||
if (_peer && (!_peer->isChannel() || _peer->isMegagroup() || !_peer->asChannel()->canPublish() || (!_peer->asChannel()->isBroadcast() && !_broadcast.checked()))) {
|
||||
updateSendAction(_history, SendActionRecordAudio);
|
||||
updateSendAction(_history, SendActionRecordVoice);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4241,9 +4233,9 @@ void HistoryWidget::firstLoadMessages() {
|
||||
}
|
||||
|
||||
if (loadImportant) {
|
||||
_firstLoadRequest = MTP::send(MTPchannels_GetImportantHistory(from->asChannel()->inputChannel, MTP_int(offset_id), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from), rpcFail(&HistoryWidget::messagesFailed));
|
||||
_firstLoadRequest = MTP::send(MTPchannels_GetImportantHistory(from->asChannel()->inputChannel, MTP_int(offset_id), MTP_int(0), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from), rpcFail(&HistoryWidget::messagesFailed));
|
||||
} else {
|
||||
_firstLoadRequest = MTP::send(MTPmessages_GetHistory(from->input, MTP_int(offset_id), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from), rpcFail(&HistoryWidget::messagesFailed));
|
||||
_firstLoadRequest = MTP::send(MTPmessages_GetHistory(from->input, MTP_int(offset_id), MTP_int(offset), MTP_int(0), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from), rpcFail(&HistoryWidget::messagesFailed));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4265,9 +4257,9 @@ void HistoryWidget::loadMessages() {
|
||||
int32 offset = 0, loadCount = offset_id ? MessagesPerPage : MessagesFirstLoad;
|
||||
|
||||
if (loadImportant) {
|
||||
_preloadRequest = MTP::send(MTPchannels_GetImportantHistory(from->peer->asChannel()->inputChannel, MTP_int(offset_id), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from->peer), rpcFail(&HistoryWidget::messagesFailed));
|
||||
_preloadRequest = MTP::send(MTPchannels_GetImportantHistory(from->peer->asChannel()->inputChannel, MTP_int(offset_id), MTP_int(0), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from->peer), rpcFail(&HistoryWidget::messagesFailed));
|
||||
} else {
|
||||
_preloadRequest = MTP::send(MTPmessages_GetHistory(from->peer->input, MTP_int(offset_id), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from->peer), rpcFail(&HistoryWidget::messagesFailed));
|
||||
_preloadRequest = MTP::send(MTPmessages_GetHistory(from->peer->input, MTP_int(offset_id), MTP_int(0), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from->peer), rpcFail(&HistoryWidget::messagesFailed));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4295,9 +4287,9 @@ void HistoryWidget::loadMessagesDown() {
|
||||
}
|
||||
|
||||
if (loadImportant) {
|
||||
_preloadDownRequest = MTP::send(MTPchannels_GetImportantHistory(from->peer->asChannel()->inputChannel, MTP_int(offset_id + 1), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from->peer), rpcFail(&HistoryWidget::messagesFailed));
|
||||
_preloadDownRequest = MTP::send(MTPchannels_GetImportantHistory(from->peer->asChannel()->inputChannel, MTP_int(offset_id + 1), MTP_int(0), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from->peer), rpcFail(&HistoryWidget::messagesFailed));
|
||||
} else {
|
||||
_preloadDownRequest = MTP::send(MTPmessages_GetHistory(from->peer->input, MTP_int(offset_id + 1), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from->peer), rpcFail(&HistoryWidget::messagesFailed));
|
||||
_preloadDownRequest = MTP::send(MTPmessages_GetHistory(from->peer->input, MTP_int(offset_id + 1), MTP_int(0), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from->peer), rpcFail(&HistoryWidget::messagesFailed));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4355,9 +4347,9 @@ void HistoryWidget::delayedShowAt(MsgId showAtMsgId) {
|
||||
}
|
||||
|
||||
if (loadImportant) {
|
||||
_delayedShowAtRequest = MTP::send(MTPchannels_GetImportantHistory(from->asChannel()->inputChannel, MTP_int(offset_id), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from), rpcFail(&HistoryWidget::messagesFailed));
|
||||
_delayedShowAtRequest = MTP::send(MTPchannels_GetImportantHistory(from->asChannel()->inputChannel, MTP_int(offset_id), MTP_int(0), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from), rpcFail(&HistoryWidget::messagesFailed));
|
||||
} else {
|
||||
_delayedShowAtRequest = MTP::send(MTPmessages_GetHistory(from->input, MTP_int(offset_id), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from), rpcFail(&HistoryWidget::messagesFailed));
|
||||
_delayedShowAtRequest = MTP::send(MTPmessages_GetHistory(from->input, MTP_int(offset_id), MTP_int(0), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, from), rpcFail(&HistoryWidget::messagesFailed));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4807,7 +4799,7 @@ void HistoryWidget::onDocumentSelect() {
|
||||
void HistoryWidget::dragEnterEvent(QDragEnterEvent *e) {
|
||||
if (!_history) return;
|
||||
|
||||
if (_peer && (_peer->isChannel() && !_peer->asChannel()->canPublish())) return;
|
||||
if (_peer && !_canSendMessages) return;
|
||||
|
||||
_attachDrag = getDragState(e->mimeData());
|
||||
updateDragAreas();
|
||||
@ -4887,7 +4879,7 @@ void HistoryWidget::stopRecording(bool send) {
|
||||
_recording = false;
|
||||
_recordingSamples = 0;
|
||||
if (_peer && (!_peer->isChannel() || _peer->isMegagroup() || !_peer->asChannel()->canPublish() || (!_peer->asChannel()->isBroadcast() && !_broadcast.checked()))) {
|
||||
updateSendAction(_history, SendActionRecordAudio, -1);
|
||||
updateSendAction(_history, SendActionRecordVoice, -1);
|
||||
}
|
||||
|
||||
updateControlsVisibility();
|
||||
@ -5151,7 +5143,7 @@ void HistoryWidget::onPhotoDrop(const QMimeData *data) {
|
||||
void HistoryWidget::onDocumentDrop(const QMimeData *data) {
|
||||
if (!_history) return;
|
||||
|
||||
if (_peer && (_peer->isChannel() && !_peer->asChannel()->canPublish())) return;
|
||||
if (_peer && !_canSendMessages) return;
|
||||
|
||||
QStringList files = getMediasFromMime(data);
|
||||
if (files.isEmpty()) return;
|
||||
@ -5161,7 +5153,7 @@ void HistoryWidget::onDocumentDrop(const QMimeData *data) {
|
||||
|
||||
void HistoryWidget::onFilesDrop(const QMimeData *data) {
|
||||
|
||||
if (_peer && (_peer->isChannel() && !_peer->asChannel()->canPublish())) return;
|
||||
if (_peer && !_canSendMessages) return;
|
||||
|
||||
QStringList files = getMediasFromMime(data);
|
||||
if (files.isEmpty()) {
|
||||
@ -5522,13 +5514,10 @@ void HistoryWidget::confirmSendFile(const FileLoadResultPtr &file, bool ctrlShif
|
||||
connect(App::uploader(), SIGNAL(photoReady(const FullMsgId&, const MTPInputFile&)), this, SLOT(onPhotoUploaded(const FullMsgId&, const MTPInputFile&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(documentReady(const FullMsgId&, const MTPInputFile&)), this, SLOT(onDocumentUploaded(const FullMsgId&, const MTPInputFile&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(thumbDocumentReady(const FullMsgId&, const MTPInputFile&, const MTPInputFile&)), this, SLOT(onThumbDocumentUploaded(const FullMsgId&, const MTPInputFile&, const MTPInputFile&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(audioReady(const FullMsgId&, const MTPInputFile&)), this, SLOT(onAudioUploaded(const FullMsgId&, const MTPInputFile&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(photoProgress(const FullMsgId&)), this, SLOT(onPhotoProgress(const FullMsgId&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(documentProgress(const FullMsgId&)), this, SLOT(onDocumentProgress(const FullMsgId&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(audioProgress(const FullMsgId&)), this, SLOT(onAudioProgress(const FullMsgId&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(photoFailed(const FullMsgId&)), this, SLOT(onPhotoFailed(const FullMsgId&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(documentFailed(const FullMsgId&)), this, SLOT(onDocumentFailed(const FullMsgId&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(audioFailed(const FullMsgId&)), this, SLOT(onAudioFailed(const FullMsgId&)), Qt::UniqueConnection);
|
||||
|
||||
App::uploader()->upload(newId, file);
|
||||
|
||||
@ -5552,7 +5541,7 @@ void HistoryWidget::confirmSendFile(const FileLoadResultPtr &file, bool ctrlShif
|
||||
if (!h->peer->isChannel()) {
|
||||
flags |= MTPDmessage::flag_media_unread;
|
||||
}
|
||||
h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(file->to.peer), MTPPeer(), MTPint(), MTPint(), MTP_int(file->to.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(file->audio), MTPnullMarkup, MTPnullEntities, MTP_int(1)), NewMessageUnread);
|
||||
h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(file->to.peer), MTPPeer(), MTPint(), MTPint(), MTP_int(file->to.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(file->document, MTP_string(file->caption)), MTPnullMarkup, MTPnullEntities, MTP_int(1)), NewMessageUnread);
|
||||
}
|
||||
|
||||
if (_peer && file->to.peer == _peer->id) {
|
||||
@ -5628,7 +5617,9 @@ namespace {
|
||||
} else if (document->type == StickerDocument && document->sticker()) {
|
||||
attributes.push_back(MTP_documentAttributeSticker(MTP_string(document->sticker()->alt), document->sticker()->set));
|
||||
} else if (document->type == SongDocument && document->song()) {
|
||||
attributes.push_back(MTP_documentAttributeAudio(MTP_int(document->song()->duration), MTP_string(document->song()->title), MTP_string(document->song()->performer)));
|
||||
attributes.push_back(MTP_documentAttributeAudio(MTP_int(MTPDdocumentAttributeAudio::flag_title | MTPDdocumentAttributeAudio::flag_performer), MTP_int(document->song()->duration), MTP_string(document->song()->title), MTP_string(document->song()->performer), MTPstring()));
|
||||
} else if (document->type == VoiceDocument && document->voice()) {
|
||||
attributes.push_back(MTP_documentAttributeAudio(MTP_int(MTPDdocumentAttributeAudio::flag_voice | MTPDdocumentAttributeAudio::flag_waveform), MTP_int(document->voice()->duration), MTPstring(), MTPstring(), MTP_string(documentWaveformEncode5bit(document->voice()->waveform))));
|
||||
}
|
||||
return MTP_vector<MTPDocumentAttribute>(attributes);
|
||||
}
|
||||
@ -5684,33 +5675,6 @@ void HistoryWidget::onThumbDocumentUploaded(const FullMsgId &newId, const MTPInp
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onAudioUploaded(const FullMsgId &newId, const MTPInputFile &file) {
|
||||
if (!MTP::authedId()) return;
|
||||
HistoryMessage *item = dynamic_cast<HistoryMessage*>(App::histItemById(newId));
|
||||
if (item) {
|
||||
AudioData *audio = 0;
|
||||
if (HistoryAudio *media = dynamic_cast<HistoryAudio*>(item->getMedia())) {
|
||||
audio = media->audio();
|
||||
}
|
||||
if (audio) {
|
||||
uint64 randomId = MTP::nonce<uint64>();
|
||||
App::historyRegRandom(randomId, newId);
|
||||
History *hist = item->history();
|
||||
MsgId replyTo = item->toHistoryReply() ? item->toHistoryReply()->replyToId() : 0;
|
||||
int32 sendFlags = 0;
|
||||
if (replyTo) {
|
||||
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
|
||||
}
|
||||
|
||||
bool fromChannelName = hist->peer->isChannel() && !hist->peer->isMegagroup() && hist->peer->asChannel()->canPublish() && item->fromChannel();
|
||||
if (fromChannelName) {
|
||||
sendFlags |= MTPmessages_SendMedia::flag_broadcast;
|
||||
}
|
||||
hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedAudio(file, MTP_int(audio->duration), MTP_string(audio->mime)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendMessageFail), 0, 0, hist->sendRequestId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onPhotoProgress(const FullMsgId &newId) {
|
||||
if (!MTP::authedId()) return;
|
||||
if (HistoryItem *item = App::histItemById(newId)) {
|
||||
@ -5728,18 +5692,7 @@ void HistoryWidget::onDocumentProgress(const FullMsgId &newId) {
|
||||
HistoryMedia *media = item->getMedia();
|
||||
DocumentData *doc = media ? media->getDocument() : 0;
|
||||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadFile, doc ? doc->uploadOffset : 0);
|
||||
}
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onAudioProgress(const FullMsgId &newId) {
|
||||
if (!MTP::authedId()) return;
|
||||
if (HistoryItem *item = App::histItemById(newId)) {
|
||||
AudioData *audio = (item->getMedia() && item->getMedia()->type() == MediaTypeAudio) ? static_cast<HistoryAudio*>(item->getMedia())->audio() : 0;
|
||||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadAudio, audio ? audio->uploadOffset : 0);
|
||||
updateSendAction(item->history(), (doc && doc->voice()) ? SendActionUploadVoice : SendActionUploadFile, doc ? doc->uploadOffset : 0);
|
||||
}
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
@ -5760,19 +5713,10 @@ void HistoryWidget::onDocumentFailed(const FullMsgId &newId) {
|
||||
if (!MTP::authedId()) return;
|
||||
HistoryItem *item = App::histItemById(newId);
|
||||
if (item) {
|
||||
HistoryMedia *media = item->getMedia();
|
||||
DocumentData *doc = media ? media->getDocument() : 0;
|
||||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadFile, -1);
|
||||
}
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onAudioFailed(const FullMsgId &newId) {
|
||||
if (!MTP::authedId()) return;
|
||||
HistoryItem *item = App::histItemById(newId);
|
||||
if (item) {
|
||||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadAudio, -1);
|
||||
updateSendAction(item->history(), (doc && doc->voice()) ? SendActionUploadVoice : SendActionUploadFile, -1);
|
||||
}
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
@ -7194,7 +7138,7 @@ void HistoryWidget::drawRecording(Painter &p) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::recordSignalColor->b);
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||
float64 delta = qMin(float64(a_recordingLevel.current()) * 3 * M_PI / 0x7fff, 1.);
|
||||
float64 delta = qMin(float64(a_recordingLevel.current()) / 0x4000, 1.);
|
||||
int32 d = 2 * qRound(st::recordSignalMin + (delta * (st::recordSignalMax - st::recordSignalMin)));
|
||||
p.drawEllipse(_attachPhoto.x() + (_attachEmoji.width() - d) / 2, _attachPhoto.y() + (_attachPhoto.height() - d) / 2, d, d);
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||
|
@ -610,15 +610,12 @@ public slots:
|
||||
void onPhotoUploaded(const FullMsgId &msgId, const MTPInputFile &file);
|
||||
void onDocumentUploaded(const FullMsgId &msgId, const MTPInputFile &file);
|
||||
void onThumbDocumentUploaded(const FullMsgId &msgId, const MTPInputFile &file, const MTPInputFile &thumb);
|
||||
void onAudioUploaded(const FullMsgId &msgId, const MTPInputFile &file);
|
||||
|
||||
void onPhotoProgress(const FullMsgId &msgId);
|
||||
void onDocumentProgress(const FullMsgId &msgId);
|
||||
void onAudioProgress(const FullMsgId &msgId);
|
||||
|
||||
void onPhotoFailed(const FullMsgId &msgId);
|
||||
void onDocumentFailed(const FullMsgId &msgId);
|
||||
void onAudioFailed(const FullMsgId &msgId);
|
||||
|
||||
void onReportSpamClicked();
|
||||
void onReportSpamSure();
|
||||
@ -683,8 +680,8 @@ public slots:
|
||||
void updateField();
|
||||
|
||||
void onRecordError();
|
||||
void onRecordDone(QByteArray result, qint32 samples);
|
||||
void onRecordUpdate(qint16 level, qint32 samples);
|
||||
void onRecordDone(QByteArray result, VoiceWaveform waveform, qint32 samples);
|
||||
void onRecordUpdate(quint16 level, qint32 samples);
|
||||
|
||||
void onUpdateHistoryItems();
|
||||
|
||||
|
@ -550,23 +550,25 @@ void LayoutOverviewVideo::updateStatusText() const {
|
||||
}
|
||||
}
|
||||
|
||||
LayoutOverviewAudio::LayoutOverviewAudio(AudioData *audio, HistoryItem *parent) : LayoutAbstractFileItem(OverviewItemInfo::Bit(), parent)
|
||||
, _data(audio)
|
||||
, _namel(new AudioOpenLink(_data)) {
|
||||
setLinks(new AudioOpenLink(_data), new AudioOpenLink(_data), new AudioCancelLink(_data));
|
||||
LayoutOverviewVoice::LayoutOverviewVoice(DocumentData *voice, HistoryItem *parent) : LayoutAbstractFileItem(OverviewItemInfo::Bit(), parent)
|
||||
, _data(voice)
|
||||
, _namel(new DocumentOpenLink(_data)) {
|
||||
t_assert(_data->voice() != 0);
|
||||
|
||||
setLinks(new DocumentOpenLink(_data), new DocumentOpenLink(_data), new DocumentCancelLink(_data));
|
||||
updateName();
|
||||
QString d = textcmdLink(1, textRichPrepare(langDateTime(date(_data->date))));
|
||||
TextParseOptions opts = { TextParseRichText, 0, 0, Qt::LayoutDirectionAuto };
|
||||
_details.setText(st::normalFont, lng_date_and_duration(lt_date, d, lt_duration, formatDurationText(_data->duration)), opts);
|
||||
_details.setText(st::normalFont, lng_date_and_duration(lt_date, d, lt_duration, formatDurationText(_data->voice()->duration)), opts);
|
||||
_details.setLink(1, TextLinkPtr(new MessageLink(parent)));
|
||||
}
|
||||
|
||||
void LayoutOverviewAudio::initDimensions() {
|
||||
void LayoutOverviewVoice::initDimensions() {
|
||||
_maxw = st::profileMaxWidth;
|
||||
_minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom() + st::lineWidth;
|
||||
}
|
||||
|
||||
void LayoutOverviewAudio::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void LayoutOverviewVoice::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
bool selected = (selection == FullSelection);
|
||||
|
||||
_data->automaticLoad(_parent);
|
||||
@ -666,7 +668,7 @@ void LayoutOverviewAudio::paint(Painter &p, const QRect &clip, uint32 selection,
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutOverviewAudio::getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const {
|
||||
void LayoutOverviewVoice::getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const {
|
||||
bool loaded = _data->loaded();
|
||||
|
||||
bool showPause = updateStatusText();
|
||||
@ -696,7 +698,7 @@ void LayoutOverviewAudio::getState(TextLinkPtr &link, HistoryCursorState &cursor
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutOverviewAudio::updateName() const {
|
||||
void LayoutOverviewVoice::updateName() const {
|
||||
int32 version = 0;
|
||||
if (HistoryForwarded *fwd = _parent->toHistoryForwarded()) {
|
||||
_name.setText(st::semiboldFont, lang(lng_forwarded_from) + ' ' + App::peerName(fwd->fromForwarded()), _textNameOptions);
|
||||
@ -708,7 +710,7 @@ void LayoutOverviewAudio::updateName() const {
|
||||
_nameVersion = version;
|
||||
}
|
||||
|
||||
bool LayoutOverviewAudio::updateStatusText() const {
|
||||
bool LayoutOverviewVoice::updateStatusText() const {
|
||||
bool showPause = false;
|
||||
int32 statusSize = 0, realDuration = 0;
|
||||
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
|
||||
@ -733,7 +735,7 @@ bool LayoutOverviewAudio::updateStatusText() const {
|
||||
statusSize = FileStatusSizeReady;
|
||||
}
|
||||
if (statusSize != _statusSize) {
|
||||
setStatusSize(statusSize, _data->size, _data->duration, realDuration);
|
||||
setStatusSize(statusSize, _data->size, _data->voice()->duration, realDuration);
|
||||
}
|
||||
return showPause;
|
||||
}
|
||||
|
@ -349,9 +349,9 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class LayoutOverviewAudio : public LayoutAbstractFileItem {
|
||||
class LayoutOverviewVoice : public LayoutAbstractFileItem {
|
||||
public:
|
||||
LayoutOverviewAudio(AudioData *audio, HistoryItem *parent);
|
||||
LayoutOverviewVoice(DocumentData *voice, HistoryItem *parent);
|
||||
|
||||
virtual void initDimensions();
|
||||
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||
@ -372,7 +372,7 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
AudioData *_data;
|
||||
DocumentData *_data;
|
||||
TextLinkPtr _namel;
|
||||
|
||||
mutable Text _name, _details;
|
||||
|
@ -198,10 +198,11 @@ FileLoadTask::FileLoadTask(const QImage &image, PrepareMediaType type, const Fil
|
||||
, _result(0) {
|
||||
}
|
||||
|
||||
FileLoadTask::FileLoadTask(const QByteArray &audio, int32 duration, const FileLoadTo &to) : _id(MTP::nonce<uint64>())
|
||||
FileLoadTask::FileLoadTask(const QByteArray &voice, int32 duration, const VoiceWaveform &waveform, const FileLoadTo &to) : _id(MTP::nonce<uint64>())
|
||||
, _to(to)
|
||||
, _content(audio)
|
||||
, _content(voice)
|
||||
, _duration(duration)
|
||||
, _waveform(waveform)
|
||||
, _type(PrepareAudio)
|
||||
, _confirm(FileLoadNoForceConfirm)
|
||||
, _result(0) {
|
||||
@ -220,7 +221,7 @@ void FileLoadTask::process() {
|
||||
QString thumbname = "thumb.jpg";
|
||||
QByteArray thumbdata;
|
||||
|
||||
bool animated = false;
|
||||
bool animated = false, song = false, gif = false, voice = (_type == PrepareAudio);
|
||||
QImage fullimage = _image;
|
||||
|
||||
if (!_filepath.isEmpty()) {
|
||||
@ -232,30 +233,32 @@ void FileLoadTask::process() {
|
||||
filesize = info.size();
|
||||
filemime = mimeTypeForFile(info).name();
|
||||
filename = info.fileName();
|
||||
if (filesize <= MaxUploadPhotoSize && _type != PrepareAudio) {
|
||||
if (filesize <= MaxUploadPhotoSize && !voice) {
|
||||
bool opaque = (filemime != stickerMime);
|
||||
fullimage = App::readImage(_filepath, 0, opaque, &animated);
|
||||
}
|
||||
} else if (!_content.isEmpty()) {
|
||||
filesize = _content.size();
|
||||
MimeType mimeType = mimeTypeForData(_content);
|
||||
filemime = mimeType.name();
|
||||
if (filesize <= MaxUploadPhotoSize && _type != PrepareAudio) {
|
||||
bool opaque = (filemime != stickerMime);
|
||||
fullimage = App::readImage(_content, 0, opaque, &animated);
|
||||
}
|
||||
if (filemime == "image/jpeg") {
|
||||
filename = filedialogDefaultName(qsl("image"), qsl(".jpg"), QString(), true);
|
||||
} else if (_type == PrepareAudio) {
|
||||
if (voice) {
|
||||
filename = filedialogDefaultName(qsl("audio"), qsl(".ogg"), QString(), true);
|
||||
filemime = "audio/ogg";
|
||||
} else {
|
||||
QString ext;
|
||||
QStringList patterns = mimeType.globPatterns();
|
||||
if (!patterns.isEmpty()) {
|
||||
ext = patterns.front().replace('*', QString());
|
||||
MimeType mimeType = mimeTypeForData(_content);
|
||||
filemime = mimeType.name();
|
||||
if (filesize <= MaxUploadPhotoSize && !voice) {
|
||||
bool opaque = (filemime != stickerMime);
|
||||
fullimage = App::readImage(_content, 0, opaque, &animated);
|
||||
}
|
||||
if (filemime == "image/jpeg") {
|
||||
filename = filedialogDefaultName(qsl("image"), qsl(".jpg"), QString(), true);
|
||||
} else {
|
||||
QString ext;
|
||||
QStringList patterns = mimeType.globPatterns();
|
||||
if (!patterns.isEmpty()) {
|
||||
ext = patterns.front().replace('*', QString());
|
||||
}
|
||||
filename = filedialogDefaultName(qsl("file"), ext, QString(), true);
|
||||
}
|
||||
filename = filedialogDefaultName(qsl("file"), ext, QString(), true);
|
||||
}
|
||||
} else if (!_image.isNull()) {
|
||||
_image = QImage();
|
||||
@ -292,10 +295,8 @@ void FileLoadTask::process() {
|
||||
MTPPhotoSize thumbSize(MTP_photoSizeEmpty(MTP_string("")));
|
||||
MTPPhoto photo(MTP_photoEmpty(MTP_long(0)));
|
||||
MTPDocument document(MTP_documentEmpty(MTP_long(0)));
|
||||
MTPAudio audio(MTP_audioEmpty(MTP_long(0)));
|
||||
|
||||
bool song = false, gif = false;
|
||||
if (_type != PrepareAudio) {
|
||||
if (!voice) {
|
||||
if (filemime == qstr("audio/mp3") || filemime == qstr("audio/m4a") || filemime == qstr("audio/aac") || filemime == qstr("audio/ogg") || filemime == qstr("audio/flac") ||
|
||||
filename.endsWith(qstr(".mp3"), Qt::CaseInsensitive) || filename.endsWith(qstr(".m4a"), Qt::CaseInsensitive) ||
|
||||
filename.endsWith(qstr(".aac"), Qt::CaseInsensitive) || filename.endsWith(qstr(".ogg"), Qt::CaseInsensitive) ||
|
||||
@ -358,7 +359,7 @@ void FileLoadTask::process() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!fullimage.isNull() && fullimage.width() > 0 && !song && !gif) {
|
||||
if (!fullimage.isNull() && fullimage.width() > 0 && !song && !gif && !voice) {
|
||||
int32 w = fullimage.width(), h = fullimage.height();
|
||||
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(w), MTP_int(h)));
|
||||
|
||||
@ -408,8 +409,10 @@ void FileLoadTask::process() {
|
||||
}
|
||||
}
|
||||
|
||||
if (_type == PrepareAudio) {
|
||||
audio = MTP_audio(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_int(_duration), MTP_string(filemime), MTP_int(filesize), MTP_int(MTP::maindc()));
|
||||
if (voice) {
|
||||
attributes[0] = MTP_documentAttributeAudio(MTP_int(MTPDdocumentAttributeAudio::flag_voice | MTPDdocumentAttributeAudio::flag_waveform), MTP_int(_duration), MTPstring(), MTPstring(), MTP_string(documentWaveformEncode5bit(_waveform)));
|
||||
attributes.resize(1);
|
||||
document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
|
||||
} else {
|
||||
document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
|
||||
if (photo.type() == mtpc_photoEmpty) {
|
||||
@ -431,7 +434,6 @@ void FileLoadTask::process() {
|
||||
_result->thumb = thumb;
|
||||
|
||||
_result->photo = photo;
|
||||
_result->audio = audio;
|
||||
_result->document = document;
|
||||
_result->photoThumbs = photoThumbs;
|
||||
}
|
||||
|
@ -52,8 +52,8 @@ typedef QList<ToPrepareMedia> ToPrepareMedias;
|
||||
|
||||
typedef QMap<int32, QByteArray> UploadFileParts;
|
||||
struct ReadyLocalMedia {
|
||||
ReadyLocalMedia(PrepareMediaType type, const QString &file, const QString &filename, int32 filesize, const QByteArray &data, const uint64 &id, const uint64 &thumbId, const QString &thumbExt, const PeerId &peer, const MTPPhoto &photo, const MTPAudio &audio, const PreparedPhotoThumbs &photoThumbs, const MTPDocument &document, const QByteArray &jpeg, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) :
|
||||
replyTo(replyTo), type(type), file(file), filename(filename), filesize(filesize), data(data), thumbExt(thumbExt), id(id), thumbId(thumbId), peer(peer), photo(photo), document(document), audio(audio), photoThumbs(photoThumbs), broadcast(broadcast), ctrlShiftEnter(ctrlShiftEnter) {
|
||||
ReadyLocalMedia(PrepareMediaType type, const QString &file, const QString &filename, int32 filesize, const QByteArray &data, const uint64 &id, const uint64 &thumbId, const QString &thumbExt, const PeerId &peer, const MTPPhoto &photo, const PreparedPhotoThumbs &photoThumbs, const MTPDocument &document, const QByteArray &jpeg, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) :
|
||||
replyTo(replyTo), type(type), file(file), filename(filename), filesize(filesize), data(data), thumbExt(thumbExt), id(id), thumbId(thumbId), peer(peer), photo(photo), document(document), photoThumbs(photoThumbs), broadcast(broadcast), ctrlShiftEnter(ctrlShiftEnter) {
|
||||
if (!jpeg.isEmpty()) {
|
||||
int32 size = jpeg.size();
|
||||
for (int32 i = 0, part = 0; i < size; i += UploadPartSize, ++part) {
|
||||
@ -74,7 +74,6 @@ struct ReadyLocalMedia {
|
||||
|
||||
MTPPhoto photo;
|
||||
MTPDocument document;
|
||||
MTPAudio audio;
|
||||
PreparedPhotoThumbs photoThumbs;
|
||||
UploadFileParts parts;
|
||||
QByteArray jpeg_md5;
|
||||
@ -114,7 +113,7 @@ public:
|
||||
TaskId addTask(TaskPtr task);
|
||||
void addTasks(const TasksList &tasks);
|
||||
void cancelTask(TaskId id); // this task finish() won't be called
|
||||
|
||||
|
||||
TaskId addTask(Task *task) {
|
||||
return addTask(TaskPtr(task));
|
||||
}
|
||||
@ -203,7 +202,6 @@ struct FileLoadResult {
|
||||
QPixmap thumb;
|
||||
|
||||
MTPPhoto photo;
|
||||
MTPAudio audio;
|
||||
MTPDocument document;
|
||||
|
||||
PreparedPhotoThumbs photoThumbs;
|
||||
@ -248,7 +246,7 @@ public:
|
||||
FileLoadTask(const QString &filepath, PrepareMediaType type, const FileLoadTo &to, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm);
|
||||
FileLoadTask(const QByteArray &content, PrepareMediaType type, const FileLoadTo &to);
|
||||
FileLoadTask(const QImage &image, PrepareMediaType type, const FileLoadTo &to, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm, const QString &originalText = QString());
|
||||
FileLoadTask(const QByteArray &audio, int32 duration, const FileLoadTo &to);
|
||||
FileLoadTask(const QByteArray &voice, int32 duration, const VoiceWaveform &waveform, const FileLoadTo &to);
|
||||
|
||||
uint64 fileid() const {
|
||||
return _id;
|
||||
@ -265,6 +263,7 @@ protected:
|
||||
QImage _image;
|
||||
QByteArray _content;
|
||||
int32 _duration;
|
||||
VoiceWaveform _waveform;
|
||||
PrepareMediaType _type;
|
||||
FileLoadForceConfirmType _confirm;
|
||||
QString _originalText;
|
||||
|
@ -2785,6 +2785,77 @@ namespace Local {
|
||||
return _storageWebFilesSize;
|
||||
}
|
||||
|
||||
class CountWaveformTask : public Task {
|
||||
public:
|
||||
CountWaveformTask(DocumentData *doc)
|
||||
: _doc(doc)
|
||||
, _loc(doc->location(true))
|
||||
, _data(doc->data())
|
||||
, _wavemax(0) {
|
||||
if (_data.isEmpty() && !_loc.accessEnable()) {
|
||||
_doc = 0;
|
||||
}
|
||||
}
|
||||
void process() {
|
||||
if (!_doc) return;
|
||||
|
||||
_waveform = audioCountWaveform(_loc, _data);
|
||||
uchar wavemax = 0;
|
||||
for (int32 i = 0, l = _waveform.size(); i < l; ++i) {
|
||||
uchar waveat = _waveform.at(i);
|
||||
if (wavemax < waveat) wavemax = waveat;
|
||||
}
|
||||
_wavemax = wavemax;
|
||||
}
|
||||
void finish() {
|
||||
if (VoiceData *voice = _doc ? _doc->voice() : 0) {
|
||||
if (!_waveform.isEmpty()) {
|
||||
voice->waveform = _waveform;
|
||||
voice->wavemax = _wavemax;
|
||||
}
|
||||
if (voice->waveform.isEmpty()) {
|
||||
voice->waveform.resize(1);
|
||||
voice->waveform[0] = -2;
|
||||
voice->wavemax = 0;
|
||||
} else if (voice->waveform[0] < 0) {
|
||||
voice->waveform[0] = -2;
|
||||
voice->wavemax = 0;
|
||||
}
|
||||
const DocumentItems &items(App::documentItems());
|
||||
DocumentItems::const_iterator i = items.constFind(_doc);
|
||||
if (i != items.cend()) {
|
||||
for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) {
|
||||
Ui::repaintHistoryItem(j.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual ~CountWaveformTask() {
|
||||
if (_data.isEmpty() && _doc) {
|
||||
_loc.accessDisable();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
DocumentData *_doc;
|
||||
FileLocation _loc;
|
||||
QByteArray _data;
|
||||
VoiceWaveform _waveform;
|
||||
char _wavemax;
|
||||
|
||||
};
|
||||
|
||||
void countVoiceWaveform(DocumentData *document) {
|
||||
if (VoiceData *voice = document->voice()) {
|
||||
if (_localLoader) {
|
||||
voice->waveform.resize(1 + sizeof(TaskId));
|
||||
voice->waveform[0] = -1; // counting
|
||||
TaskId taskId = _localLoader->addTask(new CountWaveformTask(document));
|
||||
memcpy(voice->waveform.data() + 1, &taskId, sizeof(taskId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cancelTask(TaskId id) {
|
||||
if (_localLoader) {
|
||||
_localLoader->cancelTask(id);
|
||||
|
@ -144,6 +144,8 @@ namespace Local {
|
||||
int32 hasWebFiles();
|
||||
qint64 storageWebFilesSize();
|
||||
|
||||
void countVoiceWaveform(DocumentData *document);
|
||||
|
||||
void cancelTask(TaskId id);
|
||||
|
||||
void writeStickers();
|
||||
|
@ -1124,9 +1124,9 @@ bool MainWidget::kickParticipantFail(ChatData *chat, const RPCError &error) {
|
||||
|
||||
void MainWidget::checkPeerHistory(PeerData *peer) {
|
||||
if (peer->isChannel() && !peer->isMegagroup()) {
|
||||
MTP::send(MTPchannels_GetImportantHistory(peer->asChannel()->inputChannel, MTP_int(0), MTP_int(0), MTP_int(1), MTP_int(0), MTP_int(0)), rpcDone(&MainWidget::checkedHistory, peer));
|
||||
MTP::send(MTPchannels_GetImportantHistory(peer->asChannel()->inputChannel, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(1), MTP_int(0), MTP_int(0)), rpcDone(&MainWidget::checkedHistory, peer));
|
||||
} else {
|
||||
MTP::send(MTPmessages_GetHistory(peer->input, MTP_int(0), MTP_int(0), MTP_int(1), MTP_int(0), MTP_int(0)), rpcDone(&MainWidget::checkedHistory, peer));
|
||||
MTP::send(MTPmessages_GetHistory(peer->input, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(1), MTP_int(0), MTP_int(0)), rpcDone(&MainWidget::checkedHistory, peer));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1479,9 +1479,9 @@ void MainWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
|
||||
switch (i) {
|
||||
case OverviewPhotos: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaPhotos, lang(lng_media_type_photos))), SIGNAL(clicked()), this, SLOT(onPhotosSelect())); break;
|
||||
case OverviewVideos: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaVideos, lang(lng_media_type_videos))), SIGNAL(clicked()), this, SLOT(onVideosSelect())); break;
|
||||
case OverviewAudioDocuments: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaSongs, lang(lng_media_type_songs))), SIGNAL(clicked()), this, SLOT(onSongsSelect())); break;
|
||||
case OverviewDocuments: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaDocuments, lang(lng_media_type_files))), SIGNAL(clicked()), this, SLOT(onDocumentsSelect())); break;
|
||||
case OverviewAudios: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaAudios, lang(lng_media_type_audios))), SIGNAL(clicked()), this, SLOT(onAudiosSelect())); break;
|
||||
case OverviewMusicFiles: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaSongs, lang(lng_media_type_songs))), SIGNAL(clicked()), this, SLOT(onSongsSelect())); break;
|
||||
case OverviewFiles: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaDocuments, lang(lng_media_type_files))), SIGNAL(clicked()), this, SLOT(onDocumentsSelect())); break;
|
||||
case OverviewVoiceFiles: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaAudios, lang(lng_media_type_audios))), SIGNAL(clicked()), this, SLOT(onAudiosSelect())); break;
|
||||
case OverviewLinks: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaLinks, lang(lng_media_type_links))), SIGNAL(clicked()), this, SLOT(onLinksSelect())); break;
|
||||
}
|
||||
}
|
||||
@ -1709,24 +1709,6 @@ void MainWidget::videoLoadRetry() {
|
||||
if (video) video->save(failedFileName);
|
||||
}
|
||||
|
||||
void MainWidget::audioLoadProgress(FileLoader *loader) {
|
||||
mtpFileLoader *l = loader ? loader->mtpLoader() : 0;
|
||||
if (!l) return;
|
||||
|
||||
AudioData *audio = App::audio(l->objId());
|
||||
if (audio->loaded()) {
|
||||
audio->performActionOnLoad();
|
||||
}
|
||||
|
||||
const AudioItems &items(App::audioItems());
|
||||
AudioItems::const_iterator i = items.constFind(audio);
|
||||
if (i != items.cend()) {
|
||||
for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) {
|
||||
Ui::repaintHistoryItem(j.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
|
||||
AudioMsgId playing;
|
||||
AudioPlayerState state = AudioPlayerStopped;
|
||||
@ -1734,7 +1716,7 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
|
||||
if (playing == audioId && state == AudioPlayerStoppedAtStart) {
|
||||
audioPlayer()->clearStoppedAtStart(audioId);
|
||||
|
||||
AudioData *audio = audioId.audio;
|
||||
DocumentData *audio = audioId.audio;
|
||||
QString already = audio->already(true);
|
||||
if (already.isEmpty() && !audio->data().isEmpty()) {
|
||||
bool mp3 = (audio->mime == qstr("audio/mp3"));
|
||||
@ -1746,7 +1728,7 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
|
||||
f.close();
|
||||
already = filename;
|
||||
audio->setLocation(FileLocation(StorageFilePartial, filename));
|
||||
Local::writeFileLocation(mediaKey(mtpToLocationType(mtpc_inputAudioFileLocation), audio->dc, audio->id), FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename));
|
||||
Local::writeFileLocation(mediaKey(AudioFileLocation, audio->dc, audio->id), FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1794,7 +1776,7 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
|
||||
f.close();
|
||||
already = filename;
|
||||
document->setLocation(FileLocation(StorageFilePartial, filename));
|
||||
Local::writeFileLocation(mediaKey(mtpToLocationType(mtpc_inputDocumentFileLocation), document->dc, document->id), FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename));
|
||||
Local::writeFileLocation(mediaKey(DocumentFileLocation, document->dc, document->id), FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1831,24 +1813,6 @@ void MainWidget::hidePlayer() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::audioLoadFailed(FileLoader *loader, bool started) {
|
||||
mtpFileLoader *l = loader ? loader->mtpLoader() : 0;
|
||||
if (!l) return;
|
||||
|
||||
loadFailed(l, started, SLOT(audioLoadRetry()));
|
||||
AudioData *audio = App::audio(l->objId());
|
||||
if (audio) {
|
||||
if (audio->loading()) audio->cancel();
|
||||
audio->status = FileDownloadFailed;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::audioLoadRetry() {
|
||||
Ui::hideLayer();
|
||||
AudioData *audio = App::audio(failedObjId);
|
||||
if (audio) audio->save(failedFileName);
|
||||
}
|
||||
|
||||
void MainWidget::documentLoadProgress(FileLoader *loader) {
|
||||
mtpFileLoader *l = loader ? loader->mtpLoader() : 0;
|
||||
if (!l) return;
|
||||
@ -1915,9 +1879,9 @@ void MainWidget::inlineResultLoadFailed(FileLoader *loader, bool started) {
|
||||
//Ui::repaintInlineItem();
|
||||
}
|
||||
|
||||
void MainWidget::audioMarkRead(AudioData *data) {
|
||||
const AudioItems &items(App::audioItems());
|
||||
AudioItems::const_iterator i = items.constFind(data);
|
||||
void MainWidget::audioMarkRead(DocumentData *data) {
|
||||
const DocumentItems &items(App::documentItems());
|
||||
DocumentItems::const_iterator i = items.constFind(data);
|
||||
if (i != items.cend()) {
|
||||
mediaMarkRead(i.value());
|
||||
}
|
||||
@ -2428,7 +2392,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
|
||||
if (overview && overview->peer() == peer) {
|
||||
if (overview->type() != type) {
|
||||
overview->switchType(type);
|
||||
} else if (type == OverviewAudioDocuments) { // hack for player
|
||||
} else if (type == OverviewMusicFiles) { // hack for player
|
||||
showBackFromStack();
|
||||
}
|
||||
return;
|
||||
@ -2872,17 +2836,17 @@ void MainWidget::onVideosSelect() {
|
||||
}
|
||||
|
||||
void MainWidget::onSongsSelect() {
|
||||
if (overview) overview->switchType(OverviewAudioDocuments);
|
||||
if (overview) overview->switchType(OverviewMusicFiles);
|
||||
_mediaType.hideStart();
|
||||
}
|
||||
|
||||
void MainWidget::onDocumentsSelect() {
|
||||
if (overview) overview->switchType(OverviewDocuments);
|
||||
if (overview) overview->switchType(OverviewFiles);
|
||||
_mediaType.hideStart();
|
||||
}
|
||||
|
||||
void MainWidget::onAudiosSelect() {
|
||||
if (overview) overview->switchType(OverviewAudios);
|
||||
if (overview) overview->switchType(OverviewVoiceFiles);
|
||||
_mediaType.hideStart();
|
||||
}
|
||||
|
||||
|
@ -375,7 +375,7 @@ public:
|
||||
void cancelForwarding();
|
||||
void finishForwarding(History *hist, bool broadcast); // send them
|
||||
|
||||
void audioMarkRead(AudioData *data);
|
||||
void audioMarkRead(DocumentData *data);
|
||||
void videoMarkRead(VideoData *data);
|
||||
void mediaMarkRead(const HistoryItemsMap &items);
|
||||
|
||||
@ -448,9 +448,6 @@ public slots:
|
||||
void videoLoadProgress(FileLoader *loader);
|
||||
void videoLoadFailed(FileLoader *loader, bool started);
|
||||
void videoLoadRetry();
|
||||
void audioLoadProgress(FileLoader *loader);
|
||||
void audioLoadFailed(FileLoader *loader, bool started);
|
||||
void audioLoadRetry();
|
||||
void audioPlayProgress(const AudioMsgId &audioId);
|
||||
void documentLoadProgress(FileLoader *loader);
|
||||
void documentLoadFailed(FileLoader *loader, bool started);
|
||||
|
@ -363,7 +363,7 @@ void MediaView::updateControls() {
|
||||
_dateNav = myrtlrect(st::mvTextLeft, height() - st::mvTextTop, st::mvFont->width(_dateText), st::mvFont->height);
|
||||
}
|
||||
updateHeader();
|
||||
if (_photo || (_history && (_overview == OverviewPhotos || _overview == OverviewDocuments))) {
|
||||
if (_photo || (_history && (_overview == OverviewPhotos || _overview == OverviewFiles))) {
|
||||
_leftNavVisible = (_index > 0) || (_index == 0 && (
|
||||
(!_msgmigrated && _history && _history->overview[_overview].size() < _history->overviewCount(_overview)) ||
|
||||
(_msgmigrated && _migrated && _migrated->overview[_overview].size() < _migrated->overviewCount(_overview)) ||
|
||||
@ -865,7 +865,7 @@ void MediaView::showDocument(DocumentData *doc, HistoryItem *context) {
|
||||
_canForward = _msgid > 0;
|
||||
_canDelete = context ? context->canDelete() : false;
|
||||
if (_history) {
|
||||
_overview = OverviewDocuments;
|
||||
_overview = OverviewFiles;
|
||||
findCurrent();
|
||||
}
|
||||
displayDocument(doc, context);
|
||||
@ -1486,7 +1486,7 @@ void MediaView::keyPressEvent(QKeyEvent *e) {
|
||||
}
|
||||
|
||||
void MediaView::moveToNext(int32 delta) {
|
||||
if (_index < 0 || (_history && _overview != OverviewPhotos && _overview != OverviewDocuments) || (_overview == OverviewCount && !_user)) {
|
||||
if (_index < 0 || (_history && _overview != OverviewPhotos && _overview != OverviewFiles) || (_overview == OverviewCount && !_user)) {
|
||||
return;
|
||||
}
|
||||
if (_msgmigrated && !_history->overviewLoaded(_overview)) {
|
||||
@ -1515,7 +1515,7 @@ void MediaView::moveToNext(int32 delta) {
|
||||
if (HistoryMedia *media = item->getMedia()) {
|
||||
switch (media->type()) {
|
||||
case MediaTypePhoto: displayPhoto(static_cast<HistoryPhoto*>(item->getMedia())->photo(), item); preloadData(delta); break;
|
||||
case MediaTypeDocument:
|
||||
case MediaTypeFile:
|
||||
case MediaTypeGif:
|
||||
case MediaTypeSticker: displayDocument(media->getDocument(), item); preloadData(delta); break;
|
||||
}
|
||||
@ -1562,7 +1562,7 @@ void MediaView::preloadData(int32 delta) {
|
||||
if (HistoryMedia *media = item->getMedia()) {
|
||||
switch (media->type()) {
|
||||
case MediaTypePhoto: static_cast<HistoryPhoto*>(media)->photo()->forget(); break;
|
||||
case MediaTypeDocument:
|
||||
case MediaTypeFile:
|
||||
case MediaTypeGif:
|
||||
case MediaTypeSticker: media->getDocument()->forget(); break;
|
||||
}
|
||||
@ -1587,7 +1587,7 @@ void MediaView::preloadData(int32 delta) {
|
||||
if (HistoryMedia *media = item->getMedia()) {
|
||||
switch (media->type()) {
|
||||
case MediaTypePhoto: static_cast<HistoryPhoto*>(media)->photo()->download(); break;
|
||||
case MediaTypeDocument:
|
||||
case MediaTypeFile:
|
||||
case MediaTypeGif: {
|
||||
DocumentData *doc = media->getDocument();
|
||||
doc->thumb->load();
|
||||
|
@ -368,7 +368,7 @@ static const mtpTypeId mtpLayers[] = {
|
||||
mtpTypeId(mtpc_invokeWithLayer18),
|
||||
};
|
||||
static const uint32 mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]);
|
||||
static const mtpPrime mtpCurrentLayer = 45;
|
||||
static const mtpPrime mtpCurrentLayer = 46;
|
||||
|
||||
template <typename bareT>
|
||||
class MTPBoxed : public bareT {
|
||||
|
@ -388,7 +388,7 @@ bool mtpFileLoader::loadPart() {
|
||||
} else {
|
||||
switch (_locationType) {
|
||||
case VideoFileLocation: loc = MTP_inputVideoFileLocation(MTP_long(_id), MTP_long(_access)); break;
|
||||
case AudioFileLocation: loc = MTP_inputAudioFileLocation(MTP_long(_id), MTP_long(_access)); break;
|
||||
case AudioFileLocation: loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_access)); break;
|
||||
case DocumentFileLocation: loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_access)); break;
|
||||
default: cancel(true); return false; break;
|
||||
}
|
||||
|
@ -30,23 +30,6 @@ enum LocationType {
|
||||
AudioFileLocation = 0x74dc404d, // mtpc_inputAudioFileLocation
|
||||
VideoFileLocation = 0x3d0364ec, // mtpc_inputVideoFileLocation
|
||||
};
|
||||
inline LocationType mtpToLocationType(mtpTypeId type) {
|
||||
switch (type) {
|
||||
case mtpc_inputDocumentFileLocation: return DocumentFileLocation;
|
||||
case mtpc_inputAudioFileLocation: return AudioFileLocation;
|
||||
case mtpc_inputVideoFileLocation: return VideoFileLocation;
|
||||
default: return UnknownFileLocation;
|
||||
}
|
||||
}
|
||||
inline mtpTypeId mtpFromLocationType(LocationType type) {
|
||||
switch (type) {
|
||||
case DocumentFileLocation: return mtpc_inputDocumentFileLocation;
|
||||
case AudioFileLocation: return mtpc_inputAudioFileLocation;
|
||||
case VideoFileLocation: return mtpc_inputVideoFileLocation;
|
||||
case UnknownFileLocation:
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
enum StorageFileType {
|
||||
StorageFileUnknown = 0xaa963b05, // mtpc_storage_fileUnknown
|
||||
|
@ -693,34 +693,6 @@ void _serialize_inputMediaVideo(MTPStringLogger &to, int32 stage, int32 lev, Typ
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_inputMediaUploadedAudio(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ inputMediaUploadedAudio");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" file: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 2: to.add(" mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_inputMediaAudio(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ inputMediaAudio");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_inputMediaUploadedDocument(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
@ -928,20 +900,6 @@ void _serialize_inputEncryptedFileLocation(MTPStringLogger &to, int32 stage, int
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_inputAudioFileLocation(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ inputAudioFileLocation");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_inputDocumentFileLocation(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
@ -1279,14 +1237,15 @@ void _serialize_channel(MTPStringLogger &to, int32 stage, int32 lev, Types &type
|
||||
case 7: to.add(" verified: "); ++stages.back(); if (flag & MTPDchannel::flag_verified) { to.add("YES [ BY BIT 7 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break;
|
||||
case 8: to.add(" megagroup: "); ++stages.back(); if (flag & MTPDchannel::flag_megagroup) { to.add("YES [ BY BIT 8 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 8 IN FIELD flags ]"); } break;
|
||||
case 9: to.add(" restricted: "); ++stages.back(); if (flag & MTPDchannel::flag_restricted) { to.add("YES [ BY BIT 9 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 9 IN FIELD flags ]"); } break;
|
||||
case 10: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 11: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 12: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 13: to.add(" username: "); ++stages.back(); if (flag & MTPDchannel::flag_username) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break;
|
||||
case 14: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 15: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 16: to.add(" version: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 17: to.add(" restriction_reason: "); ++stages.back(); if (flag & MTPDchannel::flag_restriction_reason) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 9 IN FIELD flags ]"); } break;
|
||||
case 10: to.add(" invites_enabled: "); ++stages.back(); if (flag & MTPDchannel::flag_invites_enabled) { to.add("YES [ BY BIT 10 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 10 IN FIELD flags ]"); } break;
|
||||
case 11: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 12: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 13: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 14: to.add(" username: "); ++stages.back(); if (flag & MTPDchannel::flag_username) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break;
|
||||
case 15: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 16: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 17: to.add(" version: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 18: to.add(" restriction_reason: "); ++stages.back(); if (flag & MTPDchannel::flag_restriction_reason) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 9 IN FIELD flags ]"); } break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
@ -1587,19 +1546,6 @@ void _serialize_messageMediaDocument(MTPStringLogger &to, int32 stage, int32 lev
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_messageMediaAudio(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ messageMediaAudio");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" audio: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_messageMediaWebPage(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
@ -2189,20 +2135,6 @@ void _serialize_contactBlocked(MTPStringLogger &to, int32 stage, int32 lev, Type
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_contactSuggested(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ contactSuggested");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" mutual_contacts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_contactStatus(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
@ -2294,20 +2226,6 @@ void _serialize_contacts_blockedSlice(MTPStringLogger &to, int32 stage, int32 le
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_contacts_suggested(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ contacts_suggested");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" results: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" users: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_messages_dialogs(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
@ -2458,14 +2376,6 @@ void _serialize_inputMessagesFilterDocument(MTPStringLogger &to, int32 stage, in
|
||||
to.add("{ inputMessagesFilterDocument }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputMessagesFilterAudio(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputMessagesFilterAudio }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputMessagesFilterAudioDocuments(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputMessagesFilterAudioDocuments }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputMessagesFilterUrl(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputMessagesFilterUrl }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
@ -2474,6 +2384,14 @@ void _serialize_inputMessagesFilterGif(MTPStringLogger &to, int32 stage, int32 l
|
||||
to.add("{ inputMessagesFilterGif }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputMessagesFilterVoice(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputMessagesFilterVoice }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputMessagesFilterMusic(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputMessagesFilterMusic }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_updateNewMessage(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
@ -3067,6 +2985,21 @@ void _serialize_updateBotInlineQuery(MTPStringLogger &to, int32 stage, int32 lev
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_updateBotInlineSend(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ updateBotInlineSend");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" query: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 2: to.add(" id: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_updates_state(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
@ -3673,24 +3606,6 @@ void _serialize_messages_sentEncryptedFile(MTPStringLogger &to, int32 stage, int
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_inputAudioEmpty(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputAudioEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputAudio(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ inputAudio");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_inputDocumentEmpty(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputDocumentEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
@ -3709,38 +3624,6 @@ void _serialize_inputDocument(MTPStringLogger &to, int32 stage, int32 lev, Types
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_audioEmpty(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ audioEmpty");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_audio(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ audio");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 2: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 3: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 4: to.add(" mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 5: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 6: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_documentEmpty(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
@ -3908,10 +3791,18 @@ void _serialize_inputPrivacyKeyStatusTimestamp(MTPStringLogger &to, int32 stage,
|
||||
to.add("{ inputPrivacyKeyStatusTimestamp }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputPrivacyKeyChatInvite(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputPrivacyKeyChatInvite }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_privacyKeyStatusTimestamp(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ privacyKeyStatusTimestamp }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_privacyKeyChatInvite(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ privacyKeyChatInvite }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputPrivacyValueAllowContacts(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputPrivacyValueAllowContacts }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
@ -4092,9 +3983,12 @@ void _serialize_documentAttributeAudio(MTPStringLogger &to, int32 stage, int32 l
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 2: to.add(" performer: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" voice: "); ++stages.back(); if (flag & MTPDdocumentAttributeAudio::flag_voice) { to.add("YES [ BY BIT 10 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 10 IN FIELD flags ]"); } break;
|
||||
case 2: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 3: to.add(" title: "); ++stages.back(); if (flag & MTPDdocumentAttributeAudio::flag_title) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
|
||||
case 4: to.add(" performer: "); ++stages.back(); if (flag & MTPDdocumentAttributeAudio::flag_performer) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
|
||||
case 5: to.add(" waveform: "); ++stages.back(); if (flag & MTPDdocumentAttributeAudio::flag_waveform) { types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
@ -6373,19 +6267,6 @@ void _serialize_contacts_importContacts(MTPStringLogger &to, int32 stage, int32
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_contacts_getSuggested(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ contacts_getSuggested");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_contacts_deleteContact(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
@ -6482,10 +6363,11 @@ void _serialize_messages_getHistory(MTPStringLogger &to, int32 stage, int32 lev,
|
||||
switch (stage) {
|
||||
case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" offset_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 2: to.add(" add_offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 3: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 4: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 5: to.add(" min_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 2: to.add(" offset_date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 3: to.add(" add_offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 4: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 5: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 6: to.add(" min_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
@ -6539,10 +6421,11 @@ void _serialize_channels_getImportantHistory(MTPStringLogger &to, int32 stage, i
|
||||
switch (stage) {
|
||||
case 0: to.add(" channel: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" offset_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 2: to.add(" add_offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 3: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 4: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 5: to.add(" min_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 2: to.add(" offset_date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 3: to.add(" add_offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 4: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 5: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 6: to.add(" min_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
@ -7063,6 +6946,20 @@ void _serialize_channels_deleteChannel(MTPStringLogger &to, int32 stage, int32 l
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_channels_toggleInvites(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ channels_toggleInvites");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" channel: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" enabled: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_messages_getChats(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
@ -7678,8 +7575,6 @@ namespace {
|
||||
_serializers.insert(mtpc_inputMediaUploadedVideo, _serialize_inputMediaUploadedVideo);
|
||||
_serializers.insert(mtpc_inputMediaUploadedThumbVideo, _serialize_inputMediaUploadedThumbVideo);
|
||||
_serializers.insert(mtpc_inputMediaVideo, _serialize_inputMediaVideo);
|
||||
_serializers.insert(mtpc_inputMediaUploadedAudio, _serialize_inputMediaUploadedAudio);
|
||||
_serializers.insert(mtpc_inputMediaAudio, _serialize_inputMediaAudio);
|
||||
_serializers.insert(mtpc_inputMediaUploadedDocument, _serialize_inputMediaUploadedDocument);
|
||||
_serializers.insert(mtpc_inputMediaUploadedThumbDocument, _serialize_inputMediaUploadedThumbDocument);
|
||||
_serializers.insert(mtpc_inputMediaDocument, _serialize_inputMediaDocument);
|
||||
@ -7697,7 +7592,6 @@ namespace {
|
||||
_serializers.insert(mtpc_inputFileLocation, _serialize_inputFileLocation);
|
||||
_serializers.insert(mtpc_inputVideoFileLocation, _serialize_inputVideoFileLocation);
|
||||
_serializers.insert(mtpc_inputEncryptedFileLocation, _serialize_inputEncryptedFileLocation);
|
||||
_serializers.insert(mtpc_inputAudioFileLocation, _serialize_inputAudioFileLocation);
|
||||
_serializers.insert(mtpc_inputDocumentFileLocation, _serialize_inputDocumentFileLocation);
|
||||
_serializers.insert(mtpc_inputPhotoCropAuto, _serialize_inputPhotoCropAuto);
|
||||
_serializers.insert(mtpc_inputPhotoCrop, _serialize_inputPhotoCrop);
|
||||
@ -7751,7 +7645,6 @@ namespace {
|
||||
_serializers.insert(mtpc_messageMediaContact, _serialize_messageMediaContact);
|
||||
_serializers.insert(mtpc_messageMediaUnsupported, _serialize_messageMediaUnsupported);
|
||||
_serializers.insert(mtpc_messageMediaDocument, _serialize_messageMediaDocument);
|
||||
_serializers.insert(mtpc_messageMediaAudio, _serialize_messageMediaAudio);
|
||||
_serializers.insert(mtpc_messageMediaWebPage, _serialize_messageMediaWebPage);
|
||||
_serializers.insert(mtpc_messageMediaVenue, _serialize_messageMediaVenue);
|
||||
_serializers.insert(mtpc_messageActionEmpty, _serialize_messageActionEmpty);
|
||||
@ -7802,7 +7695,6 @@ namespace {
|
||||
_serializers.insert(mtpc_contact, _serialize_contact);
|
||||
_serializers.insert(mtpc_importedContact, _serialize_importedContact);
|
||||
_serializers.insert(mtpc_contactBlocked, _serialize_contactBlocked);
|
||||
_serializers.insert(mtpc_contactSuggested, _serialize_contactSuggested);
|
||||
_serializers.insert(mtpc_contactStatus, _serialize_contactStatus);
|
||||
_serializers.insert(mtpc_contacts_link, _serialize_contacts_link);
|
||||
_serializers.insert(mtpc_contacts_contactsNotModified, _serialize_contacts_contactsNotModified);
|
||||
@ -7810,7 +7702,6 @@ namespace {
|
||||
_serializers.insert(mtpc_contacts_importedContacts, _serialize_contacts_importedContacts);
|
||||
_serializers.insert(mtpc_contacts_blocked, _serialize_contacts_blocked);
|
||||
_serializers.insert(mtpc_contacts_blockedSlice, _serialize_contacts_blockedSlice);
|
||||
_serializers.insert(mtpc_contacts_suggested, _serialize_contacts_suggested);
|
||||
_serializers.insert(mtpc_messages_dialogs, _serialize_messages_dialogs);
|
||||
_serializers.insert(mtpc_messages_dialogsSlice, _serialize_messages_dialogsSlice);
|
||||
_serializers.insert(mtpc_messages_messages, _serialize_messages_messages);
|
||||
@ -7825,10 +7716,10 @@ namespace {
|
||||
_serializers.insert(mtpc_inputMessagesFilterPhotoVideo, _serialize_inputMessagesFilterPhotoVideo);
|
||||
_serializers.insert(mtpc_inputMessagesFilterPhotoVideoDocuments, _serialize_inputMessagesFilterPhotoVideoDocuments);
|
||||
_serializers.insert(mtpc_inputMessagesFilterDocument, _serialize_inputMessagesFilterDocument);
|
||||
_serializers.insert(mtpc_inputMessagesFilterAudio, _serialize_inputMessagesFilterAudio);
|
||||
_serializers.insert(mtpc_inputMessagesFilterAudioDocuments, _serialize_inputMessagesFilterAudioDocuments);
|
||||
_serializers.insert(mtpc_inputMessagesFilterUrl, _serialize_inputMessagesFilterUrl);
|
||||
_serializers.insert(mtpc_inputMessagesFilterGif, _serialize_inputMessagesFilterGif);
|
||||
_serializers.insert(mtpc_inputMessagesFilterVoice, _serialize_inputMessagesFilterVoice);
|
||||
_serializers.insert(mtpc_inputMessagesFilterMusic, _serialize_inputMessagesFilterMusic);
|
||||
_serializers.insert(mtpc_updateNewMessage, _serialize_updateNewMessage);
|
||||
_serializers.insert(mtpc_updateMessageID, _serialize_updateMessageID);
|
||||
_serializers.insert(mtpc_updateDeleteMessages, _serialize_updateDeleteMessages);
|
||||
@ -7871,6 +7762,7 @@ namespace {
|
||||
_serializers.insert(mtpc_updateStickerSets, _serialize_updateStickerSets);
|
||||
_serializers.insert(mtpc_updateSavedGifs, _serialize_updateSavedGifs);
|
||||
_serializers.insert(mtpc_updateBotInlineQuery, _serialize_updateBotInlineQuery);
|
||||
_serializers.insert(mtpc_updateBotInlineSend, _serialize_updateBotInlineSend);
|
||||
_serializers.insert(mtpc_updates_state, _serialize_updates_state);
|
||||
_serializers.insert(mtpc_updates_differenceEmpty, _serialize_updates_differenceEmpty);
|
||||
_serializers.insert(mtpc_updates_difference, _serialize_updates_difference);
|
||||
@ -7910,12 +7802,8 @@ namespace {
|
||||
_serializers.insert(mtpc_messages_dhConfig, _serialize_messages_dhConfig);
|
||||
_serializers.insert(mtpc_messages_sentEncryptedMessage, _serialize_messages_sentEncryptedMessage);
|
||||
_serializers.insert(mtpc_messages_sentEncryptedFile, _serialize_messages_sentEncryptedFile);
|
||||
_serializers.insert(mtpc_inputAudioEmpty, _serialize_inputAudioEmpty);
|
||||
_serializers.insert(mtpc_inputAudio, _serialize_inputAudio);
|
||||
_serializers.insert(mtpc_inputDocumentEmpty, _serialize_inputDocumentEmpty);
|
||||
_serializers.insert(mtpc_inputDocument, _serialize_inputDocument);
|
||||
_serializers.insert(mtpc_audioEmpty, _serialize_audioEmpty);
|
||||
_serializers.insert(mtpc_audio, _serialize_audio);
|
||||
_serializers.insert(mtpc_documentEmpty, _serialize_documentEmpty);
|
||||
_serializers.insert(mtpc_document, _serialize_document);
|
||||
_serializers.insert(mtpc_help_support, _serialize_help_support);
|
||||
@ -7935,7 +7823,9 @@ namespace {
|
||||
_serializers.insert(mtpc_sendMessageChooseContactAction, _serialize_sendMessageChooseContactAction);
|
||||
_serializers.insert(mtpc_contacts_found, _serialize_contacts_found);
|
||||
_serializers.insert(mtpc_inputPrivacyKeyStatusTimestamp, _serialize_inputPrivacyKeyStatusTimestamp);
|
||||
_serializers.insert(mtpc_inputPrivacyKeyChatInvite, _serialize_inputPrivacyKeyChatInvite);
|
||||
_serializers.insert(mtpc_privacyKeyStatusTimestamp, _serialize_privacyKeyStatusTimestamp);
|
||||
_serializers.insert(mtpc_privacyKeyChatInvite, _serialize_privacyKeyChatInvite);
|
||||
_serializers.insert(mtpc_inputPrivacyValueAllowContacts, _serialize_inputPrivacyValueAllowContacts);
|
||||
_serializers.insert(mtpc_inputPrivacyValueAllowAll, _serialize_inputPrivacyValueAllowAll);
|
||||
_serializers.insert(mtpc_inputPrivacyValueAllowUsers, _serialize_inputPrivacyValueAllowUsers);
|
||||
@ -8133,7 +8023,6 @@ namespace {
|
||||
_serializers.insert(mtpc_contacts_getStatuses, _serialize_contacts_getStatuses);
|
||||
_serializers.insert(mtpc_contacts_getContacts, _serialize_contacts_getContacts);
|
||||
_serializers.insert(mtpc_contacts_importContacts, _serialize_contacts_importContacts);
|
||||
_serializers.insert(mtpc_contacts_getSuggested, _serialize_contacts_getSuggested);
|
||||
_serializers.insert(mtpc_contacts_deleteContact, _serialize_contacts_deleteContact);
|
||||
_serializers.insert(mtpc_contacts_getBlocked, _serialize_contacts_getBlocked);
|
||||
_serializers.insert(mtpc_contacts_exportCard, _serialize_contacts_exportCard);
|
||||
@ -8180,6 +8069,7 @@ namespace {
|
||||
_serializers.insert(mtpc_channels_inviteToChannel, _serialize_channels_inviteToChannel);
|
||||
_serializers.insert(mtpc_channels_kickFromChannel, _serialize_channels_kickFromChannel);
|
||||
_serializers.insert(mtpc_channels_deleteChannel, _serialize_channels_deleteChannel);
|
||||
_serializers.insert(mtpc_channels_toggleInvites, _serialize_channels_toggleInvites);
|
||||
_serializers.insert(mtpc_messages_getChats, _serialize_messages_getChats);
|
||||
_serializers.insert(mtpc_channels_getChannels, _serialize_channels_getChannels);
|
||||
_serializers.insert(mtpc_messages_getFullChat, _serialize_messages_getFullChat);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -153,8 +153,6 @@ inputMediaContact#a6e45987 phone_number:string first_name:string last_name:strin
|
||||
inputMediaUploadedVideo#82713fdf file:InputFile duration:int w:int h:int mime_type:string caption:string = InputMedia;
|
||||
inputMediaUploadedThumbVideo#7780ddf9 file:InputFile thumb:InputFile duration:int w:int h:int mime_type:string caption:string = InputMedia;
|
||||
inputMediaVideo#936a4ebd id:InputVideo caption:string = InputMedia;
|
||||
inputMediaUploadedAudio#4e498cab file:InputFile duration:int mime_type:string = InputMedia;
|
||||
inputMediaAudio#89938781 id:InputAudio = InputMedia;
|
||||
inputMediaUploadedDocument#1d89306d file:InputFile mime_type:string attributes:Vector<DocumentAttribute> caption:string = InputMedia;
|
||||
inputMediaUploadedThumbDocument#ad613491 file:InputFile thumb:InputFile mime_type:string attributes:Vector<DocumentAttribute> caption:string = InputMedia;
|
||||
inputMediaDocument#1a77f29c id:InputDocument caption:string = InputMedia;
|
||||
@ -177,7 +175,6 @@ inputVideo#ee579652 id:long access_hash:long = InputVideo;
|
||||
inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation;
|
||||
inputVideoFileLocation#3d0364ec id:long access_hash:long = InputFileLocation;
|
||||
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
|
||||
inputAudioFileLocation#74dc404d id:long access_hash:long = InputFileLocation;
|
||||
inputDocumentFileLocation#4e45abe9 id:long access_hash:long = InputFileLocation;
|
||||
|
||||
inputPhotoCropAuto#ade6b004 = InputPhotoCrop;
|
||||
@ -219,7 +216,7 @@ userStatusLastMonth#77ebc742 = UserStatus;
|
||||
chatEmpty#9ba2d800 id:int = Chat;
|
||||
chat#d91cdd54 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true admins_enabled:flags.3?true admin:flags.4?true deactivated:flags.5?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel = Chat;
|
||||
chatForbidden#7328bdb id:int title:string = Chat;
|
||||
channel#4b1b7506 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true editor:flags.3?true moderator:flags.4?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true id:int access_hash:long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string = Chat;
|
||||
channel#4b1b7506 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true editor:flags.3?true moderator:flags.4?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true invites_enabled:flags.10?true id:int access_hash:long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string = Chat;
|
||||
channelForbidden#2d85832c id:int access_hash:long title:string = Chat;
|
||||
|
||||
chatFull#2e02a614 id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> = ChatFull;
|
||||
@ -246,7 +243,6 @@ messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
|
||||
messageMediaContact#5e7d2f39 phone_number:string first_name:string last_name:string user_id:int = MessageMedia;
|
||||
messageMediaUnsupported#9f84f49e = MessageMedia;
|
||||
messageMediaDocument#f3e02ea8 document:Document caption:string = MessageMedia;
|
||||
messageMediaAudio#c6b68300 audio:Audio = MessageMedia;
|
||||
messageMediaWebPage#a32dd600 webpage:WebPage = MessageMedia;
|
||||
messageMediaVenue#7912b71f geo:GeoPoint title:string address:string provider:string venue_id:string = MessageMedia;
|
||||
|
||||
@ -319,8 +315,6 @@ importedContact#d0028438 user_id:int client_id:long = ImportedContact;
|
||||
|
||||
contactBlocked#561bc879 user_id:int date:int = ContactBlocked;
|
||||
|
||||
contactSuggested#3de191a1 user_id:int mutual_contacts:int = ContactSuggested;
|
||||
|
||||
contactStatus#d3680c61 user_id:int status:UserStatus = ContactStatus;
|
||||
|
||||
contacts.link#3ace484c my_link:ContactLink foreign_link:ContactLink user:User = contacts.Link;
|
||||
@ -333,8 +327,6 @@ contacts.importedContacts#ad524315 imported:Vector<ImportedContact> retry_contac
|
||||
contacts.blocked#1c138d15 blocked:Vector<ContactBlocked> users:Vector<User> = contacts.Blocked;
|
||||
contacts.blockedSlice#900802a1 count:int blocked:Vector<ContactBlocked> users:Vector<User> = contacts.Blocked;
|
||||
|
||||
contacts.suggested#5649dcc5 results:Vector<ContactSuggested> users:Vector<User> = contacts.Suggested;
|
||||
|
||||
messages.dialogs#15ba6c40 dialogs:Vector<Dialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Dialogs;
|
||||
messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Dialogs;
|
||||
|
||||
@ -354,10 +346,10 @@ inputMessagesFilterVideo#9fc00e65 = MessagesFilter;
|
||||
inputMessagesFilterPhotoVideo#56e9f0e4 = MessagesFilter;
|
||||
inputMessagesFilterPhotoVideoDocuments#d95e73bb = MessagesFilter;
|
||||
inputMessagesFilterDocument#9eddf188 = MessagesFilter;
|
||||
inputMessagesFilterAudio#cfc87522 = MessagesFilter;
|
||||
inputMessagesFilterAudioDocuments#5afbf764 = MessagesFilter;
|
||||
inputMessagesFilterUrl#7ef0dd87 = MessagesFilter;
|
||||
inputMessagesFilterGif#ffc86587 = MessagesFilter;
|
||||
inputMessagesFilterVoice#50f5c392 = MessagesFilter;
|
||||
inputMessagesFilterMusic#3751b49e = MessagesFilter;
|
||||
|
||||
updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
|
||||
updateMessageID#4e90bfd6 id:int random_id:long = Update;
|
||||
@ -401,6 +393,7 @@ updateStickerSetsOrder#f0dfb451 order:Vector<long> = Update;
|
||||
updateStickerSets#43ae3dec = Update;
|
||||
updateSavedGifs#9375341e = Update;
|
||||
updateBotInlineQuery#c01eea08 query_id:long user_id:int query:string offset:string = Update;
|
||||
updateBotInlineSend#f69e113 user_id:int query:string id:string = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
@ -459,15 +452,9 @@ messages.dhConfig#2c221edd g:int p:bytes version:int random:bytes = messages.DhC
|
||||
messages.sentEncryptedMessage#560f8935 date:int = messages.SentEncryptedMessage;
|
||||
messages.sentEncryptedFile#9493ff32 date:int file:EncryptedFile = messages.SentEncryptedMessage;
|
||||
|
||||
inputAudioEmpty#d95adc84 = InputAudio;
|
||||
inputAudio#77d440ff id:long access_hash:long = InputAudio;
|
||||
|
||||
inputDocumentEmpty#72f0eaae = InputDocument;
|
||||
inputDocument#18798952 id:long access_hash:long = InputDocument;
|
||||
|
||||
audioEmpty#586988d8 id:long = Audio;
|
||||
audio#f9e35055 id:long access_hash:long date:int duration:int mime_type:string size:int dc_id:int = Audio;
|
||||
|
||||
documentEmpty#36f8c871 id:long = Document;
|
||||
document#f9a39f4f id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector<DocumentAttribute> = Document;
|
||||
|
||||
@ -492,8 +479,10 @@ sendMessageChooseContactAction#628cbc6f = SendMessageAction;
|
||||
contacts.found#1aa1f784 results:Vector<Peer> chats:Vector<Chat> users:Vector<User> = contacts.Found;
|
||||
|
||||
inputPrivacyKeyStatusTimestamp#4f96cb18 = InputPrivacyKey;
|
||||
inputPrivacyKeyChatInvite#bdfb0426 = InputPrivacyKey;
|
||||
|
||||
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
|
||||
privacyKeyChatInvite#500e6dfa = PrivacyKey;
|
||||
|
||||
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
|
||||
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
|
||||
@ -519,7 +508,7 @@ documentAttributeImageSize#6c37c15c w:int h:int = DocumentAttribute;
|
||||
documentAttributeAnimated#11b58939 = DocumentAttribute;
|
||||
documentAttributeSticker#3a556302 alt:string stickerset:InputStickerSet = DocumentAttribute;
|
||||
documentAttributeVideo#5910cccb duration:int w:int h:int = DocumentAttribute;
|
||||
documentAttributeAudio#ded218e0 duration:int title:string performer:string = DocumentAttribute;
|
||||
documentAttributeAudio#9852f9c6 flags:# voice:flags.10?true duration:int title:flags.0?string performer:flags.1?string waveform:flags.2?bytes = DocumentAttribute;
|
||||
documentAttributeFilename#15590068 file_name:string = DocumentAttribute;
|
||||
|
||||
messages.stickersNotModified#f1749a22 = messages.Stickers;
|
||||
@ -552,7 +541,7 @@ account.password#7c18141c current_salt:bytes new_salt:bytes hint:string has_reco
|
||||
|
||||
account.passwordSettings#b7b72ab3 email:string = account.PasswordSettings;
|
||||
|
||||
account.passwordInputSettings#bcfc532c flags:# new_salt:flags.0?bytes new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string = account.PasswordInputSettings;
|
||||
account.passwordInputSettings#86916deb flags:# new_salt:flags.0?bytes new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string = account.PasswordInputSettings;
|
||||
|
||||
auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery;
|
||||
|
||||
@ -717,7 +706,6 @@ users.getFullUser#ca30a5b1 id:InputUser = UserFull;
|
||||
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
|
||||
contacts.getContacts#22c6aa08 hash:string = contacts.Contacts;
|
||||
contacts.importContacts#da30b32d contacts:Vector<InputContact> replace:Bool = contacts.ImportedContacts;
|
||||
contacts.getSuggested#cd773428 limit:int = contacts.Suggested;
|
||||
contacts.deleteContact#8e953744 id:InputUser = contacts.Link;
|
||||
contacts.deleteContacts#59ab389e id:Vector<InputUser> = Bool;
|
||||
contacts.block#332b49fc id:InputUser = Bool;
|
||||
@ -730,7 +718,7 @@ contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer;
|
||||
|
||||
messages.getMessages#4222fa74 id:Vector<int> = messages.Messages;
|
||||
messages.getDialogs#6b47f94d offset_date:int offset_id:int offset_peer:InputPeer limit:int = messages.Dialogs;
|
||||
messages.getHistory#8a8ec2da peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
messages.getHistory#afa92846 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
messages.search#d4569248 flags:# important_only:flags.0?true peer:InputPeer q:string filter:MessagesFilter min_date:int max_date:int offset:int max_id:int limit:int = messages.Messages;
|
||||
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
|
||||
messages.deleteHistory#b7c13bd9 peer:InputPeer max_id:int = messages.AffectedHistory;
|
||||
@ -808,7 +796,7 @@ help.getAppChangelog#5bab7fb2 device_model:string system_version:string app_vers
|
||||
help.getTermsOfService#37d78f83 lang_code:string = help.TermsOfService;
|
||||
|
||||
channels.getDialogs#a9d3d249 offset:int limit:int = messages.Dialogs;
|
||||
channels.getImportantHistory#ddb929cb channel:InputChannel offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
channels.getImportantHistory#8f494bb2 channel:InputChannel offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
|
||||
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
|
||||
channels.deleteUserHistory#d10dd71b channel:InputChannel user_id:InputUser = messages.AffectedHistory;
|
||||
@ -832,3 +820,4 @@ channels.inviteToChannel#199f3a6c channel:InputChannel users:Vector<InputUser> =
|
||||
channels.kickFromChannel#a672de14 channel:InputChannel user_id:InputUser kicked:Bool = Updates;
|
||||
channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite;
|
||||
channels.deleteChannel#c0111fe3 channel:InputChannel = Updates;
|
||||
channels.toggleInvites#49609307 channel:InputChannel enabled:Bool = Updates;
|
||||
|
@ -39,7 +39,7 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerD
|
||||
, _resizeSkip(0)
|
||||
, _peer(peer->migrateTo() ? peer->migrateTo() : peer)
|
||||
, _type(type)
|
||||
, _reversed(_type != OverviewDocuments && _type != OverviewLinks)
|
||||
, _reversed(_type != OverviewFiles && _type != OverviewLinks)
|
||||
, _migrated(_peer->migrateFrom() ? App::history(_peer->migrateFrom()->id) : 0)
|
||||
, _history(App::history(_peer->id))
|
||||
, _channel(peerToChannel(_peer->id))
|
||||
@ -108,7 +108,7 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerD
|
||||
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages()));
|
||||
|
||||
_cancelSearch.hide();
|
||||
if (_type == OverviewLinks || _type == OverviewDocuments) {
|
||||
if (_type == OverviewLinks || _type == OverviewFiles) {
|
||||
_search.show();
|
||||
} else {
|
||||
_search.hide();
|
||||
@ -735,7 +735,7 @@ QPoint OverviewInner::mapMouseToItem(QPoint p, MsgId itemId, int32 itemIndex) {
|
||||
}
|
||||
|
||||
void OverviewInner::activate() {
|
||||
if (_type == OverviewLinks || _type == OverviewDocuments) {
|
||||
if (_type == OverviewLinks || _type == OverviewFiles) {
|
||||
_search.setFocus();
|
||||
} else {
|
||||
setFocus();
|
||||
@ -759,7 +759,7 @@ void OverviewInner::clear() {
|
||||
}
|
||||
|
||||
int32 OverviewInner::itemTop(const FullMsgId &msgId) const {
|
||||
if (_type == OverviewAudioDocuments) {
|
||||
if (_type == OverviewMusicFiles) {
|
||||
int32 itemIndex = -1;
|
||||
fixItemIndex(itemIndex, (msgId.channel == _channel) ? msgId.msg : ((_migrated && msgId.channel == _migrated->channelId()) ? -msgId.msg : 0));
|
||||
if (itemIndex >= 0) {
|
||||
@ -1261,9 +1261,9 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||
_contextMenuLnk = textlnkOver();
|
||||
PhotoLink *lnkPhoto = dynamic_cast<PhotoLink*>(_contextMenuLnk.data());
|
||||
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
|
||||
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
|
||||
if (lnkPhoto || lnkVideo || lnkAudio || lnkDocument) {
|
||||
bool lnkIsAudio = lnkDocument ? lnkDocument->document()->voice() : false;
|
||||
if (lnkPhoto || lnkVideo || lnkDocument) {
|
||||
_menu = new PopupMenu();
|
||||
if (App::hoveredLinkItem()) {
|
||||
_menu->addAction(lang(lng_context_to_msg), this, SLOT(goToMessage()))->setEnabled(true);
|
||||
@ -1271,14 +1271,14 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||
if (lnkPhoto) {
|
||||
_menu->addAction(lang(lng_context_open_image), this, SLOT(openContextUrl()))->setEnabled(true);
|
||||
} else {
|
||||
if ((lnkVideo && lnkVideo->video()->loading()) || (lnkAudio && lnkAudio->audio()->loading()) || (lnkDocument && lnkDocument->document()->loading())) {
|
||||
if ((lnkVideo && lnkVideo->video()->loading()) || (lnkDocument && lnkDocument->document()->loading())) {
|
||||
_menu->addAction(lang(lng_context_cancel_download), this, SLOT(cancelContextDownload()))->setEnabled(true);
|
||||
} else {
|
||||
if ((lnkVideo && !lnkVideo->video()->already(true).isEmpty()) || (lnkAudio && !lnkAudio->audio()->already(true).isEmpty()) || (lnkDocument && !lnkDocument->document()->already(true).isEmpty())) {
|
||||
if ((lnkVideo && !lnkVideo->video()->already(true).isEmpty()) || (lnkDocument && !lnkDocument->document()->already(true).isEmpty())) {
|
||||
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), this, SLOT(showContextInFolder()))->setEnabled(true);
|
||||
}
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_open_video : (lnkAudio ? lng_context_open_audio : lng_context_open_file)), this, SLOT(openContextFile()))->setEnabled(true);
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_save_video : (lnkAudio ? lng_context_save_audio : lng_context_save_file)), this, SLOT(saveContextFile()))->setEnabled(true);
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_open_video : (lnkIsAudio ? lng_context_open_audio : lng_context_open_file)), this, SLOT(openContextFile()))->setEnabled(true);
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_save_video : (lnkIsAudio ? lng_context_save_audio : lng_context_save_file)), this, SLOT(saveContextFile()))->setEnabled(true);
|
||||
}
|
||||
}
|
||||
if (isUponSelected > 1) {
|
||||
@ -1420,8 +1420,8 @@ void OverviewInner::switchType(MediaOverviewType type) {
|
||||
if (_type != type) {
|
||||
clear();
|
||||
_type = type;
|
||||
_reversed = (_type != OverviewLinks && _type != OverviewDocuments);
|
||||
if (_type == OverviewLinks || _type == OverviewDocuments) {
|
||||
_reversed = (_type != OverviewLinks && _type != OverviewFiles);
|
||||
if (_type == OverviewLinks || _type == OverviewFiles) {
|
||||
_search.show();
|
||||
} else {
|
||||
_search.hide();
|
||||
@ -1502,12 +1502,9 @@ void OverviewInner::selectMessage() {
|
||||
|
||||
void OverviewInner::cancelContextDownload() {
|
||||
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
|
||||
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
|
||||
if (lnkVideo) {
|
||||
lnkVideo->video()->cancel();
|
||||
} else if (lnkAudio) {
|
||||
lnkAudio->audio()->cancel();
|
||||
} else if (lnkDocument) {
|
||||
lnkDocument->document()->cancel();
|
||||
}
|
||||
@ -1515,18 +1512,15 @@ void OverviewInner::cancelContextDownload() {
|
||||
|
||||
void OverviewInner::showContextInFolder() {
|
||||
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
|
||||
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
|
||||
QString already = lnkVideo ? lnkVideo->video()->already(true) : (lnkAudio ? lnkAudio->audio()->already(true) : (lnkDocument ? lnkDocument->document()->already(true) : QString()));
|
||||
QString already = lnkVideo ? lnkVideo->video()->already(true) : (lnkDocument ? lnkDocument->document()->already(true) : QString());
|
||||
if (!already.isEmpty()) psShowInFolder(already);
|
||||
}
|
||||
|
||||
void OverviewInner::saveContextFile() {
|
||||
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
|
||||
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
|
||||
if (lnkVideo) VideoSaveLink::doSave(lnkVideo->video(), true);
|
||||
if (lnkAudio) AudioSaveLink::doSave(lnkAudio->audio(), true);
|
||||
if (lnkDocument) DocumentSaveLink::doSave(lnkDocument->document(), true);
|
||||
}
|
||||
|
||||
@ -1534,10 +1528,8 @@ void OverviewInner::openContextFile() {
|
||||
HistoryItem *was = App::hoveredLinkItem();
|
||||
App::hoveredLinkItem(App::contextItem());
|
||||
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
|
||||
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
|
||||
if (lnkVideo) VideoOpenLink(lnkVideo->video()).onClick(Qt::LeftButton);
|
||||
if (lnkAudio) AudioOpenLink(lnkAudio->audio()).onClick(Qt::LeftButton);
|
||||
if (lnkDocument) DocumentOpenLink(lnkDocument->document()).onClick(Qt::LeftButton);
|
||||
App::hoveredLinkItem(was);
|
||||
}
|
||||
@ -1581,7 +1573,7 @@ void OverviewInner::onNeedSearchMessages() {
|
||||
}
|
||||
|
||||
void OverviewInner::onSearchUpdate() {
|
||||
QString filterText = (_type == OverviewLinks || _type == OverviewDocuments) ? _search.text().trimmed() : QString();
|
||||
QString filterText = (_type == OverviewLinks || _type == OverviewFiles) ? _search.text().trimmed() : QString();
|
||||
bool inSearch = !filterText.isEmpty(), changed = (inSearch != _inSearch);
|
||||
_inSearch = inSearch;
|
||||
|
||||
@ -1729,7 +1721,7 @@ void OverviewInner::mediaOverviewUpdated() {
|
||||
|
||||
_height = countHeight();
|
||||
} else {
|
||||
bool dateEveryMonth = (_type == OverviewDocuments), dateEveryDay = (_type == OverviewLinks);
|
||||
bool dateEveryMonth = (_type == OverviewFiles), dateEveryDay = (_type == OverviewLinks);
|
||||
bool withDates = (dateEveryMonth || dateEveryDay);
|
||||
|
||||
History::MediaOverview &o(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0;
|
||||
@ -1793,7 +1785,7 @@ void OverviewInner::mediaOverviewUpdated() {
|
||||
int32 newHeight = _marginTop + _height + _marginBottom, deltaHeight = newHeight - height();
|
||||
if (deltaHeight) {
|
||||
resize(_width, newHeight);
|
||||
if (_type != OverviewLinks && _type != OverviewDocuments) {
|
||||
if (_type != OverviewLinks && _type != OverviewFiles) {
|
||||
_overview->scrollBy(deltaHeight);
|
||||
}
|
||||
} else {
|
||||
@ -1909,10 +1901,10 @@ void OverviewInner::recountMargins() {
|
||||
if (_type == OverviewPhotos || _type == OverviewVideos) {
|
||||
_marginBottom = 0;
|
||||
_marginTop = qMax(_minHeight - _height - _marginBottom, 0);
|
||||
} else if (_type == OverviewAudioDocuments) {
|
||||
} else if (_type == OverviewMusicFiles) {
|
||||
_marginTop = st::playlistPadding;
|
||||
_marginBottom = qMax(_minHeight - _height - _marginTop, int32(st::playlistPadding));
|
||||
} else if (_type == OverviewLinks || _type == OverviewDocuments) {
|
||||
} else if (_type == OverviewLinks || _type == OverviewFiles) {
|
||||
_marginTop = st::linksSearchMargin.top() + _search.height() + st::linksSearchMargin.bottom();
|
||||
_marginBottom = qMax(_minHeight - _height - _marginTop, int32(st::playlistPadding));
|
||||
} else {
|
||||
@ -1940,15 +1932,15 @@ LayoutMediaItem *OverviewInner::layoutPrepare(HistoryItem *item) {
|
||||
i.value()->initDimensions();
|
||||
}
|
||||
}
|
||||
} else if (_type == OverviewAudios) {
|
||||
if (media && media->type() == MediaTypeAudio) {
|
||||
} else if (_type == OverviewVoiceFiles) {
|
||||
if (media && (media->type() == MediaTypeVoiceFile)) {
|
||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
||||
i = _layoutItems.insert(item, new LayoutOverviewAudio(static_cast<HistoryAudio*>(media)->audio(), item));
|
||||
i = _layoutItems.insert(item, new LayoutOverviewVoice(media->getDocument(), item));
|
||||
i.value()->initDimensions();
|
||||
}
|
||||
}
|
||||
} else if (_type == OverviewDocuments || _type == OverviewAudioDocuments) {
|
||||
if (media && (media->type() == MediaTypeDocument || media->type() == MediaTypeGif)) {
|
||||
} else if (_type == OverviewFiles || _type == OverviewMusicFiles) {
|
||||
if (media && (media->type() == MediaTypeFile || media->type() == MediaTypeMusicFile || media->type() == MediaTypeGif)) {
|
||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
||||
i = _layoutItems.insert(item, new LayoutOverviewDocument(media->getDocument(), item));
|
||||
i.value()->initDimensions();
|
||||
@ -2032,7 +2024,7 @@ void OverviewWidget::onScroll() {
|
||||
int32 preloadThreshold = _scroll.height() * 5;
|
||||
bool needToPreload = false;
|
||||
do {
|
||||
needToPreload = (type() == OverviewLinks || type() == OverviewDocuments) ? (_scroll.scrollTop() + preloadThreshold > _scroll.scrollTopMax()) : (_scroll.scrollTop() < preloadThreshold);
|
||||
needToPreload = (type() == OverviewLinks || type() == OverviewFiles) ? (_scroll.scrollTop() + preloadThreshold > _scroll.scrollTopMax()) : (_scroll.scrollTop() < preloadThreshold);
|
||||
if (!needToPreload || !_inner.preloadLocal()) {
|
||||
break;
|
||||
}
|
||||
@ -2097,7 +2089,7 @@ void OverviewWidget::scrollBy(int32 add) {
|
||||
}
|
||||
|
||||
void OverviewWidget::scrollReset() {
|
||||
_scroll.scrollToY((type() == OverviewLinks || type() == OverviewDocuments) ? 0 : _scroll.scrollTopMax());
|
||||
_scroll.scrollToY((type() == OverviewLinks || type() == OverviewFiles) ? 0 : _scroll.scrollTopMax());
|
||||
}
|
||||
|
||||
void OverviewWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth) {
|
||||
@ -2142,9 +2134,9 @@ void OverviewWidget::switchType(MediaOverviewType type) {
|
||||
switch (type) {
|
||||
case OverviewPhotos: _header = lang(lng_profile_photos_header); break;
|
||||
case OverviewVideos: _header = lang(lng_profile_videos_header); break;
|
||||
case OverviewAudioDocuments: _header = lang(lng_profile_songs_header); break;
|
||||
case OverviewDocuments: _header = lang(lng_profile_files_header); break;
|
||||
case OverviewAudios: _header = lang(lng_profile_audios_header); break;
|
||||
case OverviewMusicFiles: _header = lang(lng_profile_songs_header); break;
|
||||
case OverviewFiles: _header = lang(lng_profile_files_header); break;
|
||||
case OverviewVoiceFiles: _header = lang(lng_profile_audios_header); break;
|
||||
case OverviewLinks: _header = lang(lng_profile_shared_links_header); break;
|
||||
}
|
||||
noSelectingScroll();
|
||||
@ -2183,7 +2175,7 @@ int32 OverviewWidget::lastScrollTop() const {
|
||||
}
|
||||
|
||||
int32 OverviewWidget::countBestScroll() const {
|
||||
if (type() == OverviewAudioDocuments && audioPlayer()) {
|
||||
if (type() == OverviewMusicFiles && audioPlayer()) {
|
||||
SongMsgId playing;
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
audioPlayer()->currentState(&playing, &playingState);
|
||||
@ -2193,7 +2185,7 @@ int32 OverviewWidget::countBestScroll() const {
|
||||
return snap(top - int(_scroll.height() - (st::msgPadding.top() + st::mediaThumbSize + st::msgPadding.bottom())) / 2, 0, _scroll.scrollTopMax());
|
||||
}
|
||||
}
|
||||
} else if (type() == OverviewLinks || type() == OverviewDocuments) {
|
||||
} else if (type() == OverviewLinks || type() == OverviewFiles) {
|
||||
return 0;
|
||||
}
|
||||
return _scroll.scrollTopMax();
|
||||
@ -2350,7 +2342,7 @@ void OverviewWidget::onScrollTimer() {
|
||||
}
|
||||
|
||||
void OverviewWidget::onPlayerSongChanged(const FullMsgId &msgId) {
|
||||
if (type() == OverviewAudioDocuments) {
|
||||
if (type() == OverviewMusicFiles) {
|
||||
// int32 top = _inner.itemTop(msgId);
|
||||
// if (top > 0) {
|
||||
// _scroll.scrollToY(snap(top - int(_scroll.height() - (st::msgPadding.top() + st::mediaThumbSize + st::msgPadding.bottom())) / 2, 0, _scroll.scrollTopMax()));
|
||||
|
@ -198,7 +198,7 @@ void PlayerWidget::mousePressEvent(QMouseEvent *e) {
|
||||
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
|
||||
if (playing == _song && playingDuration) {
|
||||
if (playingState == AudioPlayerPlaying || playingState == AudioPlayerStarting || playingState == AudioPlayerResuming) {
|
||||
audioPlayer()->pauseresume(OverviewDocuments);
|
||||
audioPlayer()->pauseresume(OverviewFiles);
|
||||
}
|
||||
_down = OverPlayback;
|
||||
_downProgress = snap((pos.x() - _playbackRect.x()) / float64(_playbackRect.width()), 0., 1.);
|
||||
@ -210,7 +210,7 @@ void PlayerWidget::mousePressEvent(QMouseEvent *e) {
|
||||
}
|
||||
} else if (_over == OverFull && _song) {
|
||||
if (HistoryItem *item = App::histItemById(_song.msgId)) {
|
||||
App::main()->showMediaOverview(item->history()->peer, OverviewAudioDocuments);
|
||||
App::main()->showMediaOverview(item->history()->peer, OverviewMusicFiles);
|
||||
}
|
||||
} else if (_over == OverRepeat) {
|
||||
_repeat = !_repeat;
|
||||
@ -269,23 +269,23 @@ void PlayerWidget::updateControls() {
|
||||
_fullAvailable = (_index >= 0);
|
||||
|
||||
History *history = _msgmigrated ? _migrated : _history;
|
||||
_prevAvailable = _fullAvailable && ((_index > 0) || (_index == 0 && _migrated && !_msgmigrated && !_migrated->overview[OverviewAudioDocuments].isEmpty()));
|
||||
_nextAvailable = _fullAvailable && ((_index < history->overview[OverviewAudioDocuments].size() - 1) || (_msgmigrated && _index == _migrated->overview[OverviewAudioDocuments].size() - 1 && _history->overviewLoaded(OverviewAudioDocuments) && _history->overviewCount(OverviewAudioDocuments) > 0));
|
||||
_prevAvailable = _fullAvailable && ((_index > 0) || (_index == 0 && _migrated && !_msgmigrated && !_migrated->overview[OverviewMusicFiles].isEmpty()));
|
||||
_nextAvailable = _fullAvailable && ((_index < history->overview[OverviewMusicFiles].size() - 1) || (_msgmigrated && _index == _migrated->overview[OverviewMusicFiles].size() - 1 && _history->overviewLoaded(OverviewMusicFiles) && _history->overviewCount(OverviewMusicFiles) > 0));
|
||||
resizeEvent(0);
|
||||
update();
|
||||
if (_index >= 0 && _index < MediaOverviewStartPerPage) {
|
||||
if (!_history->overviewLoaded(OverviewAudioDocuments) || (_migrated && !_migrated->overviewLoaded(OverviewAudioDocuments))) {
|
||||
if (!_history->overviewLoaded(OverviewMusicFiles) || (_migrated && !_migrated->overviewLoaded(OverviewMusicFiles))) {
|
||||
if (App::main()) {
|
||||
if (_msgmigrated || (_migrated && _index == 0 && _history->overviewLoaded(OverviewAudioDocuments))) {
|
||||
App::main()->loadMediaBack(_migrated->peer, OverviewAudioDocuments);
|
||||
if (_msgmigrated || (_migrated && _index == 0 && _history->overviewLoaded(OverviewMusicFiles))) {
|
||||
App::main()->loadMediaBack(_migrated->peer, OverviewMusicFiles);
|
||||
} else {
|
||||
App::main()->loadMediaBack(_history->peer, OverviewAudioDocuments);
|
||||
if (_migrated && _index == 0 && _migrated->overview[OverviewAudioDocuments].isEmpty() && !_migrated->overviewLoaded(OverviewAudioDocuments)) {
|
||||
App::main()->loadMediaBack(_migrated->peer, OverviewAudioDocuments);
|
||||
App::main()->loadMediaBack(_history->peer, OverviewMusicFiles);
|
||||
if (_migrated && _index == 0 && _migrated->overview[OverviewMusicFiles].isEmpty() && !_migrated->overviewLoaded(OverviewMusicFiles)) {
|
||||
App::main()->loadMediaBack(_migrated->peer, OverviewMusicFiles);
|
||||
}
|
||||
}
|
||||
if (_msgmigrated && !_history->overviewCountLoaded(OverviewAudioDocuments)) {
|
||||
App::main()->preloadOverview(_history->peer, OverviewAudioDocuments);
|
||||
if (_msgmigrated && !_history->overviewCountLoaded(OverviewMusicFiles)) {
|
||||
App::main()->preloadOverview(_history->peer, OverviewMusicFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -296,7 +296,7 @@ void PlayerWidget::findCurrent() {
|
||||
_index = -1;
|
||||
if (!_history) return;
|
||||
|
||||
const History::MediaOverview *o = &(_msgmigrated ? _migrated : _history)->overview[OverviewAudioDocuments];
|
||||
const History::MediaOverview *o = &(_msgmigrated ? _migrated : _history)->overview[OverviewMusicFiles];
|
||||
if ((_msgmigrated ? _migrated : _history)->channelId() == _song.msgId.channel) {
|
||||
for (int i = 0, l = o->size(); i < l; ++i) {
|
||||
if (o->at(i) == _song.msgId.msg) {
|
||||
@ -312,14 +312,14 @@ void PlayerWidget::preloadNext() {
|
||||
if (_index < 0) return;
|
||||
|
||||
History *history = _msgmigrated ? _migrated : _history;
|
||||
const History::MediaOverview *o = &history->overview[OverviewAudioDocuments];
|
||||
const History::MediaOverview *o = &history->overview[OverviewMusicFiles];
|
||||
HistoryItem *next = 0;
|
||||
if (_index < o->size() - 1) {
|
||||
next = App::histItemById(history->channelId(), o->at(_index + 1));
|
||||
} else if (_msgmigrated && _index == o->size() - 1 && _history->overviewLoaded(OverviewAudioDocuments) && _history->overviewCount(OverviewAudioDocuments) > 0) {
|
||||
next = App::histItemById(_history->channelId(), _history->overview[OverviewAudioDocuments].at(0));
|
||||
} else if (_msgmigrated && _index == o->size() - 1 && !_history->overviewCountLoaded(OverviewAudioDocuments)) {
|
||||
if (App::main()) App::main()->preloadOverview(_history->peer, OverviewAudioDocuments);
|
||||
} else if (_msgmigrated && _index == o->size() - 1 && _history->overviewLoaded(OverviewMusicFiles) && _history->overviewCount(OverviewMusicFiles) > 0) {
|
||||
next = App::histItemById(_history->channelId(), _history->overview[OverviewMusicFiles].at(0));
|
||||
} else if (_msgmigrated && _index == o->size() - 1 && !_history->overviewCountLoaded(OverviewMusicFiles)) {
|
||||
if (App::main()) App::main()->preloadOverview(_history->peer, OverviewMusicFiles);
|
||||
}
|
||||
if (next) {
|
||||
if (HistoryDocument *document = static_cast<HistoryDocument*>(next->getMedia())) {
|
||||
@ -348,12 +348,12 @@ void PlayerWidget::clearSelection() {
|
||||
}
|
||||
|
||||
void PlayerWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
|
||||
if (_history && (_history->peer == peer || (_migrated && _migrated->peer == peer)) && type == OverviewAudioDocuments) {
|
||||
if (_history && (_history->peer == peer || (_migrated && _migrated->peer == peer)) && type == OverviewMusicFiles) {
|
||||
_index = -1;
|
||||
History *history = _msgmigrated ? _migrated : _history;
|
||||
if (history->channelId() == _song.msgId.channel) {
|
||||
for (int i = 0, l = history->overview[OverviewAudioDocuments].size(); i < l; ++i) {
|
||||
if (history->overview[OverviewAudioDocuments].at(i) == _song.msgId.msg) {
|
||||
for (int i = 0, l = history->overview[OverviewMusicFiles].size(); i < l; ++i) {
|
||||
if (history->overview[OverviewMusicFiles].at(i) == _song.msgId.msg) {
|
||||
_index = i;
|
||||
preloadNext();
|
||||
break;
|
||||
@ -476,7 +476,7 @@ void PlayerWidget::playPressed() {
|
||||
audioPlayer()->currentState(&playing, &playingState);
|
||||
if (playing == _song && !(playingState & AudioPlayerStoppedMask)) {
|
||||
if (playingState == AudioPlayerPausing || playingState == AudioPlayerPaused || playingState == AudioPlayerPausedAtEnd) {
|
||||
audioPlayer()->pauseresume(OverviewDocuments);
|
||||
audioPlayer()->pauseresume(OverviewFiles);
|
||||
}
|
||||
} else {
|
||||
audioPlayer()->play(_song);
|
||||
@ -492,7 +492,7 @@ void PlayerWidget::pausePressed() {
|
||||
audioPlayer()->currentState(&playing, &playingState);
|
||||
if (playing == _song && !(playingState & AudioPlayerStoppedMask)) {
|
||||
if (playingState == AudioPlayerStarting || playingState == AudioPlayerResuming || playingState == AudioPlayerPlaying || playingState == AudioPlayerFinishing) {
|
||||
audioPlayer()->pauseresume(OverviewDocuments);
|
||||
audioPlayer()->pauseresume(OverviewFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -504,7 +504,7 @@ void PlayerWidget::playPausePressed() {
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
audioPlayer()->currentState(&playing, &playingState);
|
||||
if (playing == _song && !(playingState & AudioPlayerStoppedMask)) {
|
||||
audioPlayer()->pauseresume(OverviewDocuments);
|
||||
audioPlayer()->pauseresume(OverviewFiles);
|
||||
} else {
|
||||
audioPlayer()->play(_song);
|
||||
if (App::main()) App::main()->documentPlayProgress(_song);
|
||||
@ -515,11 +515,11 @@ void PlayerWidget::prevPressed() {
|
||||
if (isHidden()) return;
|
||||
|
||||
History *history = _msgmigrated ? _migrated : _history;
|
||||
const History::MediaOverview *o = history ? &history->overview[OverviewAudioDocuments] : 0;
|
||||
const History::MediaOverview *o = history ? &history->overview[OverviewMusicFiles] : 0;
|
||||
if (audioPlayer() && o && _index > 0 && _index <= o->size() && !o->isEmpty()) {
|
||||
startPlay(FullMsgId(history->channelId(), o->at(_index - 1)));
|
||||
} else if (!_index && _history && _migrated && !_msgmigrated) {
|
||||
o = &_migrated->overview[OverviewAudioDocuments];
|
||||
o = &_migrated->overview[OverviewMusicFiles];
|
||||
if (!o->isEmpty()) {
|
||||
startPlay(FullMsgId(_migrated->channelId(), o->at(o->size() - 1)));
|
||||
}
|
||||
@ -530,11 +530,11 @@ void PlayerWidget::nextPressed() {
|
||||
if (isHidden()) return;
|
||||
|
||||
History *history = _msgmigrated ? _migrated : _history;
|
||||
const History::MediaOverview *o = history ? &history->overview[OverviewAudioDocuments] : 0;
|
||||
const History::MediaOverview *o = history ? &history->overview[OverviewMusicFiles] : 0;
|
||||
if (audioPlayer() && o && _index >= 0 && _index < o->size() - 1) {
|
||||
startPlay(FullMsgId(history->channelId(), o->at(_index + 1)));
|
||||
} else if (o && (_index == o->size() - 1) && _msgmigrated && _history->overviewLoaded(OverviewAudioDocuments)) {
|
||||
o = &_history->overview[OverviewAudioDocuments];
|
||||
} else if (o && (_index == o->size() - 1) && _msgmigrated && _history->overviewLoaded(OverviewMusicFiles)) {
|
||||
o = &_history->overview[OverviewMusicFiles];
|
||||
if (!o->isEmpty()) {
|
||||
startPlay(FullMsgId(_history->channelId(), o->at(0)));
|
||||
}
|
||||
@ -544,7 +544,7 @@ void PlayerWidget::nextPressed() {
|
||||
void PlayerWidget::stopPressed() {
|
||||
if (!_song || isHidden()) return;
|
||||
|
||||
audioPlayer()->stop(OverviewDocuments);
|
||||
audioPlayer()->stop(OverviewFiles);
|
||||
if (App::main()) App::main()->hidePlayer();
|
||||
}
|
||||
|
||||
@ -636,7 +636,7 @@ void PlayerWidget::updateState(SongMsgId playing, AudioPlayerState playingState,
|
||||
display = _song.song->song()->duration;
|
||||
}
|
||||
bool showPause = false, stopped = ((playingState & AudioPlayerStoppedMask) || playingState == AudioPlayerFinishing);
|
||||
bool wasPlaying = !!_duration;
|
||||
bool wasPlaying = (_duration != 0);
|
||||
if (!stopped) {
|
||||
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, PeerData
|
||||
, _kickOver(0)
|
||||
, _kickDown(0)
|
||||
, _kickConfirm(0)
|
||||
|
||||
|
||||
, _menu(0) {
|
||||
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
|
||||
|
||||
@ -209,9 +209,9 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, PeerData
|
||||
// shared media
|
||||
connect((_mediaButtons[OverviewPhotos] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaPhotos()));
|
||||
connect((_mediaButtons[OverviewVideos] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaVideos()));
|
||||
connect((_mediaButtons[OverviewAudioDocuments] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaSongs()));
|
||||
connect((_mediaButtons[OverviewDocuments] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaDocuments()));
|
||||
connect((_mediaButtons[OverviewAudios] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaAudios()));
|
||||
connect((_mediaButtons[OverviewMusicFiles] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaSongs()));
|
||||
connect((_mediaButtons[OverviewFiles] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaDocuments()));
|
||||
connect((_mediaButtons[OverviewVoiceFiles] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaAudios()));
|
||||
connect((_mediaButtons[OverviewLinks] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaLinks()));
|
||||
updateMediaLinks();
|
||||
|
||||
@ -261,7 +261,7 @@ void ProfileInner::loadProfilePhotos(int32 yFrom) {
|
||||
int32 yTo = yFrom + (parentWidget() ? parentWidget()->height() : App::wnd()->height()) * 5;
|
||||
MTP::clearLoaderPriorities();
|
||||
|
||||
int32 partfrom = _mediaButtons[OverviewAudios]->y() + _mediaButtons[OverviewAudios]->height() + st::profileHeaderSkip;
|
||||
int32 partfrom = _mediaButtons[OverviewVoiceFiles]->y() + _mediaButtons[OverviewVoiceFiles]->height() + st::profileHeaderSkip;
|
||||
yFrom -= partfrom;
|
||||
yTo -= partfrom;
|
||||
|
||||
@ -279,7 +279,7 @@ void ProfileInner::loadProfilePhotos(int32 yFrom) {
|
||||
void ProfileInner::onUpdatePhoto() {
|
||||
saveError();
|
||||
|
||||
QStringList imgExtensions(cImgExtensions());
|
||||
QStringList imgExtensions(cImgExtensions());
|
||||
QString filter(qsl("Image files (*") + imgExtensions.join(qsl(" *")) + qsl(");;All files (*.*)"));
|
||||
|
||||
QImage img;
|
||||
@ -440,15 +440,15 @@ void ProfileInner::onMediaVideos() {
|
||||
}
|
||||
|
||||
void ProfileInner::onMediaSongs() {
|
||||
App::main()->showMediaOverview(_peer, OverviewAudioDocuments);
|
||||
App::main()->showMediaOverview(_peer, OverviewMusicFiles);
|
||||
}
|
||||
|
||||
void ProfileInner::onMediaDocuments() {
|
||||
App::main()->showMediaOverview(_peer, OverviewDocuments);
|
||||
App::main()->showMediaOverview(_peer, OverviewFiles);
|
||||
}
|
||||
|
||||
void ProfileInner::onMediaAudios() {
|
||||
App::main()->showMediaOverview(_peer, OverviewAudios);
|
||||
App::main()->showMediaOverview(_peer, OverviewVoiceFiles);
|
||||
}
|
||||
|
||||
void ProfileInner::onMediaLinks() {
|
||||
@ -464,7 +464,7 @@ void ProfileInner::onInvitationLink() {
|
||||
|
||||
void ProfileInner::onPublicLink() {
|
||||
if (!_peerChannel) return;
|
||||
|
||||
|
||||
if (_peerChannel->isPublic()) {
|
||||
QApplication::clipboard()->setText(qsl("https://telegram.me/") + _peerChannel->username);
|
||||
Ui::showLayer(new InformBox(lang(lng_channel_public_link_copied)));
|
||||
@ -776,7 +776,7 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
|
||||
p.setOpacity(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32 namew = _width - st::profilePhotoSize - st::profileNameLeft;
|
||||
p.setPen(st::black->p);
|
||||
if (_peer->isVerified()) {
|
||||
@ -1271,7 +1271,7 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
|
||||
_left = (width() - _width) / 2;
|
||||
|
||||
int32 top = 0, btnWidth = (_width - st::profileButtonSkip) / 2;
|
||||
|
||||
|
||||
// profile
|
||||
top += st::profilePadding.top();
|
||||
int32 addbyname = 0;
|
||||
@ -1446,7 +1446,7 @@ ProfileInner::~ProfileInner() {
|
||||
}
|
||||
_participantsData.clear();
|
||||
}
|
||||
|
||||
|
||||
void ProfileInner::openContextImage() {
|
||||
}
|
||||
|
||||
@ -1711,9 +1711,9 @@ QString ProfileInner::overviewLinkText(int32 type, int32 count) {
|
||||
switch (type) {
|
||||
case OverviewPhotos: return lng_profile_photos(lt_count, count);
|
||||
case OverviewVideos: return lng_profile_videos(lt_count, count);
|
||||
case OverviewAudioDocuments: return lng_profile_songs(lt_count, count);
|
||||
case OverviewDocuments: return lng_profile_files(lt_count, count);
|
||||
case OverviewAudios: return lng_profile_audios(lt_count, count);
|
||||
case OverviewMusicFiles: return lng_profile_songs(lt_count, count);
|
||||
case OverviewFiles: return lng_profile_files(lt_count, count);
|
||||
case OverviewVoiceFiles: return lng_profile_audios(lt_count, count);
|
||||
case OverviewLinks: return lng_profile_shared_links(lt_count, count);
|
||||
}
|
||||
return QString();
|
||||
|
@ -1013,97 +1013,6 @@ void VideoData::setLocation(const FileLocation &loc) {
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOpenLink::onClick(Qt::MouseButton button) const {
|
||||
if (button != Qt::LeftButton) return;
|
||||
AudioData *data = audio();
|
||||
|
||||
if (!data->date) return;
|
||||
|
||||
HistoryItem *item = App::hoveredLinkItem() ? App::hoveredLinkItem() : (App::contextItem() ? App::contextItem() : 0);
|
||||
|
||||
bool play = audioPlayer() && item;
|
||||
const FileLocation &location(data->location(true));
|
||||
if (!location.isEmpty() || (!data->data().isEmpty() && play)) {
|
||||
if (play) {
|
||||
AudioMsgId playing;
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
audioPlayer()->currentState(&playing, &playingState);
|
||||
if (playing.msgId == item->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||
audioPlayer()->pauseresume(OverviewAudios);
|
||||
} else {
|
||||
AudioMsgId audio(data, item->fullId());
|
||||
audioPlayer()->play(audio);
|
||||
if (App::main()) {
|
||||
App::main()->audioPlayProgress(audio);
|
||||
App::main()->audioMarkRead(data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
psOpenFile(location.name());
|
||||
if (App::main()) App::main()->audioMarkRead(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->status != FileReady) return;
|
||||
|
||||
QString filename;
|
||||
if (!data->saveToCache()) {
|
||||
bool mp3 = (data->mime == qstr("audio/mp3"));
|
||||
filename = saveFileName(lang(lng_save_audio), mp3 ? qsl("MP3 Audio (*.mp3);;All files (*.*)") : qsl("OGG Opus Audio (*.ogg);;All files (*.*)"), qsl("audio"), mp3 ? qsl(".mp3") : qsl(".ogg"), false);
|
||||
|
||||
if (filename.isEmpty()) return;
|
||||
}
|
||||
|
||||
data->save(filename, ActionOnLoadOpen, item ? item->fullId() : FullMsgId());
|
||||
}
|
||||
|
||||
void AudioSaveLink::doSave(AudioData *data, bool forceSavingAs) {
|
||||
if (!data->date) return;
|
||||
|
||||
QString already = data->already(true);
|
||||
bool openWith = !already.isEmpty();
|
||||
if (openWith && !forceSavingAs) {
|
||||
QPoint pos(QCursor::pos());
|
||||
if (!psShowOpenWithMenu(pos.x(), pos.y(), already)) {
|
||||
psOpenFile(already, true);
|
||||
}
|
||||
} else {
|
||||
QFileInfo alreadyInfo(already);
|
||||
QDir alreadyDir(already.isEmpty() ? QDir() : alreadyInfo.dir());
|
||||
bool mp3 = (data->mime == qstr("audio/mp3"));
|
||||
QString name = already.isEmpty() ? (mp3 ? qsl(".mp3") : qsl(".ogg")) : alreadyInfo.fileName();
|
||||
QString filename = saveFileName(lang(lng_save_audio), mp3 ? qsl("MP3 Audio (*.mp3);;All files (*.*)") : qsl("OGG Opus Audio (*.ogg);;All files (*.*)"), qsl("audio"), name, forceSavingAs, alreadyDir);
|
||||
if (!filename.isEmpty()) {
|
||||
ActionOnLoad action = already.isEmpty() ? ActionOnLoadNone : ActionOnLoadOpenWith;
|
||||
FullMsgId actionMsgId = App::hoveredLinkItem() ? App::hoveredLinkItem()->fullId() : (App::contextItem() ? App::contextItem()->fullId() : FullMsgId());
|
||||
data->save(filename, action, actionMsgId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSaveLink::onClick(Qt::MouseButton button) const {
|
||||
if (button != Qt::LeftButton) return;
|
||||
doSave(audio());
|
||||
}
|
||||
|
||||
void AudioCancelLink::onClick(Qt::MouseButton button) const {
|
||||
AudioData *data = audio();
|
||||
if (!data->date || button != Qt::LeftButton) return;
|
||||
|
||||
if (data->uploading()) {
|
||||
HistoryItem *item = App::hoveredLinkItem() ? App::hoveredLinkItem() : (App::contextItem() ? App::contextItem() : 0);
|
||||
if (HistoryMessage *msg = item->toHistoryMessage()) {
|
||||
if (msg->getMedia() && msg->getMedia()->type() == MediaTypeAudio && static_cast<HistoryAudio*>(msg->getMedia())->audio() == data) {
|
||||
App::contextItem(item);
|
||||
App::main()->deleteLayer(-2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
bool StickerData::setInstalled() const {
|
||||
switch (set.type()) {
|
||||
case mtpc_inputStickerSetID: {
|
||||
@ -1122,239 +1031,44 @@ bool StickerData::setInstalled() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioData::AudioData(const AudioId &id, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size)
|
||||
: id(id)
|
||||
, access(access)
|
||||
, date(date)
|
||||
, mime(mime)
|
||||
, duration(duration)
|
||||
, dc(dc)
|
||||
, size(size)
|
||||
, status(FileReady)
|
||||
, uploadOffset(0)
|
||||
, _actionOnLoad(ActionOnLoadNone)
|
||||
, _loader(0) {
|
||||
_location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
|
||||
}
|
||||
|
||||
bool AudioData::saveToCache() const {
|
||||
return size < AudioVoiceMsgInMemory;
|
||||
}
|
||||
|
||||
void AudioData::forget() {
|
||||
_data.clear();
|
||||
}
|
||||
|
||||
void AudioData::automaticLoad(const HistoryItem *item) {
|
||||
if (loaded() || status != FileReady) return;
|
||||
|
||||
if (saveToCache() && _loader != CancelledMtpFileLoader) {
|
||||
if (item) {
|
||||
bool loadFromCloud = false;
|
||||
if (item->history()->peer->isUser()) {
|
||||
loadFromCloud = !(cAutoDownloadAudio() & dbiadNoPrivate);
|
||||
} else {
|
||||
loadFromCloud = !(cAutoDownloadAudio() & dbiadNoGroups);
|
||||
}
|
||||
save(QString(), _actionOnLoad, _actionOnLoadMsgId, loadFromCloud ? LoadFromCloudOrLocal : LoadFromLocalOnly, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioData::automaticLoadSettingsChanged() {
|
||||
if (loaded() || status != FileReady || !saveToCache() || _loader != CancelledMtpFileLoader) return;
|
||||
_loader = 0;
|
||||
}
|
||||
|
||||
void AudioData::performActionOnLoad() {
|
||||
if (_actionOnLoad == ActionOnLoadNone) return;
|
||||
|
||||
const FileLocation &loc(location(true));
|
||||
QString already = loc.name();
|
||||
bool play = _actionOnLoadMsgId.msg && (_actionOnLoad == ActionOnLoadPlayInline || _actionOnLoad == ActionOnLoadOpen) && audioPlayer();
|
||||
|
||||
if (play) {
|
||||
if (loaded()) {
|
||||
AudioMsgId playing;
|
||||
AudioPlayerState state = AudioPlayerStopped;
|
||||
audioPlayer()->currentState(&playing, &state);
|
||||
if (playing.msgId == _actionOnLoadMsgId && !(state & AudioPlayerStoppedMask) && state != AudioPlayerFinishing) {
|
||||
audioPlayer()->pauseresume(OverviewAudios);
|
||||
} else {
|
||||
audioPlayer()->play(AudioMsgId(this, _actionOnLoadMsgId));
|
||||
if (App::main()) App::main()->audioMarkRead(this);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (already.isEmpty()) return;
|
||||
if (_actionOnLoad == ActionOnLoadOpenWith) {
|
||||
if (already.isEmpty()) return;
|
||||
|
||||
QPoint pos(QCursor::pos());
|
||||
if (!psShowOpenWithMenu(pos.x(), pos.y(), already)) {
|
||||
psOpenFile(already, true);
|
||||
}
|
||||
if (App::main()) App::main()->audioMarkRead(this);
|
||||
} else if (_actionOnLoad == ActionOnLoadOpen || _actionOnLoad == ActionOnLoadPlayInline) {
|
||||
psOpenFile(already);
|
||||
if (App::main()) App::main()->audioMarkRead(this);
|
||||
}
|
||||
}
|
||||
_actionOnLoad = ActionOnLoadNone;
|
||||
}
|
||||
|
||||
bool AudioData::loaded(bool check) const {
|
||||
if (loading() && _loader->done()) {
|
||||
if (_loader->fileType() == mtpc_storage_fileUnknown) {
|
||||
_loader->deleteLater();
|
||||
_loader->rpcInvalidate();
|
||||
_loader = CancelledMtpFileLoader;
|
||||
} else {
|
||||
AudioData *that = const_cast<AudioData*>(this);
|
||||
that->_location = FileLocation(mtpToStorageType(_loader->fileType()), _loader->fileName());
|
||||
that->_data = _loader->bytes();
|
||||
|
||||
_loader->deleteLater();
|
||||
_loader->rpcInvalidate();
|
||||
_loader = 0;
|
||||
}
|
||||
notifyLayoutChanged();
|
||||
}
|
||||
return !_data.isEmpty() || !already(check).isEmpty();
|
||||
}
|
||||
|
||||
bool AudioData::loading() const {
|
||||
return _loader && _loader != CancelledMtpFileLoader;
|
||||
}
|
||||
|
||||
bool AudioData::displayLoading() const {
|
||||
return loading() ? (!_loader->loadingLocal() || !_loader->autoLoading()) : uploading();
|
||||
}
|
||||
|
||||
float64 AudioData::progress() const {
|
||||
if (uploading()) {
|
||||
if (size > 0) {
|
||||
return float64(uploadOffset) / size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return loading() ? _loader->currentProgress() : (loaded() ? 1 : 0);
|
||||
}
|
||||
|
||||
int32 AudioData::loadOffset() const {
|
||||
return loading() ? _loader->currentOffset() : 0;
|
||||
}
|
||||
|
||||
bool AudioData::uploading() const {
|
||||
return status == FileUploading;
|
||||
}
|
||||
|
||||
void AudioData::save(const QString &toFile, ActionOnLoad action, const FullMsgId &actionMsgId, LoadFromCloudSetting fromCloud, bool autoLoading) {
|
||||
if (loaded(true)) {
|
||||
const FileLocation &l(location(true));
|
||||
if (!toFile.isEmpty()) {
|
||||
if (!_data.isEmpty()) {
|
||||
QFile f(toFile);
|
||||
f.open(QIODevice::WriteOnly);
|
||||
f.write(_data);
|
||||
} else if (l.accessEnable()) {
|
||||
QFile(l.name()).copy(toFile);
|
||||
l.accessDisable();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_loader == CancelledMtpFileLoader) _loader = 0;
|
||||
if (_loader) {
|
||||
if (!_loader->setFileName(toFile)) {
|
||||
cancel();
|
||||
_loader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_actionOnLoad = action;
|
||||
_actionOnLoadMsgId = actionMsgId;
|
||||
|
||||
if (_loader) {
|
||||
if (fromCloud == LoadFromCloudOrLocal) _loader->permitLoadFromCloud();
|
||||
} else {
|
||||
status = FileReady;
|
||||
_loader = new mtpFileLoader(dc, id, access, AudioFileLocation, toFile, size, (saveToCache() ? LoadToCacheAsWell : LoadToFileOnly), fromCloud, autoLoading);
|
||||
_loader->connect(_loader, SIGNAL(progress(FileLoader*)), App::main(), SLOT(audioLoadProgress(FileLoader*)));
|
||||
_loader->connect(_loader, SIGNAL(failed(FileLoader*,bool)), App::main(), SLOT(audioLoadFailed(FileLoader*,bool)));
|
||||
_loader->start();
|
||||
}
|
||||
|
||||
notifyLayoutChanged();
|
||||
}
|
||||
|
||||
void AudioData::cancel() {
|
||||
if (!loading()) return;
|
||||
|
||||
mtpFileLoader *l = _loader;
|
||||
_loader = CancelledMtpFileLoader;
|
||||
if (l) {
|
||||
l->cancel();
|
||||
l->deleteLater();
|
||||
l->rpcInvalidate();
|
||||
|
||||
notifyLayoutChanged();
|
||||
}
|
||||
_actionOnLoad = ActionOnLoadNone;
|
||||
}
|
||||
|
||||
void AudioData::notifyLayoutChanged() const {
|
||||
const AudioItems &items(App::audioItems());
|
||||
AudioItems::const_iterator i = items.constFind(const_cast<AudioData*>(this));
|
||||
if (i != items.cend()) {
|
||||
for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) {
|
||||
Notify::historyItemLayoutChanged(j.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString AudioData::already(bool check) const {
|
||||
return location(check).name();
|
||||
}
|
||||
|
||||
QByteArray AudioData::data() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
const FileLocation &AudioData::location(bool check) const {
|
||||
if (check && !_location.check()) {
|
||||
const_cast<AudioData*>(this)->_location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
|
||||
}
|
||||
return _location;
|
||||
}
|
||||
|
||||
void AudioData::setLocation(const FileLocation &loc) {
|
||||
if (loc.check()) {
|
||||
_location = loc;
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentOpenLink::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;
|
||||
bool playAnimation = data->isAnimation() && item && item->getMedia();
|
||||
const FileLocation &location(data->location(true));
|
||||
if (!location.isEmpty() || (!data->data().isEmpty() && (playMusic || playAnimation))) {
|
||||
if (playMusic) {
|
||||
if (!location.isEmpty() || (!data->data().isEmpty() && (playVoice || playMusic || playAnimation))) {
|
||||
if (playVoice) {
|
||||
AudioMsgId playing;
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
audioPlayer()->currentState(&playing, &playingState);
|
||||
if (playing.msgId == item->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||
audioPlayer()->pauseresume(OverviewVoiceFiles);
|
||||
} else {
|
||||
AudioMsgId audio(data, item->fullId());
|
||||
audioPlayer()->play(audio);
|
||||
if (App::main()) {
|
||||
App::main()->audioPlayProgress(audio);
|
||||
App::main()->audioMarkRead(data);
|
||||
}
|
||||
}
|
||||
} else if (playMusic) {
|
||||
SongMsgId playing;
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
audioPlayer()->currentState(&playing, &playingState);
|
||||
if (playing.msgId == item->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||
audioPlayer()->pauseresume(OverviewDocuments);
|
||||
audioPlayer()->pauseresume(OverviewFiles);
|
||||
} else {
|
||||
SongMsgId song(data, item->fullId());
|
||||
audioPlayer()->play(song);
|
||||
if (App::main()) App::main()->documentPlayProgress(song);
|
||||
}
|
||||
} else if (data->voice()) {
|
||||
psOpenFile(location.name());
|
||||
if (App::main()) App::main()->audioMarkRead(data);
|
||||
} else if (data->size < MediaViewImageSizeLimit) {
|
||||
if (!data->data().isEmpty() && playAnimation) {
|
||||
if (action == ActionOnLoadPlayInline) {
|
||||
@ -1386,21 +1100,32 @@ void DocumentOpenLink::doOpen(DocumentData *data, ActionOnLoad action) {
|
||||
|
||||
QString filename;
|
||||
if (!data->saveToCache()) {
|
||||
QString name = data->name, filter;
|
||||
QString name, filter, caption, prefix;
|
||||
MimeType mimeType = mimeTypeForName(data->mime);
|
||||
QStringList p = mimeType.globPatterns();
|
||||
QString pattern = p.isEmpty() ? QString() : p.front();
|
||||
if (name.isEmpty()) {
|
||||
name = pattern.isEmpty() ? qsl(".unknown") : pattern.replace('*', QString());
|
||||
}
|
||||
|
||||
if (pattern.isEmpty()) {
|
||||
filter = QString();
|
||||
if (data->voice()) {
|
||||
bool mp3 = (data->mime == qstr("audio/mp3"));
|
||||
name = mp3 ? qsl(".mp3") : qsl(".ogg");
|
||||
filter = mp3 ? qsl("MP3 Audio (*.mp3);;All files (*.*)") : qsl("OGG Opus Audio (*.ogg);;All files (*.*)");
|
||||
caption = lang(lng_save_audio);
|
||||
prefix = qsl("audio");
|
||||
} else {
|
||||
filter = mimeType.filterString() + qsl(";;All files (*.*)");
|
||||
if (data->name.isEmpty()) {
|
||||
name = pattern.isEmpty() ? qsl(".unknown") : pattern.replace('*', QString());
|
||||
} else {
|
||||
name = data->name;
|
||||
}
|
||||
if (pattern.isEmpty()) {
|
||||
filter = QString();
|
||||
} else {
|
||||
filter = mimeType.filterString() + qsl(";;All files (*.*)");
|
||||
}
|
||||
caption = lang(lng_save_file);
|
||||
prefix = qsl("doc");
|
||||
}
|
||||
|
||||
filename = saveFileName(lang(lng_save_file), filter, qsl("doc"), name, false);
|
||||
filename = saveFileName(caption, filter, prefix, name, false);
|
||||
|
||||
if (filename.isEmpty()) return;
|
||||
}
|
||||
@ -1410,16 +1135,17 @@ void DocumentOpenLink::doOpen(DocumentData *data, ActionOnLoad action) {
|
||||
|
||||
void DocumentOpenLink::onClick(Qt::MouseButton button) const {
|
||||
if (button != Qt::LeftButton) return;
|
||||
doOpen(document());
|
||||
doOpen(document(), document()->voice() ? ActionOnLoadNone : ActionOnLoadOpen);
|
||||
}
|
||||
|
||||
void GifOpenLink::doOpen(DocumentData *data) {
|
||||
return DocumentOpenLink::doOpen(data, ActionOnLoadPlayInline);
|
||||
void VoiceSaveLink::onClick(Qt::MouseButton button) const {
|
||||
if (button != Qt::LeftButton) return;
|
||||
doOpen(document(), ActionOnLoadNone);
|
||||
}
|
||||
|
||||
void GifOpenLink::onClick(Qt::MouseButton button) const {
|
||||
if (button != Qt::LeftButton) return;
|
||||
doOpen(document());
|
||||
doOpen(document(), ActionOnLoadPlayInline);
|
||||
}
|
||||
|
||||
void DocumentSaveLink::doSave(DocumentData *data, bool forceSavingAs) {
|
||||
@ -1433,23 +1159,34 @@ void DocumentSaveLink::doSave(DocumentData *data, bool forceSavingAs) {
|
||||
psOpenFile(already, true);
|
||||
}
|
||||
} else {
|
||||
|
||||
QFileInfo alreadyInfo(already);
|
||||
QDir alreadyDir(already.isEmpty() ? QDir() : alreadyInfo.dir());
|
||||
QString name = already.isEmpty() ? data->name : alreadyInfo.fileName(), filter;
|
||||
QString caption, filter, prefix, name;
|
||||
MimeType mimeType = mimeTypeForName(data->mime);
|
||||
QStringList p = mimeType.globPatterns();
|
||||
QString pattern = p.isEmpty() ? QString() : p.front();
|
||||
if (name.isEmpty()) {
|
||||
name = pattern.isEmpty() ? qsl(".unknown") : pattern.replace('*', QString());
|
||||
}
|
||||
|
||||
if (pattern.isEmpty()) {
|
||||
filter = QString();
|
||||
if (data->voice()) {
|
||||
bool mp3 = (data->mime == qstr("audio/mp3"));
|
||||
caption = lang(lng_save_audio);
|
||||
filter = mp3 ? qsl("MP3 Audio (*.mp3);;All files (*.*)") : qsl("OGG Opus Audio (*.ogg);;All files (*.*)");
|
||||
prefix = qsl("audio");
|
||||
name = already.isEmpty() ? (mp3 ? qsl(".mp3") : qsl(".ogg")) : alreadyInfo.fileName();
|
||||
} else {
|
||||
filter = mimeType.filterString() + qsl(";;All files (*.*)");
|
||||
caption = lang(lng_save_file);
|
||||
if (pattern.isEmpty()) {
|
||||
filter = QString();
|
||||
} else {
|
||||
filter = mimeType.filterString() + qsl(";;All files (*.*)");
|
||||
}
|
||||
prefix = qsl("doc");
|
||||
name = already.isEmpty() ? data->name : alreadyInfo.fileName();
|
||||
if (name.isEmpty()) {
|
||||
name = pattern.isEmpty() ? qsl(".unknown") : pattern.replace('*', QString());
|
||||
}
|
||||
}
|
||||
|
||||
QString filename = saveFileName(lang(lng_save_file), filter, qsl("doc"), name, forceSavingAs, alreadyDir);
|
||||
QString filename = saveFileName(caption, filter, prefix, name, forceSavingAs, alreadyDir);
|
||||
if (!filename.isEmpty()) {
|
||||
ActionOnLoad action = already.isEmpty() ? ActionOnLoadNone : ActionOnLoadOpenWith;
|
||||
FullMsgId actionMsgId = App::hoveredLinkItem() ? App::hoveredLinkItem()->fullId() : (App::contextItem() ? App::contextItem()->fullId() : FullMsgId());
|
||||
@ -1482,6 +1219,14 @@ void DocumentCancelLink::onClick(Qt::MouseButton button) const {
|
||||
}
|
||||
}
|
||||
|
||||
VoiceData::~VoiceData() {
|
||||
if (!waveform.isEmpty() && waveform.at(0) == -1 && waveform.size() > sizeof(TaskId)) {
|
||||
TaskId taskId = 0;
|
||||
memcpy(&taskId, waveform.constData() + 1, sizeof(taskId));
|
||||
Local::cancelTask(taskId);
|
||||
}
|
||||
}
|
||||
|
||||
DocumentData::DocumentData(const DocumentId &id, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size) : id(id)
|
||||
, type(FileDocument)
|
||||
, access(access)
|
||||
@ -1496,8 +1241,8 @@ DocumentData::DocumentData(const DocumentId &id, const uint64 &access, int32 dat
|
||||
, _duration(-1)
|
||||
, _actionOnLoad(ActionOnLoadNone)
|
||||
, _loader(0) {
|
||||
_location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id));
|
||||
setattributes(attributes);
|
||||
_location = Local::readFileLocation(mediaKey(voice() ? AudioFileLocation : DocumentFileLocation, dc, id));
|
||||
}
|
||||
|
||||
void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes) {
|
||||
@ -1535,11 +1280,27 @@ void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes
|
||||
case mtpc_documentAttributeAudio: {
|
||||
const MTPDdocumentAttributeAudio &d(attributes[i].c_documentAttributeAudio());
|
||||
if (type == FileDocument) {
|
||||
type = SongDocument;
|
||||
SongData *song = new SongData();
|
||||
_additional = song;
|
||||
if (d.is_voice()) {
|
||||
type = VoiceDocument;
|
||||
VoiceData *voice = new VoiceData();
|
||||
_additional = voice;
|
||||
} else {
|
||||
type = SongDocument;
|
||||
SongData *song = new SongData();
|
||||
_additional = song;
|
||||
}
|
||||
}
|
||||
if (song()) {
|
||||
if (voice()) {
|
||||
voice()->duration = d.vduration.v;
|
||||
VoiceWaveform waveform = documentWaveformDecode(qba(d.vwaveform));
|
||||
uchar wavemax = 0;
|
||||
for (int32 i = 0, l = waveform.size(); i < l; ++i) {
|
||||
uchar waveat = waveform.at(i);
|
||||
if (wavemax < waveat) wavemax = waveat;
|
||||
}
|
||||
voice()->waveform = waveform;
|
||||
voice()->wavemax = wavemax;
|
||||
} else if (song()) {
|
||||
song()->duration = d.vduration.v;
|
||||
song()->title = qs(d.vtitle);
|
||||
song()->performer = qs(d.vperformer);
|
||||
@ -1558,7 +1319,7 @@ void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes
|
||||
}
|
||||
|
||||
bool DocumentData::saveToCache() const {
|
||||
return (type == StickerDocument) || (isAnimation() && size < AnimationInMemory);
|
||||
return (type == StickerDocument) || (isAnimation() && size < AnimationInMemory) || (voice() && size < AudioVoiceMsgInMemory);
|
||||
}
|
||||
|
||||
void DocumentData::forget() {
|
||||
@ -1586,12 +1347,22 @@ void DocumentData::automaticLoad(const HistoryItem *item) {
|
||||
loadFromCloud = !(cAutoDownloadGif() & dbiadNoPrivate) || !(cAutoDownloadGif() & dbiadNoGroups);
|
||||
}
|
||||
save(QString(), _actionOnLoad, _actionOnLoadMsgId, loadFromCloud ? LoadFromCloudOrLocal : LoadFromLocalOnly, true);
|
||||
} else if (voice()) {
|
||||
if (item) {
|
||||
bool loadFromCloud = false;
|
||||
if (item->history()->peer->isUser()) {
|
||||
loadFromCloud = !(cAutoDownloadAudio() & dbiadNoPrivate);
|
||||
} else {
|
||||
loadFromCloud = !(cAutoDownloadAudio() & dbiadNoGroups);
|
||||
}
|
||||
save(QString(), _actionOnLoad, _actionOnLoadMsgId, loadFromCloud ? LoadFromCloudOrLocal : LoadFromLocalOnly, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentData::automaticLoadSettingsChanged() {
|
||||
if (loaded() || status != FileReady || !isAnimation() || !saveToCache() || _loader != CancelledMtpFileLoader) return;
|
||||
if (loaded() || status != FileReady || (!isAnimation() && !voice()) || !saveToCache() || _loader != CancelledMtpFileLoader) return;
|
||||
_loader = 0;
|
||||
}
|
||||
|
||||
@ -1602,15 +1373,28 @@ void DocumentData::performActionOnLoad() {
|
||||
QString already = loc.name();
|
||||
HistoryItem *item = _actionOnLoadMsgId.msg ? App::histItemById(_actionOnLoadMsgId) : 0;
|
||||
bool showImage = 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();
|
||||
if (playMusic) {
|
||||
if (playVoice) {
|
||||
if (loaded()) {
|
||||
AudioMsgId playing;
|
||||
AudioPlayerState state = AudioPlayerStopped;
|
||||
audioPlayer()->currentState(&playing, &state);
|
||||
if (playing.msgId == _actionOnLoadMsgId && !(state & AudioPlayerStoppedMask) && state != AudioPlayerFinishing) {
|
||||
audioPlayer()->pauseresume(OverviewVoiceFiles);
|
||||
} else {
|
||||
audioPlayer()->play(AudioMsgId(this, _actionOnLoadMsgId));
|
||||
if (App::main()) App::main()->audioMarkRead(this);
|
||||
}
|
||||
}
|
||||
} else if (playMusic) {
|
||||
if (loaded()) {
|
||||
SongMsgId playing;
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
audioPlayer()->currentState(&playing, &playingState);
|
||||
if (playing.msgId == item->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||
audioPlayer()->pauseresume(OverviewDocuments);
|
||||
audioPlayer()->pauseresume(OverviewFiles);
|
||||
} else {
|
||||
SongMsgId song(this, item->fullId());
|
||||
audioPlayer()->play(song);
|
||||
@ -1636,7 +1420,10 @@ void DocumentData::performActionOnLoad() {
|
||||
psOpenFile(already, true);
|
||||
}
|
||||
} else if (_actionOnLoad == ActionOnLoadOpen || _actionOnLoad == ActionOnLoadPlayInline) {
|
||||
if (loc.accessEnable()) {
|
||||
if (voice()) {
|
||||
psOpenFile(already);
|
||||
if (App::main()) App::main()->audioMarkRead(this);
|
||||
} else if (loc.accessEnable()) {
|
||||
if (showImage && QImageReader(loc.name()).canRead()) {
|
||||
if (_actionOnLoad == ActionOnLoadPlayInline) {
|
||||
item->getMedia()->playInline(item);
|
||||
@ -1735,7 +1522,8 @@ void DocumentData::save(const QString &toFile, ActionOnLoad action, const FullMs
|
||||
if (fromCloud == LoadFromCloudOrLocal) _loader->permitLoadFromCloud();
|
||||
} else {
|
||||
status = FileReady;
|
||||
_loader = new mtpFileLoader(dc, id, access, DocumentFileLocation, toFile, size, (saveToCache() ? LoadToCacheAsWell : LoadToFileOnly), fromCloud, autoLoading);
|
||||
LocationType type = voice() ? AudioFileLocation : DocumentFileLocation;
|
||||
_loader = new mtpFileLoader(dc, id, access, type, toFile, size, (saveToCache() ? LoadToCacheAsWell : LoadToFileOnly), fromCloud, autoLoading);
|
||||
_loader->connect(_loader, SIGNAL(progress(FileLoader*)), App::main(), SLOT(documentLoadProgress(FileLoader*)));
|
||||
_loader->connect(_loader, SIGNAL(failed(FileLoader*,bool)), App::main(), SLOT(documentLoadFailed(FileLoader*,bool)));
|
||||
_loader->start();
|
||||
@ -1769,6 +1557,24 @@ void DocumentData::notifyLayoutChanged() const {
|
||||
}
|
||||
}
|
||||
|
||||
VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit) {
|
||||
VoiceWaveform result((encoded5bit.size() * 8) / 5, 0);
|
||||
for (int32 i = 0, l = result.size(); i < l; ++i) { // read each 5 bit of encoded5bit as 0-31 unsigned char
|
||||
int32 byte = (i * 5) / 8, shift = (i * 5) % 8;
|
||||
result[i] = (((*(uint16*)(encoded5bit.constData() + byte)) >> shift) & 0x1F);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray documentWaveformEncode5bit(const VoiceWaveform &waveform) {
|
||||
QByteArray result((waveform.size() * 5 + 7) / 8, 0);
|
||||
for (int32 i = 0, l = waveform.size(); i < l; ++i) { // write each 0-31 unsigned char as 5 bit to result
|
||||
int32 byte = (i * 5) / 8, shift = (i * 5) % 8;
|
||||
(*(uint16*)(result.data() + byte)) |= (uint16(waveform.at(i) & 0x1F) << shift);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QString DocumentData::already(bool check) const {
|
||||
if (check && _location.name().isEmpty()) return QString();
|
||||
return location(check).name();
|
||||
@ -1780,7 +1586,8 @@ QByteArray DocumentData::data() const {
|
||||
|
||||
const FileLocation &DocumentData::location(bool check) const {
|
||||
if (check && !_location.check()) {
|
||||
const_cast<DocumentData*>(this)->_location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id));
|
||||
LocationType type = voice() ? AudioFileLocation : DocumentFileLocation;
|
||||
const_cast<DocumentData*>(this)->_location = Local::readFileLocation(mediaKey(type, dc, id));
|
||||
}
|
||||
return _location;
|
||||
}
|
||||
|
@ -914,138 +914,13 @@ public:
|
||||
|
||||
};
|
||||
|
||||
class AudioData {
|
||||
public:
|
||||
AudioData(const AudioId &id, const uint64 &access = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
|
||||
|
||||
void automaticLoad(const HistoryItem *item); // auto load voice message
|
||||
void automaticLoadSettingsChanged();
|
||||
|
||||
bool loaded(bool check = false) const;
|
||||
bool loading() const;
|
||||
bool displayLoading() const;
|
||||
void save(const QString &toFile, ActionOnLoad action = ActionOnLoadNone, const FullMsgId &actionMsgId = FullMsgId(), LoadFromCloudSetting fromCloud = LoadFromCloudOrLocal, bool autoLoading = false);
|
||||
void cancel();
|
||||
float64 progress() const;
|
||||
int32 loadOffset() const;
|
||||
bool uploading() const;
|
||||
|
||||
QString already(bool check = false) const;
|
||||
QByteArray data() const;
|
||||
const FileLocation &location(bool check = false) const;
|
||||
void setLocation(const FileLocation &loc);
|
||||
|
||||
bool saveToCache() const;
|
||||
|
||||
void performActionOnLoad();
|
||||
|
||||
void forget();
|
||||
void setData(const QByteArray &data) {
|
||||
_data = data;
|
||||
}
|
||||
|
||||
AudioId id;
|
||||
uint64 access;
|
||||
int32 date;
|
||||
QString mime;
|
||||
int32 duration;
|
||||
int32 dc;
|
||||
int32 size;
|
||||
|
||||
FileStatus status;
|
||||
int32 uploadOffset;
|
||||
|
||||
int32 md5[8];
|
||||
|
||||
private:
|
||||
FileLocation _location;
|
||||
QByteArray _data;
|
||||
|
||||
ActionOnLoad _actionOnLoad;
|
||||
FullMsgId _actionOnLoadMsgId;
|
||||
mutable mtpFileLoader *_loader;
|
||||
|
||||
void notifyLayoutChanged() const;
|
||||
|
||||
};
|
||||
|
||||
struct AudioMsgId {
|
||||
AudioMsgId() : audio(0) {
|
||||
}
|
||||
AudioMsgId(AudioData *audio, const FullMsgId &msgId) : audio(audio), msgId(msgId) {
|
||||
}
|
||||
AudioMsgId(AudioData *audio, ChannelId channelId, MsgId msgId) : audio(audio), msgId(channelId, msgId) {
|
||||
}
|
||||
operator bool() const {
|
||||
return audio;
|
||||
}
|
||||
AudioData *audio;
|
||||
FullMsgId msgId;
|
||||
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
inline bool operator==(const AudioMsgId &a, const AudioMsgId &b) {
|
||||
return a.audio == b.audio && a.msgId == b.msgId;
|
||||
}
|
||||
inline bool operator!=(const AudioMsgId &a, const AudioMsgId &b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
class AudioLink : public ITextLink {
|
||||
TEXT_LINK_CLASS(AudioLink)
|
||||
|
||||
public:
|
||||
AudioLink(AudioData *audio) : _audio(audio) {
|
||||
}
|
||||
AudioData *audio() const {
|
||||
return _audio;
|
||||
}
|
||||
|
||||
private:
|
||||
AudioData *_audio;
|
||||
|
||||
};
|
||||
|
||||
class AudioSaveLink : public AudioLink {
|
||||
TEXT_LINK_CLASS(AudioSaveLink)
|
||||
|
||||
public:
|
||||
AudioSaveLink(AudioData *audio) : AudioLink(audio) {
|
||||
}
|
||||
static void doSave(AudioData *audio, bool forceSavingAs = false);
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
||||
class AudioOpenLink : public AudioLink {
|
||||
TEXT_LINK_CLASS(AudioOpenLink)
|
||||
|
||||
public:
|
||||
AudioOpenLink(AudioData *audio) : AudioLink(audio) {
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
||||
class AudioCancelLink : public AudioLink {
|
||||
TEXT_LINK_CLASS(AudioCancelLink)
|
||||
|
||||
public:
|
||||
AudioCancelLink(AudioData *audio) : AudioLink(audio) {
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
||||
enum DocumentType {
|
||||
FileDocument = 0,
|
||||
VideoDocument = 1,
|
||||
SongDocument = 2,
|
||||
StickerDocument = 3,
|
||||
AnimatedDocument = 4,
|
||||
VoiceDocument = 5,
|
||||
};
|
||||
|
||||
struct DocumentAdditionalData {
|
||||
@ -1072,6 +947,16 @@ struct SongData : public DocumentAdditionalData {
|
||||
|
||||
};
|
||||
|
||||
typedef QVector<char> VoiceWaveform; // [0] == -1 -- counting, [0] == -2 -- could not count
|
||||
struct VoiceData : public DocumentAdditionalData {
|
||||
VoiceData() : duration(0), wavemax(0) {
|
||||
}
|
||||
~VoiceData();
|
||||
int32 duration;
|
||||
VoiceWaveform waveform;
|
||||
char wavemax;
|
||||
};
|
||||
|
||||
bool fileIsImage(const QString &name, const QString &mime);
|
||||
|
||||
class DocumentData {
|
||||
@ -1126,12 +1011,21 @@ public:
|
||||
SongData *song() {
|
||||
return (type == SongDocument) ? static_cast<SongData*>(_additional) : 0;
|
||||
}
|
||||
VoiceData *voice() {
|
||||
return (type == VoiceDocument) ? static_cast<VoiceData*>(_additional) : 0;
|
||||
}
|
||||
const VoiceData *voice() const {
|
||||
return (type == VoiceDocument) ? static_cast<VoiceData*>(_additional) : 0;
|
||||
}
|
||||
bool isAnimation() const {
|
||||
return (type == AnimatedDocument) || !mime.compare(qstr("image/gif"), Qt::CaseInsensitive);
|
||||
}
|
||||
bool isGifv() const {
|
||||
return (type == AnimatedDocument) && !mime.compare(qstr("video/mp4"), Qt::CaseInsensitive);
|
||||
}
|
||||
bool isMusic() const {
|
||||
return (type == SongDocument) ? !static_cast<SongData*>(_additional)->title.isEmpty() : false;
|
||||
}
|
||||
int32 duration() const {
|
||||
return (isAnimation() || type == VideoDocument) ? _duration : -1;
|
||||
}
|
||||
@ -1139,6 +1033,9 @@ public:
|
||||
return !isAnimation() && (type != VideoDocument) && (_duration > 0);
|
||||
}
|
||||
void recountIsImage();
|
||||
void setData(const QByteArray &data) {
|
||||
_data = data;
|
||||
}
|
||||
|
||||
~DocumentData();
|
||||
|
||||
@ -1172,6 +1069,9 @@ private:
|
||||
|
||||
};
|
||||
|
||||
VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit);
|
||||
QByteArray documentWaveformEncode5bit(const VoiceWaveform &waveform);
|
||||
|
||||
struct SongMsgId {
|
||||
SongMsgId() : song(0) {
|
||||
}
|
||||
@ -1196,6 +1096,31 @@ inline bool operator!=(const SongMsgId &a, const SongMsgId &b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
struct AudioMsgId {
|
||||
AudioMsgId() : audio(0) {
|
||||
}
|
||||
AudioMsgId(DocumentData *audio, const FullMsgId &msgId) : audio(audio), msgId(msgId) {
|
||||
}
|
||||
AudioMsgId(DocumentData *audio, ChannelId channelId, MsgId msgId) : audio(audio), msgId(channelId, msgId) {
|
||||
}
|
||||
operator bool() const {
|
||||
return audio;
|
||||
}
|
||||
DocumentData *audio;
|
||||
FullMsgId msgId;
|
||||
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
inline bool operator==(const AudioMsgId &a, const AudioMsgId &b) {
|
||||
return a.audio == b.audio && a.msgId == b.msgId;
|
||||
}
|
||||
inline bool operator!=(const AudioMsgId &a, const AudioMsgId &b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
class DocumentLink : public ITextLink {
|
||||
TEXT_LINK_CLASS(DocumentLink)
|
||||
|
||||
@ -1233,13 +1158,22 @@ public:
|
||||
|
||||
};
|
||||
|
||||
class VoiceSaveLink : public DocumentOpenLink {
|
||||
TEXT_LINK_CLASS(VoiceSaveLink)
|
||||
|
||||
public:
|
||||
VoiceSaveLink(DocumentData *document) : DocumentOpenLink(document) {
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
||||
class GifOpenLink : public DocumentOpenLink {
|
||||
TEXT_LINK_CLASS(GifOpenLink)
|
||||
|
||||
public:
|
||||
GifOpenLink(DocumentData *document) : DocumentOpenLink(document) {
|
||||
}
|
||||
static void doOpen(DocumentData *document);
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
@ -532,18 +532,21 @@ inline void destroyImplementation(I *&ptr) {
|
||||
class Interfaces;
|
||||
typedef void(*InterfaceConstruct)(void *location, Interfaces *interfaces);
|
||||
typedef void(*InterfaceDestruct)(void *location);
|
||||
typedef void(*InterfaceAssign)(void *location, void *waslocation);
|
||||
|
||||
struct InterfaceWrapStruct {
|
||||
InterfaceWrapStruct() : Size(0), Construct(0), Destruct(0) {
|
||||
}
|
||||
InterfaceWrapStruct(int size, InterfaceConstruct construct, InterfaceDestruct destruct)
|
||||
InterfaceWrapStruct(int size, InterfaceConstruct construct, InterfaceDestruct destruct, InterfaceAssign assign)
|
||||
: Size(size)
|
||||
, Construct(construct)
|
||||
, Destruct(destruct) {
|
||||
, Destruct(destruct)
|
||||
, Assign(assign) {
|
||||
}
|
||||
int Size;
|
||||
InterfaceConstruct Construct;
|
||||
InterfaceDestruct Destruct;
|
||||
InterfaceAssign Assign;
|
||||
};
|
||||
|
||||
template <int Value, int Denominator>
|
||||
@ -560,6 +563,9 @@ struct InterfaceWrapTemplate {
|
||||
static void Destruct(void *location) {
|
||||
((Type*)location)->~Type();
|
||||
}
|
||||
static void Assign(void *location, void *waslocation) {
|
||||
*((Type*)location) = *((Type*)waslocation);
|
||||
}
|
||||
};
|
||||
|
||||
extern InterfaceWrapStruct InterfaceWraps[64];
|
||||
@ -578,7 +584,7 @@ public:
|
||||
if (InterfaceIndexLast.testAndSetOrdered(last, last + 1)) {
|
||||
t_assert(last < 64);
|
||||
if (_index.testAndSetOrdered(0, last + 1)) {
|
||||
InterfaceWraps[last] = InterfaceWrapStruct(InterfaceWrapTemplate<Type>::Size, InterfaceWrapTemplate<Type>::Construct, InterfaceWrapTemplate<Type>::Destruct);
|
||||
InterfaceWraps[last] = InterfaceWrapStruct(InterfaceWrapTemplate<Type>::Size, InterfaceWrapTemplate<Type>::Construct, InterfaceWrapTemplate<Type>::Destruct, InterfaceWrapTemplate<Type>::Assign);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -627,6 +633,10 @@ public:
|
||||
int size, last;
|
||||
int offsets[64];
|
||||
|
||||
bool equals(const uint64 &mask) const {
|
||||
return _mask == mask;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64 _mask;
|
||||
|
||||
@ -637,22 +647,25 @@ const InterfacesMetadata *GetInterfacesMetadata(uint64 mask);
|
||||
class Interfaces {
|
||||
public:
|
||||
|
||||
Interfaces(uint64 mask = 0) : _meta(GetInterfacesMetadata(mask)), _data(0) {
|
||||
if (_meta->size) {
|
||||
_data = malloc(_meta->size);
|
||||
Interfaces(uint64 mask = 0) : _data(0) {
|
||||
if (mask) {
|
||||
const InterfacesMetadata *meta = GetInterfacesMetadata(mask);
|
||||
int32 size = sizeof(const InterfacesMetadata *) + meta->size;
|
||||
_data = malloc(size);
|
||||
if (!_data) { // terminate if we can't allocate memory
|
||||
throw "Can't allocate memory!";
|
||||
}
|
||||
|
||||
for (int i = 0; i < _meta->last; ++i) {
|
||||
int offset = _meta->offsets[i];
|
||||
_meta() = meta;
|
||||
for (int i = 0; i < meta->last; ++i) {
|
||||
int offset = meta->offsets[i];
|
||||
if (offset >= 0) {
|
||||
try {
|
||||
InterfaceWraps[i].Construct(_dataptrunsafe(offset), this);
|
||||
} catch (...) {
|
||||
while (i > 0) {
|
||||
--i;
|
||||
offset = _meta->offsets[--i];
|
||||
offset = meta->offsets[--i];
|
||||
if (offset >= 0) {
|
||||
InterfaceWraps[i].Destruct(_dataptrunsafe(offset));
|
||||
}
|
||||
@ -663,10 +676,28 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
void UpdateInterfaces(uint64 mask = 0) {
|
||||
if (!_data && !mask) return;
|
||||
if (!_data || !_meta()->equals(mask)) {
|
||||
Interfaces tmp(mask);
|
||||
tmp.swap(*this);
|
||||
|
||||
if (_data && tmp._data) {
|
||||
const InterfacesMetadata *meta = _meta(), *wasmeta = tmp._meta();
|
||||
for (int i = 0; i < meta->last; ++i) {
|
||||
int offset = meta->offsets[i], wasoffset = wasmeta->offsets[i];
|
||||
if (offset >= 0 && wasoffset >= 0) {
|
||||
InterfaceWraps[i].Assign(_dataptrunsafe(offset), tmp._dataptrunsafe(wasoffset));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
~Interfaces() {
|
||||
if (_data) {
|
||||
for (int i = 0; i < _meta->last; ++i) {
|
||||
int offset = _meta->offsets[i];
|
||||
const InterfacesMetadata *meta = _meta();
|
||||
for (int i = 0; i < meta->last; ++i) {
|
||||
int offset = meta->offsets[i];
|
||||
if (offset >= 0) {
|
||||
InterfaceWraps[i].Destruct(_dataptrunsafe(offset));
|
||||
}
|
||||
@ -677,24 +708,33 @@ public:
|
||||
|
||||
template <typename Type>
|
||||
Type *Get() {
|
||||
return (Type*)_dataptr(_meta->offsets[Type::Index()]);
|
||||
return static_cast<Type*>(_dataptr(_meta()->offsets[Type::Index()]));
|
||||
}
|
||||
template <typename Type>
|
||||
const Type *Get() const {
|
||||
return (const Type*)_dataptr(_meta->offsets[Type::Index()]);
|
||||
return static_cast<const Type*>(_dataptr(_meta()->offsets[Type::Index()]));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void *_dataptrunsafe(int skip) const {
|
||||
return (char*)_data + skip;
|
||||
return (char*)_data + sizeof(const InterfacesMetadata*) + skip;
|
||||
}
|
||||
void *_dataptr(int skip) const {
|
||||
return (skip >= 0) ? _dataptrunsafe(skip) : 0;
|
||||
}
|
||||
const InterfacesMetadata *_meta;
|
||||
const InterfacesMetadata *&_meta() const {
|
||||
return *static_cast<const InterfacesMetadata**>(_data);
|
||||
}
|
||||
void *_data;
|
||||
|
||||
Interfaces(const Interfaces &other);
|
||||
Interfaces &operator=(const Interfaces &other);
|
||||
|
||||
void swap(Interfaces &other) {
|
||||
std::swap(_data, other._data);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
|
@ -645,7 +645,7 @@ void Window::sendServiceHistoryRequest() {
|
||||
int32 userFlags = MTPDuser::flag_first_name | MTPDuser::flag_phone | MTPDuser::flag_status | MTPDuser::flag_verified;
|
||||
user = App::feedUsers(MTP_vector<MTPUser>(1, MTP_user(MTP_int(userFlags), MTP_int(ServiceUserId), MTPlong(), MTP_string("Telegram"), MTPstring(), MTPstring(), MTP_string("42777"), MTP_userProfilePhotoEmpty(), MTP_userStatusRecently(), MTPint(), MTPstring(), MTPstring())));
|
||||
}
|
||||
_serviceHistoryRequest = MTP::send(MTPmessages_GetHistory(user->input, MTP_int(0), MTP_int(0), MTP_int(1), MTP_int(0), MTP_int(0)), main->rpcDone(&MainWidget::serviceHistoryDone), main->rpcFail(&MainWidget::serviceHistoryFail));
|
||||
_serviceHistoryRequest = MTP::send(MTPmessages_GetHistory(user->input, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(1), MTP_int(0), MTP_int(0)), main->rpcDone(&MainWidget::serviceHistoryDone), main->rpcFail(&MainWidget::serviceHistoryFail));
|
||||
}
|
||||
|
||||
void Window::setupMain(bool anim, const MTPUser *self) {
|
||||
|
Loading…
Reference in New Issue
Block a user