mirror of https://github.com/procxx/kepka.git
				
				
				
			Snap floating player to column and corner.
This commit is contained in:
		
							parent
							
								
									8f290451b6
								
							
						
					
					
						commit
						ee6d80673a
					
				|  | @ -2648,18 +2648,7 @@ namespace { | ||||||
| 			auto gifs = ::gifItems; | 			auto gifs = ::gifItems; | ||||||
| 			for_const (auto item, gifs) { | 			for_const (auto item, gifs) { | ||||||
| 				if (auto media = item->getMedia()) { | 				if (auto media = item->getMedia()) { | ||||||
| 					media->stopInline(); | 					if (!media->isRoundVideoPlaying()) { | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void stopRoundVideoPlayback() { |  | ||||||
| 		if (!::gifItems.isEmpty()) { |  | ||||||
| 			auto gifs = ::gifItems; |  | ||||||
| 			for_const (auto item, gifs) { |  | ||||||
| 				if (auto media = item->getMedia()) { |  | ||||||
| 					if (media->isRoundVideoPlaying()) { |  | ||||||
| 						media->stopInline(); | 						media->stopInline(); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | @ -2631,7 +2631,7 @@ void HistoryWidget::onScroll() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool HistoryWidget::isItemCompletelyHidden(HistoryItem *item) const { | bool HistoryWidget::isItemCompletelyHidden(HistoryItem *item) const { | ||||||
| 	auto top = _list->itemTop(item); | 	auto top = _list ? _list->itemTop(item) : -2; | ||||||
| 	if (top < 0) { | 	if (top < 0) { | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
|  | @ -3428,7 +3428,7 @@ bool HistoryWidget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn | ||||||
| QRect HistoryWidget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) { | QRect HistoryWidget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) { | ||||||
| 	if (playerColumn == Window::Column::Third && _tabbedSection) { | 	if (playerColumn == Window::Column::Third && _tabbedSection) { | ||||||
| 		auto tabbedColumn = (myColumn == Window::Column::First) ? Window::Column::Second : Window::Column::Third; | 		auto tabbedColumn = (myColumn == Window::Column::First) ? Window::Column::Second : Window::Column::Third; | ||||||
| 		return mapToGlobal(_tabbedSection->rectForFloatPlayer(tabbedColumn, playerColumn)); | 		return _tabbedSection->rectForFloatPlayer(tabbedColumn, playerColumn); | ||||||
| 	} | 	} | ||||||
| 	return mapToGlobal(_scroll->geometry()); | 	return mapToGlobal(_scroll->geometry()); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -98,9 +98,11 @@ StackItemSection::StackItemSection(std::unique_ptr<Window::SectionMemento> &&mem | ||||||
| StackItemSection::~StackItemSection() { | StackItemSection::~StackItemSection() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename ToggleCallback> | template <typename ToggleCallback, typename DraggedCallback> | ||||||
| MainWidget::Float::Float(QWidget *parent, HistoryItem *item, ToggleCallback callback) : widget(parent, item, [this, toggle = std::move(callback)](bool visible) { | MainWidget::Float::Float(QWidget *parent, HistoryItem *item, ToggleCallback toggle, DraggedCallback dragged) : widget(parent, item, [this, toggle = std::move(toggle)](bool visible) { | ||||||
| 	toggle(this, visible); | 	toggle(this, visible); | ||||||
|  | }, [this, dragged = std::move(dragged)](bool closed) { | ||||||
|  | 	dragged(this, closed); | ||||||
| }) { | }) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -248,7 +250,11 @@ void MainWidget::checkCurrentFloatPlayer() { | ||||||
| 						_playerFloats.push_back(std::make_unique<Float>(this, item, [this](Float *instance, bool visible) { | 						_playerFloats.push_back(std::make_unique<Float>(this, item, [this](Float *instance, bool visible) { | ||||||
| 							instance->hiddenByWidget = !visible; | 							instance->hiddenByWidget = !visible; | ||||||
| 							toggleFloatPlayer(instance); | 							toggleFloatPlayer(instance); | ||||||
|  | 						}, [this](Float *instance, bool closed) { | ||||||
|  | 							finishFloatPlayerDrag(instance, closed); | ||||||
| 						})); | 						})); | ||||||
|  | 						currentFloatPlayer()->corner = _playerFloatCorner; | ||||||
|  | 						currentFloatPlayer()->column = _playerFloatColumn; | ||||||
| 						checkFloatPlayerVisibility(); | 						checkFloatPlayerVisibility(); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  | @ -313,8 +319,15 @@ void MainWidget::updateFloatPlayerPosition(Float *instance) { | ||||||
| 	position = mapFromGlobal(position); | 	position = mapFromGlobal(position); | ||||||
| 
 | 
 | ||||||
| 	auto hiddenTop = Window::IsTopCorner(instance->corner) ? -instance->widget->height() : height(); | 	auto hiddenTop = Window::IsTopCorner(instance->corner) ? -instance->widget->height() : height(); | ||||||
| 	auto visibleTop = position.y(); | 	position.setY(anim::interpolate(hiddenTop, position.y(), visible)); | ||||||
| 	instance->widget->move(position.x(), anim::interpolate(hiddenTop, visibleTop, visible)); | 	if (!instance->widget->dragged()) { | ||||||
|  | 		auto dragged = instance->draggedAnimation.current(1.); | ||||||
|  | 		if (dragged < 1.) { | ||||||
|  | 			position.setX(anim::interpolate(instance->dragFrom.x(), position.x(), dragged)); | ||||||
|  | 			position.setY(anim::interpolate(instance->dragFrom.y(), position.y(), dragged)); | ||||||
|  | 		} | ||||||
|  | 		instance->widget->move(position); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWidget::removeFloatPlayer(Float *instance) { | void MainWidget::removeFloatPlayer(Float *instance) { | ||||||
|  | @ -358,6 +371,77 @@ Window::AbstractSectionWidget *MainWidget::getFloatPlayerSection(gsl::not_null<W | ||||||
| 	return _history; | 	return _history; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void MainWidget::updateFloatPlayerColumnCorner(QPoint center) { | ||||||
|  | 	Expects(!_playerFloats.empty()); | ||||||
|  | 	auto size = _playerFloats.back()->widget->size(); | ||||||
|  | 	auto min = INT_MAX; | ||||||
|  | 	auto checkSection = [this, center, size, &min](Window::AbstractSectionWidget *widget, Window::Column myColumn, Window::Column playerColumn) { | ||||||
|  | 		auto rect = mapFromGlobal(widget->rectForFloatPlayer(myColumn, playerColumn)); | ||||||
|  | 		auto left = rect.x() + (size.width() / 2); | ||||||
|  | 		auto right = rect.x() + rect.width() - (size.width() / 2); | ||||||
|  | 		auto top = rect.y() + (size.height() / 2); | ||||||
|  | 		auto bottom = rect.y() + rect.height() - (size.height() / 2); | ||||||
|  | 		auto checkCorner = [this, playerColumn, &min](int distance, Window::Corner corner) { | ||||||
|  | 			if (min > distance) { | ||||||
|  | 				min = distance; | ||||||
|  | 				_playerFloatColumn = playerColumn; | ||||||
|  | 				_playerFloatCorner = corner; | ||||||
|  | 			} | ||||||
|  | 		}; | ||||||
|  | 		checkCorner((QPoint(left, top) - center).manhattanLength(), Window::Corner::TopLeft); | ||||||
|  | 		checkCorner((QPoint(right, top) - center).manhattanLength(), Window::Corner::TopRight); | ||||||
|  | 		checkCorner((QPoint(left, bottom) - center).manhattanLength(), Window::Corner::BottomLeft); | ||||||
|  | 		checkCorner((QPoint(right, bottom) - center).manhattanLength(), Window::Corner::BottomRight); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	if (!Adaptive::Normal()) { | ||||||
|  | 		if (Adaptive::OneColumn() && selectingPeer()) { | ||||||
|  | 			checkSection(_dialogs, Window::Column::First, Window::Column::First); | ||||||
|  | 		} else if (_overview) { | ||||||
|  | 			checkSection(_overview, Window::Column::Second, Window::Column::Second); | ||||||
|  | 		} else if (_wideSection) { | ||||||
|  | 			checkSection(_wideSection, Window::Column::Second, Window::Column::Second); | ||||||
|  | 		} else if (!Adaptive::OneColumn() || _history->peer()) { | ||||||
|  | 			checkSection(_history, Window::Column::Second, Window::Column::Second); | ||||||
|  | 			checkSection(_history, Window::Column::Second, Window::Column::Third); | ||||||
|  | 		} else { | ||||||
|  | 			checkSection(_dialogs, Window::Column::First, Window::Column::First); | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		checkSection(_dialogs, Window::Column::First, Window::Column::First); | ||||||
|  | 		if (_overview) { | ||||||
|  | 			checkSection(_overview, Window::Column::Second, Window::Column::Second); | ||||||
|  | 		} else if (_wideSection) { | ||||||
|  | 			checkSection(_wideSection, Window::Column::Second, Window::Column::Second); | ||||||
|  | 		} else { | ||||||
|  | 			checkSection(_history, Window::Column::Second, Window::Column::Second); | ||||||
|  | 			checkSection(_history, Window::Column::Second, Window::Column::Third); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MainWidget::finishFloatPlayerDrag(Float *instance, bool closed) { | ||||||
|  | 	instance->dragFrom = instance->widget->pos(); | ||||||
|  | 
 | ||||||
|  | 	updateFloatPlayerColumnCorner(instance->widget->geometry().center()); | ||||||
|  | 	instance->column = _playerFloatColumn; | ||||||
|  | 	instance->corner = _playerFloatCorner; | ||||||
|  | 
 | ||||||
|  | 	instance->draggedAnimation.finish(); | ||||||
|  | 	instance->draggedAnimation.start([this, instance] { updateFloatPlayerPosition(instance); }, 0., 1., st::slideDuration, anim::sineInOut); | ||||||
|  | 	updateFloatPlayerPosition(instance); | ||||||
|  | 
 | ||||||
|  | 	if (closed) { | ||||||
|  | 		if (auto item = instance->widget->item()) { | ||||||
|  | 			auto voiceData = Media::Player::instance()->current(AudioMsgId::Type::Voice); | ||||||
|  | 			if (_player && voiceData.contextId() == item->fullId()) { | ||||||
|  | 				_player->entity()->stopAndClose(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		instance->widget->detach(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) { | bool MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) { | ||||||
| 	PeerData *p = App::peer(peer); | 	PeerData *p = App::peer(peer); | ||||||
| 	if (!peer || (p->isChannel() && !p->asChannel()->canPublish() && p->asChannel()->isBroadcast()) || (p->isChat() && !p->asChat()->canWrite()) || (p->isUser() && p->asUser()->isInaccessible())) { | 	if (!peer || (p->isChannel() && !p->asChannel()->canPublish() && p->asChannel()->isBroadcast()) || (p->isChat() && !p->asChat()->canWrite()) || (p->isUser() && p->asUser()->isInaccessible())) { | ||||||
|  | @ -1816,7 +1900,6 @@ void MainWidget::setCurrentCall(Calls::Call *call) { | ||||||
| 				destroyCallTopBar(); | 				destroyCallTopBar(); | ||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
| 		App::stopRoundVideoPlayback(); |  | ||||||
| 	} else { | 	} else { | ||||||
| 		destroyCallTopBar(); | 		destroyCallTopBar(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -463,8 +463,8 @@ protected: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| 	struct Float { | 	struct Float { | ||||||
| 		template <typename ToggleCallback> | 		template <typename ToggleCallback, typename DraggedCallback> | ||||||
| 		Float(QWidget *parent, HistoryItem *item, ToggleCallback callback); | 		Float(QWidget *parent, HistoryItem *item, ToggleCallback callback, DraggedCallback dragged); | ||||||
| 
 | 
 | ||||||
| 		bool hiddenByWidget = false; | 		bool hiddenByWidget = false; | ||||||
| 		bool hiddenByHistory = false; | 		bool hiddenByHistory = false; | ||||||
|  | @ -472,7 +472,8 @@ private: | ||||||
| 		Animation visibleAnimation; | 		Animation visibleAnimation; | ||||||
| 		Window::Corner corner = Window::Corner::TopRight; | 		Window::Corner corner = Window::Corner::TopRight; | ||||||
| 		Window::Column column = Window::Column::Second; | 		Window::Column column = Window::Column::Second; | ||||||
| 		QPoint position; | 		QPoint dragFrom; | ||||||
|  | 		Animation draggedAnimation; | ||||||
| 		object_ptr<Media::Player::Float> widget; | 		object_ptr<Media::Player::Float> widget; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | @ -584,6 +585,8 @@ private: | ||||||
| 		return _playerFloats.empty() ? nullptr : _playerFloats.back().get(); | 		return _playerFloats.empty() ? nullptr : _playerFloats.back().get(); | ||||||
| 	} | 	} | ||||||
| 	Window::AbstractSectionWidget *getFloatPlayerSection(gsl::not_null<Window::Column*> column); | 	Window::AbstractSectionWidget *getFloatPlayerSection(gsl::not_null<Window::Column*> column); | ||||||
|  | 	void finishFloatPlayerDrag(Float *instance, bool closed); | ||||||
|  | 	void updateFloatPlayerColumnCorner(QPoint center); | ||||||
| 
 | 
 | ||||||
| 	bool ptsUpdated(int32 pts, int32 ptsCount); | 	bool ptsUpdated(int32 pts, int32 ptsCount); | ||||||
| 	bool ptsUpdated(int32 pts, int32 ptsCount, const MTPUpdates &updates); | 	bool ptsUpdated(int32 pts, int32 ptsCount, const MTPUpdates &updates); | ||||||
|  | @ -637,6 +640,8 @@ private: | ||||||
| 	object_ptr<Media::Player::Panel> _playerPanel; | 	object_ptr<Media::Player::Panel> _playerPanel; | ||||||
| 	bool _playerUsingPanel = false; | 	bool _playerUsingPanel = false; | ||||||
| 	std::vector<std::unique_ptr<Float>> _playerFloats; | 	std::vector<std::unique_ptr<Float>> _playerFloats; | ||||||
|  | 	Window::Corner _playerFloatCorner = Window::Corner::TopRight; | ||||||
|  | 	Window::Column _playerFloatColumn = Window::Column::Second; | ||||||
| 
 | 
 | ||||||
| 	QPointer<ConfirmBox> _forwardConfirm; // for single column layout
 | 	QPointer<ConfirmBox> _forwardConfirm; // for single column layout
 | ||||||
| 	object_ptr<HistoryHider> _hider = { nullptr }; | 	object_ptr<HistoryHider> _hider = { nullptr }; | ||||||
|  |  | ||||||
|  | @ -316,7 +316,7 @@ void Mixer::Track::reattach(AudioMsgId::Type type) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	alSourcei(stream.source, AL_SAMPLE_OFFSET, qMax(state.position - bufferedPosition, 0LL)); | 	alSourcei(stream.source, AL_SAMPLE_OFFSET, qMax(state.position - bufferedPosition, 0LL)); | ||||||
| 	if (!IsStopped(state.state)) { | 	if (!IsStopped(state.state) && state.state != State::PausedAtEnd) { | ||||||
| 		alSourcef(stream.source, AL_GAIN, ComputeVolume(type)); | 		alSourcef(stream.source, AL_GAIN, ComputeVolume(type)); | ||||||
| 		alSourcePlay(stream.source); | 		alSourcePlay(stream.source); | ||||||
| 		if (IsPaused(state.state)) { | 		if (IsPaused(state.state)) { | ||||||
|  | @ -781,6 +781,7 @@ void Mixer::pause(const AudioMsgId &audio, bool fast) { | ||||||
| 			} | 			} | ||||||
| 		} break; | 		} break; | ||||||
| 
 | 
 | ||||||
|  | 		case State::Pausing: | ||||||
| 		case State::Stopping: { | 		case State::Stopping: { | ||||||
| 			track->state.state = fast ? State::Paused : State::Pausing; | 			track->state.state = fast ? State::Paused : State::Pausing; | ||||||
| 		} break; | 		} break; | ||||||
|  |  | ||||||
|  | @ -29,9 +29,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org | ||||||
| namespace Media { | namespace Media { | ||||||
| namespace Player { | namespace Player { | ||||||
| 
 | 
 | ||||||
| Float::Float(QWidget *parent, HistoryItem *item, base::lambda<void(bool visible)> toggleCallback) : TWidget(parent) | Float::Float(QWidget *parent, HistoryItem *item, base::lambda<void(bool visible)> toggleCallback, base::lambda<void(bool closed)> draggedCallback) : TWidget(parent) | ||||||
| , _item(item) | , _item(item) | ||||||
| , _toggleCallback(std::move(toggleCallback)) { | , _toggleCallback(std::move(toggleCallback)) | ||||||
|  | , _draggedCallback(std::move(draggedCallback)) { | ||||||
| 	auto media = _item->getMedia(); | 	auto media = _item->getMedia(); | ||||||
| 	t_assert(media != nullptr); | 	t_assert(media != nullptr); | ||||||
| 
 | 
 | ||||||
|  | @ -56,14 +57,56 @@ Float::Float(QWidget *parent, HistoryItem *item, base::lambda<void(bool visible) | ||||||
| 
 | 
 | ||||||
| void Float::mousePressEvent(QMouseEvent *e) { | void Float::mousePressEvent(QMouseEvent *e) { | ||||||
| 	_down = true; | 	_down = true; | ||||||
|  | 	_downPoint = e->pos(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Float::mouseMoveEvent(QMouseEvent *e) { | ||||||
|  | 	if (_down && (e->pos() - _downPoint).manhattanLength() > QApplication::startDragDistance()) { | ||||||
|  | 		_down = false; | ||||||
|  | 		_drag = true; | ||||||
|  | 		_dragLocalPoint = e->pos(); | ||||||
|  | 	} else if (_drag) { | ||||||
|  | 		auto delta = (e->pos() - _dragLocalPoint); | ||||||
|  | 		move(pos() + delta); | ||||||
|  | 		setOpacity(outRatio()); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float64 Float::outRatio() const { | ||||||
|  | 	auto parent = parentWidget()->rect(); | ||||||
|  | 	auto min = 1.; | ||||||
|  | 	if (x() < parent.x()) { | ||||||
|  | 		accumulate_min(min, 1. - (parent.x() - x()) / float64(width())); | ||||||
|  | 	} | ||||||
|  | 	if (y() < parent.y()) { | ||||||
|  | 		accumulate_min(min, 1. - (parent.y() - y()) / float64(height())); | ||||||
|  | 	} | ||||||
|  | 	if (x() + width() > parent.x() + parent.width()) { | ||||||
|  | 		accumulate_min(min, 1. - (x() + width() - parent.x() - parent.width()) / float64(width())); | ||||||
|  | 	} | ||||||
|  | 	if (y() + height() > parent.y() + parent.height()) { | ||||||
|  | 		accumulate_min(min, 1. - (y() + height() - parent.y() - parent.height()) / float64(height())); | ||||||
|  | 	} | ||||||
|  | 	return snap(min, 0., 1.); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Float::mouseReleaseEvent(QMouseEvent *e) { | void Float::mouseReleaseEvent(QMouseEvent *e) { | ||||||
| 	if (_down && _item) { | 	if (_down) { | ||||||
| 		if (auto media = _item->getMedia()) { | 		_down = false; | ||||||
|  | 		if (auto media = _item ? _item->getMedia() : nullptr) { | ||||||
| 			media->playInline(); | 			media->playInline(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	if (_drag) { | ||||||
|  | 		finishDrag(outRatio() < 0.5); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Float::finishDrag(bool closed) { | ||||||
|  | 	_drag = false; | ||||||
|  | 	if (_draggedCallback) { | ||||||
|  | 		_draggedCallback(closed); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Float::mouseDoubleClickEvent(QMouseEvent *e) { | void Float::mouseDoubleClickEvent(QMouseEvent *e) { | ||||||
|  |  | ||||||
|  | @ -29,21 +29,29 @@ namespace Player { | ||||||
| 
 | 
 | ||||||
| class Float : public TWidget, private base::Subscriber { | class Float : public TWidget, private base::Subscriber { | ||||||
| public: | public: | ||||||
| 	Float(QWidget *parent, HistoryItem *item, base::lambda<void(bool visible)> toggleCallback); | 	Float(QWidget *parent, HistoryItem *item, base::lambda<void(bool visible)> toggleCallback, base::lambda<void(bool closed)> draggedCallback); | ||||||
| 
 | 
 | ||||||
| 	HistoryItem *item() const { | 	HistoryItem *item() const { | ||||||
| 		return _item; | 		return _item; | ||||||
| 	} | 	} | ||||||
| 	void setOpacity(float64 opacity) { | 	void setOpacity(float64 opacity) { | ||||||
| 		_opacity = opacity; | 		if (_opacity != opacity) { | ||||||
| 		update(); | 			_opacity = opacity; | ||||||
|  | 			update(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	void detach(); | 	void detach(); | ||||||
| 	bool detached() const { | 	bool detached() const { | ||||||
| 		return !_item; | 		return !_item; | ||||||
| 	} | 	} | ||||||
|  | 	bool dragged() const { | ||||||
|  | 		return _drag; | ||||||
|  | 	} | ||||||
| 	void resetMouseState() { | 	void resetMouseState() { | ||||||
| 		_down = false; | 		_down = false; | ||||||
|  | 		if (_drag) { | ||||||
|  | 			finishDrag(false); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	void ui_repaintHistoryItem(const HistoryItem *item) { | 	void ui_repaintHistoryItem(const HistoryItem *item) { | ||||||
| 		if (item == _item) { | 		if (item == _item) { | ||||||
|  | @ -53,11 +61,13 @@ public: | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
| 	void paintEvent(QPaintEvent *e) override; | 	void paintEvent(QPaintEvent *e) override; | ||||||
|  | 	void mouseMoveEvent(QMouseEvent *e) override; | ||||||
| 	void mousePressEvent(QMouseEvent *e) override; | 	void mousePressEvent(QMouseEvent *e) override; | ||||||
| 	void mouseReleaseEvent(QMouseEvent *e) override; | 	void mouseReleaseEvent(QMouseEvent *e) override; | ||||||
| 	void mouseDoubleClickEvent(QMouseEvent *e) override; | 	void mouseDoubleClickEvent(QMouseEvent *e) override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  | 	float64 outRatio() const; | ||||||
| 	Clip::Reader *getReader() const; | 	Clip::Reader *getReader() const; | ||||||
| 	void repaintItem(); | 	void repaintItem(); | ||||||
| 	void prepareShadow(); | 	void prepareShadow(); | ||||||
|  | @ -65,6 +75,7 @@ private: | ||||||
| 	bool fillFrame(); | 	bool fillFrame(); | ||||||
| 	QRect getInnerRect() const; | 	QRect getInnerRect() const; | ||||||
| 	void updatePlayback(); | 	void updatePlayback(); | ||||||
|  | 	void finishDrag(bool closed); | ||||||
| 
 | 
 | ||||||
| 	HistoryItem *_item = nullptr; | 	HistoryItem *_item = nullptr; | ||||||
| 	base::lambda<void(bool visible)> _toggleCallback; | 	base::lambda<void(bool visible)> _toggleCallback; | ||||||
|  | @ -74,6 +85,11 @@ private: | ||||||
| 	QPixmap _shadow; | 	QPixmap _shadow; | ||||||
| 	QImage _frame; | 	QImage _frame; | ||||||
| 	bool _down = false; | 	bool _down = false; | ||||||
|  | 	QPoint _downPoint; | ||||||
|  | 
 | ||||||
|  | 	bool _drag = false; | ||||||
|  | 	QPoint _dragLocalPoint; | ||||||
|  | 	base::lambda<void(bool closed)> _draggedCallback; | ||||||
| 
 | 
 | ||||||
| 	std::unique_ptr<Clip::Playback> _roundPlayback; | 	std::unique_ptr<Clip::Playback> _roundPlayback; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -187,18 +187,23 @@ void Widget::updateVolumeToggleIcon() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Widget::setCloseCallback(base::lambda<void()> callback) { | void Widget::setCloseCallback(base::lambda<void()> callback) { | ||||||
| 	_close->setClickedCallback([this, callback = std::move(callback)] { | 	_closeCallback = std::move(callback); | ||||||
| 		_voiceIsActive = false; | 	_close->setClickedCallback([this] { stopAndClose(); }); | ||||||
| 		if (_type == AudioMsgId::Type::Voice) { | } | ||||||
| 			auto songData = instance()->current(AudioMsgId::Type::Song); | 
 | ||||||
| 			auto songState = mixer()->currentState(AudioMsgId::Type::Song); | void Widget::stopAndClose() { | ||||||
| 			if (songData == songState.id && !IsStoppedOrStopping(songState.state)) { | 	_voiceIsActive = false; | ||||||
| 				instance()->stop(AudioMsgId::Type::Voice); | 	if (_type == AudioMsgId::Type::Voice) { | ||||||
| 				return; | 		auto songData = instance()->current(AudioMsgId::Type::Song); | ||||||
| 			} | 		auto songState = mixer()->currentState(AudioMsgId::Type::Song); | ||||||
|  | 		if (songData == songState.id && !IsStoppedOrStopping(songState.state)) { | ||||||
|  | 			instance()->stop(AudioMsgId::Type::Voice); | ||||||
|  | 			return; | ||||||
| 		} | 		} | ||||||
| 		callback(); | 	} | ||||||
| 	}); | 	if (_closeCallback) { | ||||||
|  | 		_closeCallback(); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Widget::setShadowGeometryToLeft(int x, int y, int w, int h) { | void Widget::setShadowGeometryToLeft(int x, int y, int w, int h) { | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ public: | ||||||
| 	Widget(QWidget *parent); | 	Widget(QWidget *parent); | ||||||
| 
 | 
 | ||||||
| 	void setCloseCallback(base::lambda<void()> callback); | 	void setCloseCallback(base::lambda<void()> callback); | ||||||
| 
 | 	void stopAndClose(); | ||||||
| 	void setShadowGeometryToLeft(int x, int y, int w, int h); | 	void setShadowGeometryToLeft(int x, int y, int w, int h); | ||||||
| 	void showShadow(); | 	void showShadow(); | ||||||
| 	void hideShadow(); | 	void hideShadow(); | ||||||
|  | @ -101,6 +101,7 @@ private: | ||||||
| 	// We change _voiceIsActive to false only manually or from tracksFinished().
 | 	// We change _voiceIsActive to false only manually or from tracksFinished().
 | ||||||
| 	AudioMsgId::Type _type = AudioMsgId::Type::Unknown; | 	AudioMsgId::Type _type = AudioMsgId::Type::Unknown; | ||||||
| 	bool _voiceIsActive = false; | 	bool _voiceIsActive = false; | ||||||
|  | 	base::lambda<void()> _closeCallback; | ||||||
| 
 | 
 | ||||||
| 	bool _labelsOver = false; | 	bool _labelsOver = false; | ||||||
| 	bool _labelsDown = false; | 	bool _labelsDown = false; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue