mirror of https://github.com/procxx/kepka.git
				
				
				
			Support round video inline playback with sound.
This commit is contained in:
		
							parent
							
								
									cbf040b4dc
								
							
						
					
					
						commit
						5480a63beb
					
				
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 147 B | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 206 B | 
|  | @ -418,3 +418,7 @@ msgWaveformBar: 2px; | |||
| msgWaveformSkip: 1px; | ||||
| msgWaveformMin: 2px; | ||||
| msgWaveformMax: 20px; | ||||
| 
 | ||||
| historyVideoMessageMute: icon {{ "volume_mute", historyFileThumbIconFg }}; | ||||
| historyVideoMessageMuteSelected: icon {{ "volume_mute", historyFileThumbIconFgSelected }}; | ||||
| historyVideoMessageMuteSize: 25px; | ||||
|  |  | |||
|  | @ -892,17 +892,20 @@ void HistoryItem::clipCallback(Media::Clip::Notification notification) { | |||
| 
 | ||||
| 	switch (notification) { | ||||
| 	case NotificationReinit: { | ||||
| 		bool stopped = false; | ||||
| 		auto stopped = false; | ||||
| 		if (reader->autoPausedGif()) { | ||||
| 			if (MainWidget *m = App::main()) { | ||||
| 			if (auto m = App::main()) { | ||||
| 				if (!m->isItemVisible(this)) { // stop animation if it is not visible
 | ||||
| 					media->stopInline(); | ||||
| 					if (DocumentData *document = media->getDocument()) { // forget data from memory
 | ||||
| 					if (auto document = media->getDocument()) { // forget data from memory
 | ||||
| 						document->forget(); | ||||
| 					} | ||||
| 					stopped = true; | ||||
| 				} | ||||
| 			} | ||||
| 		} else if (reader->mode() == Media::Clip::Reader::Mode::Video && reader->state() == Media::Clip::State::Finished) { | ||||
| 			// Stop finished video message.
 | ||||
| 			media->stopInline(); | ||||
| 		} | ||||
| 		if (!stopped) { | ||||
| 			setPendingInitDimensions(); | ||||
|  |  | |||
|  | @ -1653,7 +1653,7 @@ HistoryGif::HistoryGif(HistoryItem *parent, DocumentData *document, const QStrin | |||
| 
 | ||||
| 	setStatusSize(FileStatusSizeReady); | ||||
| 
 | ||||
| 	if (!caption.isEmpty()) { | ||||
| 	if (!caption.isEmpty() && !_data->isRoundVideo()) { | ||||
| 		_caption.setText(st::messageTextStyle, caption + _parent->skipBlock(), itemTextNoMonoOptions(_parent)); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1681,8 +1681,7 @@ void HistoryGif::initDimensions() { | |||
| 		if (!_gif->autoplay()) { | ||||
| 			Ui::show(Box<InformBox>(lang(lng_gif_error))); | ||||
| 		} | ||||
| 		App::unregGifItem(_gif.get()); | ||||
| 		_gif.setBad(); | ||||
| 		setClipReader(Media::Clip::ReaderPointer::Bad()); | ||||
| 	} | ||||
| 
 | ||||
| 	if (_gif && _gif->ready()) { | ||||
|  | @ -1797,10 +1796,12 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM | |||
| 	if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; | ||||
| 
 | ||||
| 	_data->automaticLoad(_parent); | ||||
| 	bool loaded = _data->loaded(), displayLoading = (_parent->id < 0) || _data->displayLoading(); | ||||
| 	bool selected = (selection == FullSelection); | ||||
| 	auto loaded = _data->loaded(); | ||||
| 	auto displayLoading = (_parent->id < 0) || _data->displayLoading(); | ||||
| 	auto selected = (selection == FullSelection); | ||||
| 
 | ||||
| 	if (loaded && !_gif && !_gif.isBad() && cAutoPlayGif()) { | ||||
| 	auto videoFinished = _gif && (_gif->mode() == Media::Clip::Reader::Mode::Video) && (_gif->state() == Media::Clip::State::Finished); | ||||
| 	if (loaded && cAutoPlayGif() && ((!_gif && !_gif.isBad()) || videoFinished)) { | ||||
| 		Ui::autoplayMediaInlineAsync(_parent->fullId()); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1811,6 +1812,7 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM | |||
| 	auto captionw = width - st::msgPadding.left() - st::msgPadding.right(); | ||||
| 
 | ||||
| 	auto isRound = _data->isRoundVideo(); | ||||
| 	auto displayMute = false; | ||||
| 	auto animating = (_gif && _gif->started()); | ||||
| 
 | ||||
| 	if (!animating || _parent->id < 0) { | ||||
|  | @ -1848,6 +1850,13 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM | |||
| 		| ((isBubbleBottom() && _caption.isEmpty()) ? (ImageRoundCorner::BottomLeft | ImageRoundCorner::BottomRight) : ImageRoundCorner::None)); | ||||
| 	if (animating) { | ||||
| 		auto paused = App::wnd()->controller()->isGifPausedAtLeastFor(Window::GifPauseReason::Any); | ||||
| 		if (isRound) { | ||||
| 			if (_gif->mode() == Media::Clip::Reader::Mode::Video) { | ||||
| 				paused = false; | ||||
| 			} else { | ||||
| 				displayMute = true; | ||||
| 			} | ||||
| 		} | ||||
| 		p.drawPixmap(rthumb.topLeft(), _gif->current(_thumbw, _thumbh, width, height, roundRadius, roundCorners, paused ? 0 : ms)); | ||||
| 	} else { | ||||
| 		p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(_thumbw, _thumbh, width, height, roundRadius, roundCorners)); | ||||
|  | @ -1857,8 +1866,8 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM | |||
| 	} | ||||
| 
 | ||||
| 	if (radial || _gif.isBad() || (!_gif && ((!loaded && !_data->loading()) || !cAutoPlayGif()))) { | ||||
| 		float64 radialOpacity = (radial && loaded && _parent->id > 0) ? _animation->radial.opacity() : 1; | ||||
| 		QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); | ||||
| 		auto radialOpacity = (radial && loaded && _parent->id > 0) ? _animation->radial.opacity() : 1.; | ||||
| 		auto inner = QRect(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); | ||||
| 		p.setPen(Qt::NoPen); | ||||
| 		if (selected) { | ||||
| 			p.setBrush(st::msgDateImgBgSelected); | ||||
|  | @ -1908,13 +1917,21 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM | |||
| 			p.drawTextLeft(statusX, statusY, _width, _statusText, statusW - 2 * st::msgDateImgPadding.x()); | ||||
| 		} | ||||
| 	} | ||||
| 	if (displayMute) { | ||||
| 		auto muteRect = rtlrect(rthumb.x() + (rthumb.width() - st::historyVideoMessageMuteSize) / 2, rthumb.y() + rthumb.height() - st::msgDateImgDelta - st::historyVideoMessageMuteSize, st::historyVideoMessageMuteSize, st::historyVideoMessageMuteSize, _width); | ||||
| 		p.setPen(Qt::NoPen); | ||||
| 		p.setBrush(selected ? st::msgDateImgBgSelected : st::msgDateImgBg); | ||||
| 		PainterHighQualityEnabler hq(p); | ||||
| 		p.drawEllipse(muteRect); | ||||
| 		(selected ? st::historyVideoMessageMuteSelected : st::historyVideoMessageMute).paintInCenter(p, muteRect); | ||||
| 	} | ||||
| 
 | ||||
| 	if (isRound) { | ||||
| 		auto mediaUnread = _parent->isMediaUnread(); | ||||
| 		auto statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x(); | ||||
| 		auto statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y(); | ||||
| 		auto statusX = skipx + st::msgDateImgDelta + st::msgDateImgPadding.x(); | ||||
| 		auto statusY = skipy + height - st::msgDateImgDelta - statusH; | ||||
| 		auto statusY = skipy + height - st::msgDateImgDelta - statusH + st::msgDateImgPadding.y(); | ||||
| 		if (_parent->isMediaUnread()) { | ||||
| 			statusW += st::mediaUnreadSkip + st::mediaUnreadSize; | ||||
| 		} | ||||
|  | @ -1970,7 +1987,7 @@ HistoryTextState HistoryGif::getState(int x, int y, HistoryStateRequest request) | |||
| 	if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { | ||||
| 		if (_data->uploading()) { | ||||
| 			result.link = _cancell; | ||||
| 		} else if (!_gif || !cAutoPlayGif()) { | ||||
| 		} else if (!_gif || !cAutoPlayGif() || _data->isRoundVideo()) { | ||||
| 			result.link = _data->loaded() ? _openl : (_data->loading() ? _cancell : _savel); | ||||
| 		} | ||||
| 		if (_parent->getMedia() == this) { | ||||
|  | @ -2047,35 +2064,56 @@ ImagePtr HistoryGif::replyPreview() { | |||
| } | ||||
| 
 | ||||
| bool HistoryGif::playInline(bool autoplay) { | ||||
| 	using Mode = Media::Clip::Reader::Mode; | ||||
| 	if (_data->isRoundVideo() && _gif) { | ||||
| 		// Stop autoplayed silent video when we start playback by click.
 | ||||
| 		// Stop finished video message when autoplay starts.
 | ||||
| 		if ((!autoplay && _gif->mode() == Mode::Gif) | ||||
| 			|| (autoplay && _gif->mode() == Mode::Video && _gif->state() == Media::Clip::State::Finished)) { | ||||
| 			stopInline(); | ||||
| 		} | ||||
| 	} | ||||
| 	if (_gif) { | ||||
| 		stopInline(); | ||||
| 	} else if (_data->loaded(DocumentData::FilePathResolveChecked)) { | ||||
| 		if (!cAutoPlayGif()) { | ||||
| 			App::stopGifItems(); | ||||
| 		} | ||||
| 		_gif = Media::Clip::MakeReader(_data->location(), _data->data(), [this](Media::Clip::Notification notification) { | ||||
| 		auto mode = (!autoplay && _data->isRoundVideo()) ? Mode::Video : Mode::Gif; | ||||
| 		setClipReader(Media::Clip::MakeReader(_data->location(), _data->data(), [this](Media::Clip::Notification notification) { | ||||
| 			_parent->clipCallback(notification); | ||||
| 		}); | ||||
| 		App::regGifItem(_gif.get(), _parent); | ||||
| 		if (_gif) _gif->setAutoplay(); | ||||
| 		}, mode)); | ||||
| 		if (mode == Mode::Video) { | ||||
| 			if (App::main()) { | ||||
| 				App::main()->mediaMarkRead(_data); | ||||
| 			} | ||||
| 		} | ||||
| 		if (_gif && autoplay) { | ||||
| 			_gif->setAutoplay(); | ||||
| 		} | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void HistoryGif::stopInline() { | ||||
| 	if (_gif) { | ||||
| 		App::unregGifItem(_gif.get()); | ||||
| 	} | ||||
| 	_gif.reset(); | ||||
| 	clearClipReader(); | ||||
| 
 | ||||
| 	_parent->setPendingInitDimensions(); | ||||
| 	Notify::historyItemLayoutChanged(_parent); | ||||
| } | ||||
| 
 | ||||
| HistoryGif::~HistoryGif() { | ||||
| void HistoryGif::setClipReader(Media::Clip::ReaderPointer gif) { | ||||
| 	if (_gif) { | ||||
| 		App::unregGifItem(_gif.get()); | ||||
| 	} | ||||
| 	_gif = std::move(gif); | ||||
| 	if (_gif) { | ||||
| 		App::regGifItem(_gif.get(), _parent); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| HistoryGif::~HistoryGif() { | ||||
| 	clearClipReader(); | ||||
| } | ||||
| 
 | ||||
| float64 HistoryGif::dataProgress() const { | ||||
|  | @ -2099,10 +2137,6 @@ HistorySticker::HistorySticker(HistoryItem *parent, DocumentData *document) : Hi | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| class TestClickHandler : public ClickHandler { | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| void HistorySticker::initDimensions() { | ||||
| 	auto sticker = _data->sticker(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -515,6 +515,9 @@ public: | |||
| 		return _caption.originalTextWithEntities(); | ||||
| 	} | ||||
| 	bool needsBubble() const override { | ||||
| 		if (_data->isRoundVideo()) { | ||||
| 			return false; | ||||
| 		} | ||||
| 		if (!_caption.isEmpty()) { | ||||
| 			return true; | ||||
| 		} | ||||
|  | @ -546,6 +549,11 @@ protected: | |||
| 	bool dataFinished() const override; | ||||
| 	bool dataLoaded() const override; | ||||
| 
 | ||||
| 	void setClipReader(Media::Clip::ReaderPointer gif); | ||||
| 	void clearClipReader() { | ||||
| 		setClipReader(Media::Clip::ReaderPointer()); | ||||
| 	} | ||||
| 
 | ||||
| private: | ||||
| 	gsl::not_null<DocumentData*> _data; | ||||
| 	int32 _thumbw = 1; | ||||
|  |  | |||
|  | @ -54,7 +54,10 @@ MediaOverviewType messageMediaToOverviewType(HistoryMedia *media) { | |||
| 	case MediaTypeFile: return OverviewFiles; | ||||
| 	case MediaTypeMusicFile: return media->getDocument()->isMusic() ? OverviewMusicFiles : OverviewCount; | ||||
| 	case MediaTypeVoiceFile: return OverviewVoiceFiles; | ||||
| 	case MediaTypeGif: return media->getDocument()->isGifv() ? OverviewCount : OverviewFiles; | ||||
| 	case MediaTypeGif: { | ||||
| 		auto document = media->getDocument(); | ||||
| 		return (document->isGifv() || document->isRoundVideo()) ? OverviewCount : OverviewFiles; | ||||
| 	} break; | ||||
| 	default: break; | ||||
| 	} | ||||
| 	return OverviewCount; | ||||
|  |  | |||
|  | @ -338,8 +338,8 @@ void Gif::clipCallback(Media::Clip::Notification notification) { | |||
| 				_gif.setBad(); | ||||
| 				getShownDocument()->forget(); | ||||
| 			} else if (_gif->ready() && !_gif->started()) { | ||||
| 				int32 height = st::inlineMediaHeight; | ||||
| 				QSize frame = countFrameSize(); | ||||
| 				auto height = st::inlineMediaHeight; | ||||
| 				auto frame = countFrameSize(); | ||||
| 				_gif->start(frame.width(), frame.height(), _width, height, ImageRoundRadius::None, ImageRoundCorner::None); | ||||
| 			} else if (_gif->autoPausedGif() && !context()->inlineItemVisible(this)) { | ||||
| 				_gif.reset(); | ||||
|  |  | |||
|  | @ -222,11 +222,12 @@ bool MediaView::fileBubbleShown() const { | |||
| bool MediaView::gifShown() const { | ||||
| 	if (_gif && _gif->ready()) { | ||||
| 		if (!_gif->started()) { | ||||
| 			if (_doc->isVideo() && _autoplayVideoDocument != _doc && !_gif->videoPaused()) { | ||||
| 			if ((_doc->isVideo() || _doc->isRoundVideo()) && _autoplayVideoDocument != _doc && !_gif->videoPaused()) { | ||||
| 				_gif->pauseResumeVideo(); | ||||
| 				const_cast<MediaView*>(this)->_videoPaused = _gif->videoPaused(); | ||||
| 			} | ||||
| 			_gif->start(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), ImageRoundRadius::None, ImageRoundCorner::None); | ||||
| 			auto rounding = _doc->isRoundVideo() ? ImageRoundRadius::Ellipse : ImageRoundRadius::None; | ||||
| 			_gif->start(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), rounding, ImageRoundCorner::All); | ||||
| 			const_cast<MediaView*>(this)->_current = QPixmap(); | ||||
| 		} | ||||
| 		return true;// _gif->state() != Media::Clip::State::Error;
 | ||||
|  | @ -522,7 +523,7 @@ void MediaView::step_radial(TimeMs ms, bool timer) { | |||
| 		update(radialRect()); | ||||
| 	} | ||||
| 	if (_doc && _doc->loaded() && _doc->size < App::kImageSizeLimit && (!_radial.animating() || _doc->isAnimation() || _doc->isVideo())) { | ||||
| 		if (_doc->isVideo()) { | ||||
| 		if (_doc->isVideo() || _doc->isRoundVideo()) { | ||||
| 			_autoplayVideoDocument = _doc; | ||||
| 		} | ||||
| 		if (!_doc->data().isEmpty() && (_doc->isAnimation() || _doc->isVideo())) { | ||||
|  | @ -828,7 +829,7 @@ void MediaView::clipCallback(Media::Clip::Notification notification) { | |||
| 				_videoStopped = true; | ||||
| 				updateSilentVideoPlaybackState(); | ||||
| 			} else { | ||||
| 				_videoIsSilent = _doc->isVideo() && !_gif->hasAudio(); | ||||
| 				_videoIsSilent = (_doc->isVideo() || _doc->isRoundVideo()) && !_gif->hasAudio(); | ||||
| 				_videoDurationMs = _gif->getDurationMs(); | ||||
| 				_videoPositionMs = _gif->getPositionMs(); | ||||
| 				if (_videoIsSilent) { | ||||
|  | @ -1140,7 +1141,7 @@ void MediaView::showDocument(DocumentData *doc, HistoryItem *context) { | |||
| 		_overview = doc->isVideo() ? OverviewVideos : OverviewFiles; | ||||
| 		findCurrent(); | ||||
| 	} | ||||
| 	if (doc->isVideo()) { | ||||
| 	if (doc->isVideo() || doc->isRoundVideo()) { | ||||
| 		_autoplayVideoDocument = doc; | ||||
| 	} | ||||
| 	displayDocument(doc, context); | ||||
|  | @ -1383,6 +1384,14 @@ void MediaView::displayFinished() { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| Images::Options MediaView::videoThumbOptions() const { | ||||
| 	auto options = Images::Option::Smooth | Images::Option::Blurred; | ||||
| 	if (_doc->isRoundVideo()) { | ||||
| 		options |= Images::Option::Circled; | ||||
| 	} | ||||
| 	return options; | ||||
| } | ||||
| 
 | ||||
| void MediaView::initAnimation() { | ||||
| 	Expects(_doc != nullptr); | ||||
| 	Expects(_doc->isAnimation() || _doc->isVideo()); | ||||
|  | @ -1394,12 +1403,12 @@ void MediaView::initAnimation() { | |||
| 		createClipReader(); | ||||
| 		location.accessDisable(); | ||||
| 	} else if (_doc->dimensions.width() && _doc->dimensions.height()) { | ||||
| 		int w = _doc->dimensions.width(); | ||||
| 		int h = _doc->dimensions.height(); | ||||
| 		_current = _doc->thumb->pixNoCache(w, h, Images::Option::Smooth | Images::Option::Blurred, w / cIntRetinaFactor(), h / cIntRetinaFactor()); | ||||
| 		auto w = _doc->dimensions.width(); | ||||
| 		auto h = _doc->dimensions.height(); | ||||
| 		_current = _doc->thumb->pixNoCache(w, h, videoThumbOptions(), w / cIntRetinaFactor(), h / cIntRetinaFactor()); | ||||
| 		if (cRetina()) _current.setDevicePixelRatio(cRetinaFactor()); | ||||
| 	} else { | ||||
| 		_current = _doc->thumb->pixNoCache(_doc->thumb->width(), _doc->thumb->height(), Images::Option::Smooth | Images::Option::Blurred, st::mediaviewFileIconSize, st::mediaviewFileIconSize); | ||||
| 		_current = _doc->thumb->pixNoCache(_doc->thumb->width(), _doc->thumb->height(), videoThumbOptions(), st::mediaviewFileIconSize, st::mediaviewFileIconSize); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -1412,12 +1421,12 @@ void MediaView::createClipReader() { | |||
| 	if (_doc->dimensions.width() && _doc->dimensions.height()) { | ||||
| 		int w = _doc->dimensions.width(); | ||||
| 		int h = _doc->dimensions.height(); | ||||
| 		_current = _doc->thumb->pixNoCache(w, h, Images::Option::Smooth | Images::Option::Blurred, w / cIntRetinaFactor(), h / cIntRetinaFactor()); | ||||
| 		_current = _doc->thumb->pixNoCache(w, h, videoThumbOptions(), w / cIntRetinaFactor(), h / cIntRetinaFactor()); | ||||
| 		if (cRetina()) _current.setDevicePixelRatio(cRetinaFactor()); | ||||
| 	} else { | ||||
| 		_current = _doc->thumb->pixNoCache(_doc->thumb->width(), _doc->thumb->height(), Images::Option::Smooth | Images::Option::Blurred, st::mediaviewFileIconSize, st::mediaviewFileIconSize); | ||||
| 		_current = _doc->thumb->pixNoCache(_doc->thumb->width(), _doc->thumb->height(), videoThumbOptions(), st::mediaviewFileIconSize, st::mediaviewFileIconSize); | ||||
| 	} | ||||
| 	auto mode = _doc->isVideo() ? Media::Clip::Reader::Mode::Video : Media::Clip::Reader::Mode::Gif; | ||||
| 	auto mode = (_doc->isVideo() || _doc->isRoundVideo()) ? Media::Clip::Reader::Mode::Video : Media::Clip::Reader::Mode::Gif; | ||||
| 	_gif = std::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), [this](Media::Clip::Notification notification) { | ||||
| 		clipCallback(notification); | ||||
| 	}, mode); | ||||
|  | @ -1475,7 +1484,7 @@ void MediaView::initThemePreview() { | |||
| } | ||||
| 
 | ||||
| void MediaView::createClipController() { | ||||
| 	if (!_doc->isVideo()) return; | ||||
| 	if (!_doc->isVideo() && !_doc->isRoundVideo()) return; | ||||
| 
 | ||||
| 	_clipController.create(this); | ||||
| 	setClipControllerGeometry(); | ||||
|  | @ -1530,7 +1539,8 @@ void MediaView::restartVideoAtSeekPosition(TimeMs positionMs) { | |||
| 	_autoplayVideoDocument = _doc; | ||||
| 
 | ||||
| 	if (_current.isNull()) { | ||||
| 		_current = _gif->current(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), ImageRoundRadius::None, ImageRoundCorner::None, getms()); | ||||
| 		auto rounding = _doc->isRoundVideo() ? ImageRoundRadius::Ellipse : ImageRoundRadius::None; | ||||
| 		_current = _gif->current(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), rounding, ImageRoundCorner::All, getms()); | ||||
| 	} | ||||
| 	_gif = std::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), [this](Media::Clip::Notification notification) { | ||||
| 		clipCallback(notification); | ||||
|  | @ -1638,6 +1648,9 @@ void MediaView::paintEvent(QPaintEvent *e) { | |||
| 		for (int i = 0, l = region.rectCount(); i < l; ++i) { | ||||
| 			p.fillRect(rs.at(i), st::mediaviewVideoBg); | ||||
| 		} | ||||
| 		if (_doc->isRoundVideo()) { | ||||
| 			p.setCompositionMode(m); | ||||
| 		} | ||||
| 	} else { | ||||
| 		for (int i = 0, l = region.rectCount(); i < l; ++i) { | ||||
| 			p.fillRect(rs.at(i), st::mediaviewBg); | ||||
|  | @ -1670,7 +1683,8 @@ void MediaView::paintEvent(QPaintEvent *e) { | |||
| 	if (_photo || fileShown()) { | ||||
| 		QRect imgRect(_x, _y, _w, _h); | ||||
| 		if (imgRect.intersects(r)) { | ||||
| 			auto toDraw = _current.isNull() ? _gif->current(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), ImageRoundRadius::None, ImageRoundCorner::None, ms) : _current; | ||||
| 			auto rounding = _doc->isRoundVideo() ? ImageRoundRadius::Ellipse : ImageRoundRadius::None; | ||||
| 			auto toDraw = _current.isNull() ? _gif->current(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), rounding, ImageRoundCorner::None, ms) : _current; | ||||
| 			if (!_gif && (!_doc || !_doc->sticker() || _doc->sticker()->img->isNull()) && toDraw.hasAlpha()) { | ||||
| 				p.fillRect(imgRect, _transparentBrush); | ||||
| 			} | ||||
|  | @ -2011,7 +2025,7 @@ void MediaView::keyPressEvent(QKeyEvent *e) { | |||
| 	} else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return || e->key() == Qt::Key_Space) { | ||||
| 		if (_doc && !_doc->loading() && (fileBubbleShown() || !_doc->loaded())) { | ||||
| 			onDocClick(); | ||||
| 		} else if (_doc && _doc->isVideo()) { | ||||
| 		} else if (_doc && (_doc->isVideo() || _doc->isRoundVideo())) { | ||||
| 			onVideoPauseResume(); | ||||
| 		} | ||||
| 	} else if (e->key() == Qt::Key_Left) { | ||||
|  | @ -2463,7 +2477,7 @@ void MediaView::updateOver(QPoint pos) { | |||
| 	} else if (_closeNav.contains(pos)) { | ||||
| 		updateOverState(OverClose); | ||||
| 	} else if (_doc && fileShown() && QRect(_x, _y, _w, _h).contains(pos)) { | ||||
| 		if (_doc->isVideo() && _gif) { | ||||
| 		if ((_doc->isVideo() || _doc->isRoundVideo()) && _gif) { | ||||
| 			updateOverState(OverVideo); | ||||
| 		} else if (!_doc->loaded()) { | ||||
| 			updateOverState(OverIcon); | ||||
|  |  | |||
|  | @ -178,6 +178,7 @@ private: | |||
| 
 | ||||
| 	void initAnimation(); | ||||
| 	void createClipReader(); | ||||
| 	Images::Options videoThumbOptions() const; | ||||
| 
 | ||||
| 	void initThemePreview(); | ||||
| 	void destroyThemePreview(); | ||||
|  |  | |||
|  | @ -1205,14 +1205,14 @@ void DocumentOpenClickHandler::doOpen(DocumentData *data, HistoryItem *context, | |||
| 		} else if (data->size < App::kImageSizeLimit) { | ||||
| 			if (!data->data().isEmpty() && playAnimation) { | ||||
| 				if (action == ActionOnLoadPlayInline && context && context->getMedia()) { | ||||
| 					context->getMedia()->playInline(context); | ||||
| 					context->getMedia()->playInline(); | ||||
| 				} else { | ||||
| 					App::wnd()->showDocument(data, context); | ||||
| 				} | ||||
| 			} else if (location.accessEnable()) { | ||||
| 				if (data->isAnimation() || QImageReader(location.name()).canRead()) { | ||||
| 					if (action == ActionOnLoadPlayInline && context && context->getMedia()) { | ||||
| 						context->getMedia()->playInline(context); | ||||
| 						context->getMedia()->playInline(); | ||||
| 					} else { | ||||
| 						App::wnd()->showDocument(data, context); | ||||
| 					} | ||||
|  | @ -1485,7 +1485,7 @@ void DocumentData::performActionOnLoad() { | |||
| 	} else if (playAnimation) { | ||||
| 		if (loaded()) { | ||||
| 			if (_actionOnLoad == ActionOnLoadPlayInline && item->getMedia()) { | ||||
| 				item->getMedia()->playInline(item); | ||||
| 				item->getMedia()->playInline(); | ||||
| 			} else { | ||||
| 				App::wnd()->showDocument(this, item); | ||||
| 			} | ||||
|  | @ -1504,7 +1504,7 @@ void DocumentData::performActionOnLoad() { | |||
| 			} else if (loc.accessEnable()) { | ||||
| 				if (showImage && QImageReader(loc.name()).canRead()) { | ||||
| 					if (_actionOnLoad == ActionOnLoadPlayInline && item && item->getMedia()) { | ||||
| 						item->getMedia()->playInline(item); | ||||
| 						item->getMedia()->playInline(); | ||||
| 					} else { | ||||
| 						App::wnd()->showDocument(this, item); | ||||
| 					} | ||||
|  |  | |||
|  | @ -68,6 +68,11 @@ public: | |||
| 	explicit operator bool() const { | ||||
| 		return valid(); | ||||
| 	} | ||||
| 	static inline ReaderPointer Bad() { | ||||
| 		ReaderPointer result; | ||||
| 		result.setBad(); | ||||
| 		return result; | ||||
| 	} | ||||
| 	~ReaderPointer(); | ||||
| 
 | ||||
| private: | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue