mirror of https://github.com/procxx/kepka.git
				
				
				
			
		
			
				
	
	
		
			355 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			355 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
	
/*
 | 
						|
This file is part of Telegram Desktop,
 | 
						|
the official desktop application for the Telegram messaging service.
 | 
						|
 | 
						|
For license and copyright information please follow this link:
 | 
						|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
						|
*/
 | 
						|
#include "info/media/info_media_inner_widget.h"
 | 
						|
 | 
						|
#include <rpl/flatten_latest.h>
 | 
						|
#include "boxes/abstract_box.h"
 | 
						|
#include "info/media/info_media_list_widget.h"
 | 
						|
#include "info/media/info_media_buttons.h"
 | 
						|
#include "info/media/info_media_empty_widget.h"
 | 
						|
#include "info/profile/info_profile_icon.h"
 | 
						|
#include "info/info_controller.h"
 | 
						|
#include "ui/widgets/discrete_sliders.h"
 | 
						|
#include "ui/widgets/shadow.h"
 | 
						|
#include "ui/widgets/buttons.h"
 | 
						|
#include "ui/widgets/box_content_divider.h"
 | 
						|
#include "ui/wrap/vertical_layout.h"
 | 
						|
#include "ui/search_field_controller.h"
 | 
						|
#include "styles/style_info.h"
 | 
						|
#include "lang/lang_keys.h"
 | 
						|
 | 
						|
namespace Info {
 | 
						|
namespace Media {
 | 
						|
 | 
						|
InnerWidget::InnerWidget(
 | 
						|
	QWidget *parent,
 | 
						|
	not_null<Controller*> controller)
 | 
						|
: RpWidget(parent)
 | 
						|
, _controller(controller)
 | 
						|
, _empty(this) {
 | 
						|
	_empty->heightValue(
 | 
						|
	) | rpl::start_with_next(
 | 
						|
		[this] { refreshHeight(); },
 | 
						|
		_empty->lifetime());
 | 
						|
	_list = setupList();
 | 
						|
}
 | 
						|
 | 
						|
// Allows showing additional shared media links and tabs.
 | 
						|
// Was done for top level tabs support.
 | 
						|
// Now used for shared media in Saved Messages.
 | 
						|
void InnerWidget::setupOtherTypes() {
 | 
						|
	if (_controller->key().peer()->isSelf() && _isStackBottom) {
 | 
						|
		createOtherTypes();
 | 
						|
	} else {
 | 
						|
		_otherTypes.destroy();
 | 
						|
		refreshHeight();
 | 
						|
	}
 | 
						|
	//rpl::combine(
 | 
						|
	//	_controller->wrapValue(),
 | 
						|
	//	_controller->searchEnabledByContent()
 | 
						|
	//) | rpl::start_with_next([this](Wrap wrap, bool enabled) {
 | 
						|
	//	_searchEnabled = enabled;
 | 
						|
	//	refreshSearchField();
 | 
						|
	//}, lifetime());
 | 
						|
}
 | 
						|
 | 
						|
void InnerWidget::createOtherTypes() {
 | 
						|
	//_otherTabsShadow.create(this);
 | 
						|
	//_otherTabsShadow->show();
 | 
						|
 | 
						|
	//_otherTabs = nullptr;
 | 
						|
	_otherTypes.create(this);
 | 
						|
	_otherTypes->show();
 | 
						|
 | 
						|
	createTypeButtons();
 | 
						|
	_otherTypes->add(object_ptr<Ui::BoxContentDivider>(_otherTypes));
 | 
						|
	//createTabs();
 | 
						|
 | 
						|
	_otherTypes->resizeToWidth(width());
 | 
						|
	_otherTypes->heightValue(
 | 
						|
	) | rpl::start_with_next(
 | 
						|
		[this] { refreshHeight(); },
 | 
						|
		_otherTypes->lifetime());
 | 
						|
}
 | 
						|
 | 
						|
void InnerWidget::createTypeButtons() {
 | 
						|
	auto wrap = _otherTypes->add(object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
 | 
						|
		_otherTypes,
 | 
						|
		object_ptr<Ui::VerticalLayout>(_otherTypes)));
 | 
						|
	auto content = wrap->entity();
 | 
						|
	content->add(object_ptr<Ui::FixedHeightWidget>(
 | 
						|
		content,
 | 
						|
		st::infoProfileSkip));
 | 
						|
 | 
						|
	auto tracker = Ui::MultiSlideTracker();
 | 
						|
	auto addMediaButton = [&](
 | 
						|
			Type buttonType,
 | 
						|
			const style::icon &icon) {
 | 
						|
		if (buttonType == type()) {
 | 
						|
			return;
 | 
						|
		}
 | 
						|
		auto result = AddButton(
 | 
						|
			content,
 | 
						|
			_controller,
 | 
						|
			_controller->key().peer(),
 | 
						|
			_controller->migrated(),
 | 
						|
			buttonType,
 | 
						|
			tracker);
 | 
						|
		object_ptr<Profile::FloatingIcon>(
 | 
						|
			result,
 | 
						|
			icon,
 | 
						|
			st::infoSharedMediaButtonIconPosition)->show();
 | 
						|
	};
 | 
						|
	//auto addCommonGroupsButton = [&](
 | 
						|
	//		not_null<UserData*> user,
 | 
						|
	//		const style::icon &icon) {
 | 
						|
	//	auto result = AddCommonGroupsButton(
 | 
						|
	//		content,
 | 
						|
	//		_controller,
 | 
						|
	//		user,
 | 
						|
	//		tracker);
 | 
						|
	//	object_ptr<Profile::FloatingIcon>(
 | 
						|
	//		result,
 | 
						|
	//		icon,
 | 
						|
	//		st::infoSharedMediaButtonIconPosition)->show();
 | 
						|
	//};
 | 
						|
 | 
						|
	addMediaButton(Type::Photo, st::infoIconMediaPhoto);
 | 
						|
	addMediaButton(Type::Video, st::infoIconMediaVideo);
 | 
						|
	addMediaButton(Type::File, st::infoIconMediaFile);
 | 
						|
	addMediaButton(Type::MusicFile, st::infoIconMediaAudio);
 | 
						|
	addMediaButton(Type::Link, st::infoIconMediaLink);
 | 
						|
	if (auto user = _controller->key().peer()->asUser()) {
 | 
						|
//		addCommonGroupsButton(user, st::infoIconMediaGroup);
 | 
						|
	}
 | 
						|
	addMediaButton(Type::RoundVoiceFile, st::infoIconMediaVoice);
 | 
						|
 | 
						|
	content->add(object_ptr<Ui::FixedHeightWidget>(
 | 
						|
		content,
 | 
						|
		st::infoProfileSkip));
 | 
						|
	wrap->toggleOn(tracker.atLeastOneShownValue());
 | 
						|
	wrap->finishAnimating();
 | 
						|
}
 | 
						|
 | 
						|
//void InnerWidget::createTabs() {
 | 
						|
//	_otherTabs = _otherTypes->add(object_ptr<Ui::SettingsSlider>(
 | 
						|
//		this,
 | 
						|
//		st::infoTabs));
 | 
						|
//	auto sections = QStringList();
 | 
						|
//	sections.push_back(tr::lng_media_type_photos(tr::now).toUpper());
 | 
						|
//	sections.push_back(tr::lng_media_type_videos(tr::now).toUpper());
 | 
						|
//	sections.push_back(tr::lng_media_type_files(tr::now).toUpper());
 | 
						|
//	_otherTabs->setSections(sections);
 | 
						|
//	_otherTabs->setActiveSection(*TypeToTabIndex(type()));
 | 
						|
//	_otherTabs->finishAnimating();
 | 
						|
//
 | 
						|
//	_otherTabs->sectionActivated(
 | 
						|
//	) | rpl::map([](int index) {
 | 
						|
//		return TabIndexToType(index);
 | 
						|
//	}) | rpl::start_with_next(
 | 
						|
//		[this](Type newType) {
 | 
						|
//			if (type() != newType) {
 | 
						|
//				switchToTab(Memento(
 | 
						|
//					_controller->peerId(),
 | 
						|
//					_controller->migratedPeerId(),
 | 
						|
//					newType));
 | 
						|
//			}
 | 
						|
//		},
 | 
						|
//		_otherTabs->lifetime());
 | 
						|
//}
 | 
						|
 | 
						|
Type InnerWidget::type() const {
 | 
						|
	return _controller->section().mediaType();
 | 
						|
}
 | 
						|
 | 
						|
void InnerWidget::visibleTopBottomUpdated(
 | 
						|
		int visibleTop,
 | 
						|
		int visibleBottom) {
 | 
						|
	setChildVisibleTopBottom(_list, visibleTop, visibleBottom);
 | 
						|
}
 | 
						|
 | 
						|
bool InnerWidget::showInternal(not_null<Memento*> memento) {
 | 
						|
	if (!_controller->validateMementoPeer(memento)) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	auto mementoType = memento->section().mediaType();
 | 
						|
	if (mementoType == type()) {
 | 
						|
		restoreState(memento);
 | 
						|
		return true;
 | 
						|
 | 
						|
	// Allows showing additional shared media links and tabs.
 | 
						|
	// Was done for top level tabs support.
 | 
						|
	//
 | 
						|
	//} else if (_otherTypes) {
 | 
						|
	//	if (TypeToTabIndex(mementoType)) {
 | 
						|
	//		switchToTab(std::move(*memento));
 | 
						|
	//		return true;
 | 
						|
	//	}
 | 
						|
 | 
						|
	}
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
// Allows showing additional shared media links and tabs.
 | 
						|
// Was done for top level tabs support.
 | 
						|
//
 | 
						|
//void InnerWidget::switchToTab(Memento &&memento) {
 | 
						|
//	// Save state of the tab before setSection() call.
 | 
						|
//	_controller->setSection(&memento);
 | 
						|
//	_list = setupList();
 | 
						|
//	restoreState(&memento);
 | 
						|
//	_list->show();
 | 
						|
//	_list->resizeToWidth(width());
 | 
						|
//	refreshHeight();
 | 
						|
//	if (_otherTypes) {
 | 
						|
//		_otherTabsShadow->raise();
 | 
						|
//		_otherTypes->raise();
 | 
						|
//		_otherTabs->setActiveSection(*TypeToTabIndex(type()));
 | 
						|
//	}
 | 
						|
//}
 | 
						|
//
 | 
						|
//void InnerWidget::refreshSearchField() {
 | 
						|
//	auto search = _controller->searchFieldController();
 | 
						|
//	if (search && _otherTabs && _searchEnabled) {
 | 
						|
//		_searchField = search->createRowView(
 | 
						|
//			this,
 | 
						|
//			st::infoMediaSearch);
 | 
						|
//		_searchField->resizeToWidth(width());
 | 
						|
//		_searchField->show();
 | 
						|
//		search->queryChanges(
 | 
						|
//		) | rpl::start_with_next([this] {
 | 
						|
//			scrollToSearchField();
 | 
						|
//		}, _searchField->lifetime());
 | 
						|
//	} else {
 | 
						|
//		_searchField = nullptr;
 | 
						|
//	}
 | 
						|
//}
 | 
						|
//
 | 
						|
//void InnerWidget::scrollToSearchField() {
 | 
						|
//	Expects(_searchField != nullptr);
 | 
						|
//
 | 
						|
//	auto top = _searchField->y();
 | 
						|
//	auto bottom = top + _searchField->height();
 | 
						|
//	_scrollToRequests.fire({ top, bottom });
 | 
						|
//}
 | 
						|
 | 
						|
object_ptr<ListWidget> InnerWidget::setupList() {
 | 
						|
	auto result = object_ptr<ListWidget>(
 | 
						|
		this,
 | 
						|
		_controller);
 | 
						|
	result->heightValue(
 | 
						|
	) | rpl::start_with_next(
 | 
						|
		[this] { refreshHeight(); },
 | 
						|
		result->lifetime());
 | 
						|
	using namespace rpl::mappers;
 | 
						|
	result->scrollToRequests(
 | 
						|
	) | rpl::map([widget = result.data()](int to) {
 | 
						|
		return Ui::ScrollToRequest {
 | 
						|
			widget->y() + to,
 | 
						|
			-1
 | 
						|
		};
 | 
						|
	}) | rpl::start_to_stream(
 | 
						|
		_scrollToRequests,
 | 
						|
		result->lifetime());
 | 
						|
	_selectedLists.fire(result->selectedListValue());
 | 
						|
	_listTops.fire(result->topValue());
 | 
						|
	_empty->setType(_controller->section().mediaType());
 | 
						|
	_controller->mediaSourceQueryValue(
 | 
						|
	) | rpl::start_with_next([this](const QString &query) {
 | 
						|
		_empty->setSearchQuery(query);
 | 
						|
	}, result->lifetime());
 | 
						|
	return result;
 | 
						|
}
 | 
						|
 | 
						|
void InnerWidget::saveState(not_null<Memento*> memento) {
 | 
						|
	_list->saveState(memento);
 | 
						|
}
 | 
						|
 | 
						|
void InnerWidget::restoreState(not_null<Memento*> memento) {
 | 
						|
	_list->restoreState(memento);
 | 
						|
}
 | 
						|
 | 
						|
rpl::producer<SelectedItems> InnerWidget::selectedListValue() const {
 | 
						|
	return _selectedLists.events_starting_with(
 | 
						|
		_list->selectedListValue()
 | 
						|
	) | rpl::flatten_latest();
 | 
						|
}
 | 
						|
 | 
						|
void InnerWidget::cancelSelection() {
 | 
						|
	_list->cancelSelection();
 | 
						|
}
 | 
						|
 | 
						|
InnerWidget::~InnerWidget() = default;
 | 
						|
 | 
						|
int InnerWidget::resizeGetHeight(int newWidth) {
 | 
						|
	_inResize = true;
 | 
						|
	auto guard = gsl::finally([this] { _inResize = false; });
 | 
						|
 | 
						|
	if (_otherTypes) {
 | 
						|
		_otherTypes->resizeToWidth(newWidth);
 | 
						|
		//_otherTabsShadow->resizeToWidth(newWidth);
 | 
						|
	}
 | 
						|
	//if (_searchField) {
 | 
						|
	//	_searchField->resizeToWidth(newWidth);
 | 
						|
	//}
 | 
						|
	_list->resizeToWidth(newWidth);
 | 
						|
	_empty->resizeToWidth(newWidth);
 | 
						|
	return recountHeight();
 | 
						|
}
 | 
						|
 | 
						|
void InnerWidget::refreshHeight() {
 | 
						|
	if (_inResize) {
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	resize(width(), recountHeight());
 | 
						|
}
 | 
						|
 | 
						|
int InnerWidget::recountHeight() {
 | 
						|
	auto top = 0;
 | 
						|
	if (_otherTypes) {
 | 
						|
		_otherTypes->moveToLeft(0, top);
 | 
						|
		top += _otherTypes->heightNoMargins() - st::lineWidth;
 | 
						|
//		_otherTabsShadow->moveToLeft(0, top);
 | 
						|
	}
 | 
						|
	//if (_searchField) {
 | 
						|
	//	_searchField->moveToLeft(0, top);
 | 
						|
	//	top += _searchField->heightNoMargins() - st::lineWidth;
 | 
						|
	//}
 | 
						|
	auto listHeight = 0;
 | 
						|
	if (_list) {
 | 
						|
		_list->moveToLeft(0, top);
 | 
						|
		listHeight = _list->heightNoMargins();
 | 
						|
		top += listHeight;
 | 
						|
	}
 | 
						|
	if (listHeight > 0) {
 | 
						|
		_empty->hide();
 | 
						|
	} else {
 | 
						|
		_empty->show();
 | 
						|
		_empty->moveToLeft(0, top);
 | 
						|
		top += _empty->heightNoMargins();
 | 
						|
	}
 | 
						|
	return top;
 | 
						|
}
 | 
						|
 | 
						|
void InnerWidget::setScrollHeightValue(rpl::producer<int> value) {
 | 
						|
	using namespace rpl::mappers;
 | 
						|
	_empty->setFullHeight(rpl::combine(
 | 
						|
		std::move(value),
 | 
						|
		_listTops.events_starting_with(
 | 
						|
			_list->topValue()
 | 
						|
		) | rpl::flatten_latest(),
 | 
						|
		_1 - _2));
 | 
						|
}
 | 
						|
 | 
						|
rpl::producer<Ui::ScrollToRequest> InnerWidget::scrollToRequests() const {
 | 
						|
	return _scrollToRequests.events();
 | 
						|
}
 | 
						|
 | 
						|
} // namespace Media
 | 
						|
} // namespace Info
 |