mirror of https://github.com/procxx/kepka.git
				
				
				
			Closed beta 10019013: Groups in common now are opened in a section.
This commit is contained in:
		
							parent
							
								
									47977009b8
								
							
						
					
					
						commit
						4692fdeb5f
					
				|  | @ -309,12 +309,6 @@ simpleCloseIcon: icon {{ "simple_close", #c7c7c7 }}; | |||
| simpleCloseIconOver: icon {{ "simple_close", #a3a3a3 }}; | ||||
| dialogsForwardCancelIcon: icon {{ "simple_close", dialogsForwardFg }}; | ||||
| 
 | ||||
| profileMaxWidth: 410px; | ||||
| profilePadding: margins(28px, 30px, 28px, 0px); | ||||
| 
 | ||||
| profileOnlineFg: statusFgActive; | ||||
| profileOfflineFg: statusFg; | ||||
| 
 | ||||
| membersPadding: margins(0px, 10px, 0px, 10px); | ||||
| 
 | ||||
| forwardMargins: margins(30px, 10px, 30px, 10px); | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 2.5 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 4.9 KiB | 
|  | @ -34,8 +34,8 @@ IDI_ICON1               ICON                    "..\\art\\icon256.ico" | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 0,10,19,12 | ||||
|  PRODUCTVERSION 0,10,19,12 | ||||
|  FILEVERSION 0,10,19,13 | ||||
|  PRODUCTVERSION 0,10,19,13 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -51,10 +51,10 @@ BEGIN | |||
|         BLOCK "040904b0" | ||||
|         BEGIN | ||||
|             VALUE "CompanyName", "Telegram Messenger LLP" | ||||
|             VALUE "FileVersion", "0.10.19.12" | ||||
|             VALUE "FileVersion", "0.10.19.13" | ||||
|             VALUE "LegalCopyright", "Copyright (C) 2014-2016" | ||||
|             VALUE "ProductName", "Telegram Desktop" | ||||
|             VALUE "ProductVersion", "0.10.19.12" | ||||
|             VALUE "ProductVersion", "0.10.19.13" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
|  | @ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 0,10,19,12 | ||||
|  PRODUCTVERSION 0,10,19,12 | ||||
|  FILEVERSION 0,10,19,13 | ||||
|  PRODUCTVERSION 0,10,19,13 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -43,10 +43,10 @@ BEGIN | |||
|         BEGIN | ||||
|             VALUE "CompanyName", "Telegram Messenger LLP" | ||||
|             VALUE "FileDescription", "Telegram Updater" | ||||
|             VALUE "FileVersion", "0.10.19.12" | ||||
|             VALUE "FileVersion", "0.10.19.13" | ||||
|             VALUE "LegalCopyright", "Copyright (C) 2014-2016" | ||||
|             VALUE "ProductName", "Telegram Desktop" | ||||
|             VALUE "ProductVersion", "0.10.19.12" | ||||
|             VALUE "ProductVersion", "0.10.19.13" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
|  | @ -2511,26 +2511,26 @@ namespace { | |||
| 			if (!fmt.isEmpty()) *format = fmt; | ||||
| 		} | ||||
| 		buffer.seek(0); | ||||
|         QString fmt = QString::fromUtf8(*format).toLower(); | ||||
| 		auto fmt = QString::fromUtf8(*format).toLower(); | ||||
| 		if (fmt == "jpg" || fmt == "jpeg") { | ||||
| #ifdef OS_MAC_OLD | ||||
| 			ExifData *exifData = exif_data_new_from_data((const uchar*)(data.constData()), data.size()); | ||||
| 			if (exifData) { | ||||
| 				ExifByteOrder byteOrder = exif_data_get_byte_order(exifData); | ||||
| 				ExifEntry *exifEntry = exif_data_get_entry(exifData, EXIF_TAG_ORIENTATION); | ||||
| 				if (exifEntry) { | ||||
| 					QTransform orientationFix; | ||||
| 					int orientation = exif_get_short(exifEntry->data, byteOrder); | ||||
| 					switch (orientation) { | ||||
| 					case 2: orientationFix = QTransform(-1, 0, 0, 1, 0, 0); break; | ||||
| 					case 3: orientationFix = QTransform(-1, 0, 0, -1, 0, 0); break; | ||||
| 					case 4: orientationFix = QTransform(1, 0, 0, -1, 0, 0); break; | ||||
| 					case 5: orientationFix = QTransform(0, -1, -1, 0, 0, 0); break; | ||||
| 					case 6: orientationFix = QTransform(0, 1, -1, 0, 0, 0); break; | ||||
| 					case 7: orientationFix = QTransform(0, 1, 1, 0, 0, 0); break; | ||||
| 					case 8: orientationFix = QTransform(0, -1, 1, 0, 0, 0); break; | ||||
| 					} | ||||
| 					result = result.transformed(orientationFix); | ||||
| 			if (auto exifData = exif_data_new_from_data((const uchar*)(data.constData()), data.size())) { | ||||
| 				auto byteOrder = exif_data_get_byte_order(exifData); | ||||
| 				if (auto exifEntry = exif_data_get_entry(exifData, EXIF_TAG_ORIENTATION)) { | ||||
| 					auto orientationFix = [exifEntry, byteOrder] { | ||||
| 						auto orientation = exif_get_short(exifEntry->data, byteOrder); | ||||
| 						switch (orientation) { | ||||
| 						case 2: return QTransform(-1, 0, 0, 1, 0, 0); | ||||
| 						case 3: return QTransform(-1, 0, 0, -1, 0, 0); | ||||
| 						case 4: return QTransform(1, 0, 0, -1, 0, 0); | ||||
| 						case 5: return QTransform(0, -1, -1, 0, 0, 0); | ||||
| 						case 6: return QTransform(0, 1, -1, 0, 0, 0); | ||||
| 						case 7: return QTransform(0, 1, 1, 0, 0, 0); | ||||
| 						case 8: return QTransform(0, -1, 1, 0, 0, 0); | ||||
| 						} | ||||
| 						return QTransform(); | ||||
| 					}; | ||||
| 					result = result.transformed(orientationFix()); | ||||
| 				} | ||||
| 				exif_data_free(exifData); | ||||
| 			} | ||||
|  | @ -2547,9 +2547,11 @@ namespace { | |||
| 			if (animated) *animated = false; | ||||
| 			return QImage(); | ||||
| 		} | ||||
| 		QByteArray img = f.readAll(); | ||||
| 		QImage result = readImage(img, format, opaque, animated); | ||||
| 		if (content && !result.isNull()) *content = img; | ||||
| 		auto imageBytes = f.readAll(); | ||||
| 		auto result = readImage(imageBytes, format, opaque, animated); | ||||
| 		if (content && !result.isNull()) { | ||||
| 			*content = imageBytes; | ||||
| 		} | ||||
| 		return result; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -391,23 +391,24 @@ inline const QRegularExpression &cRussianLetters() { | |||
| 	return regexp; | ||||
| } | ||||
| 
 | ||||
| inline QStringList cImgExtensions() { | ||||
| 	static QStringList imgExtensions; | ||||
| 	if (imgExtensions.isEmpty()) { | ||||
| 		imgExtensions.reserve(4); | ||||
| 		imgExtensions.push_back(qsl(".jpg")); | ||||
| 		imgExtensions.push_back(qsl(".jpeg")); | ||||
| 		imgExtensions.push_back(qsl(".png")); | ||||
| 		imgExtensions.push_back(qsl(".gif")); | ||||
| inline const QStringList &cImgExtensions() { | ||||
| 	static QStringList result; | ||||
| 	if (result.isEmpty()) { | ||||
| 		result.reserve(4); | ||||
| 		result.push_back(qsl(".jpg")); | ||||
| 		result.push_back(qsl(".jpeg")); | ||||
| 		result.push_back(qsl(".png")); | ||||
| 		result.push_back(qsl(".gif")); | ||||
| 	} | ||||
| 	return imgExtensions; | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| inline QStringList cPhotoExtensions() { | ||||
| 	static QStringList photoExtensions; | ||||
| 	if (photoExtensions.isEmpty()) { | ||||
| 		photoExtensions.push_back(qsl(".jpg")); | ||||
| 		photoExtensions.push_back(qsl(".jpeg")); | ||||
| inline const QStringList &cExtensionsForCompress() { | ||||
| 	static QStringList result; | ||||
| 	if (result.isEmpty()) { | ||||
| 		result.push_back(qsl(".jpg")); | ||||
| 		result.push_back(qsl(".jpeg")); | ||||
| 		result.push_back(qsl(".png")); | ||||
| 	} | ||||
| 	return photoExtensions; | ||||
| 	return result; | ||||
| } | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | |||
| 
 | ||||
| #include "core/utils.h" | ||||
| 
 | ||||
| #define BETA_VERSION_MACRO (10019012ULL) | ||||
| #define BETA_VERSION_MACRO (10019013ULL) | ||||
| 
 | ||||
| constexpr int AppVersion = 10020; | ||||
| constexpr str_const AppVersionStr = "0.10.20"; | ||||
|  |  | |||
|  | @ -67,9 +67,6 @@ historyToDownBadgeSize: 22px; | |||
| historyToDownShownAfter: 480px; | ||||
| historyToDownDuration: 150; | ||||
| 
 | ||||
| historyEmptyDog: icon {{ "history_empty_dog", #ffffff }}; | ||||
| historyEmptySize: 128px; | ||||
| 
 | ||||
| membersInnerWidth: 310px; | ||||
| membersInnerHeightMax: 360px; | ||||
| membersInnerDropdown: InnerDropdown(defaultInnerDropdown) { | ||||
|  |  | |||
|  | @ -335,14 +335,6 @@ QVector<int> ServiceMessagePainter::countLineWidths(const Text &text, const QRec | |||
| } | ||||
| 
 | ||||
| void paintEmpty(Painter &p, int width, int height) { | ||||
| 	auto position = QPoint((width - st::historyEmptySize) / 2, ((height - st::historyEmptySize) * 4) / 9); | ||||
| 	p.setPen(Qt::NoPen); | ||||
| 	p.setBrush(st::msgServiceBg); | ||||
| 	{ | ||||
| 		PainterHighQualityEnabler hq(p); | ||||
| 		p.drawEllipse(rtlrect(position.x(), position.y(), st::historyEmptySize, st::historyEmptySize, width)); | ||||
| 	} | ||||
| 	st::historyEmptyDog.paint(p, position.x() + (st::historyEmptySize - st::historyEmptyDog.width()) / 2, position.y() + (st::historyEmptySize - st::historyEmptyDog.height()) / 2, width); | ||||
| } | ||||
| 
 | ||||
| void serviceColorsUpdated() { | ||||
|  |  | |||
|  | @ -5551,9 +5551,7 @@ void HistoryWidget::step_recording(float64 ms, bool timer) { | |||
| void HistoryWidget::chooseAttach() { | ||||
| 	if (!_history) return; | ||||
| 
 | ||||
| 	auto photoExtensions = cPhotoExtensions(); | ||||
| 	auto imageExtensions = cImgExtensions(); | ||||
| 	auto filter = filedialogAllFilesFilter() + qsl(";;Image files (*") + imageExtensions.join(qsl(" *")) + qsl(");;Photo files (*") + photoExtensions.join(qsl(" *")) + qsl(")"); | ||||
| 	auto filter = filedialogAllFilesFilter() + qsl(";;Image files (*") + cImgExtensions().join(qsl(" *")) + qsl(")"); | ||||
| 
 | ||||
| 	_attachFilesQueryId = FileDialog::queryReadFiles(lang(lng_choose_files), filter); | ||||
| } | ||||
|  | @ -5578,7 +5576,7 @@ void HistoryWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update | |||
| 		} | ||||
| 	} else { | ||||
| 		auto lists = getSendingFilesLists(update.filePaths); | ||||
| 		if (lists.allFilesArePhotos) { | ||||
| 		if (lists.allFilesForCompress) { | ||||
| 			confirmSendingFiles(lists); | ||||
| 		} else { | ||||
| 			validateSendingFiles(lists, [this](const QStringList &files) { | ||||
|  | @ -6525,7 +6523,7 @@ bool HistoryWidget::confirmSendingFiles(const SendingFilesLists &lists, Compress | |||
| 		auto insertTextOnCancel = QString(); | ||||
| 		auto prepareBox = [this, &files, &lists, compressed, &image] { | ||||
| 			if (files.size() > 1) { | ||||
| 				return new SendFilesBox(files, lists.allFilesArePhotos ? compressed : CompressConfirm::None); | ||||
| 				return new SendFilesBox(files, lists.allFilesForCompress ? compressed : CompressConfirm::None); | ||||
| 			} | ||||
| 			auto filepath = files.front(); | ||||
| 			auto animated = false; | ||||
|  | @ -6610,8 +6608,8 @@ HistoryWidget::SendingFilesLists HistoryWidget::getSendingFilesLists(const QStri | |||
| } | ||||
| 
 | ||||
| void HistoryWidget::getSendingLocalFileInfo(SendingFilesLists &result, const QString &filepath) { | ||||
| 	auto hasPhotoExtension = [](const QString &filepath) { | ||||
| 		for_const (auto extension, cPhotoExtensions()) { | ||||
| 	auto hasExtensionForCompress = [](const QString &filepath) { | ||||
| 		for_const (auto extension, cExtensionsForCompress()) { | ||||
| 			if (filepath.right(extension.size()).compare(extension, Qt::CaseInsensitive) == 0) { | ||||
| 				return true; | ||||
| 			} | ||||
|  | @ -6629,9 +6627,9 @@ void HistoryWidget::getSendingLocalFileInfo(SendingFilesLists &result, const QSt | |||
| 			result.tooLargeFiles.push_back(filepath); | ||||
| 		} else { | ||||
| 			result.filesToSend.push_back(filepath); | ||||
| 			if (result.allFilesArePhotos) { | ||||
| 				if (filesize > App::kImageSizeLimit || !hasPhotoExtension(filepath)) { | ||||
| 					result.allFilesArePhotos = false; | ||||
| 			if (result.allFilesForCompress) { | ||||
| 				if (filesize > App::kImageSizeLimit || !hasExtensionForCompress(filepath)) { | ||||
| 					result.allFilesForCompress = false; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -858,7 +858,7 @@ private: | |||
| 		QStringList emptyFiles; | ||||
| 		QStringList tooLargeFiles; | ||||
| 		QStringList filesToSend; | ||||
| 		bool allFilesArePhotos = true; | ||||
| 		bool allFilesForCompress = true; | ||||
| 	}; | ||||
| 	SendingFilesLists getSendingFilesLists(const QList<QUrl> &files); | ||||
| 	SendingFilesLists getSendingFilesLists(const QStringList &files); | ||||
|  |  | |||
|  | @ -4546,15 +4546,14 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { | |||
| 	case mtpc_updateWebPage: { | ||||
| 		auto &d = update.c_updateWebPage(); | ||||
| 
 | ||||
| 		if (!ptsUpdated(d.vpts.v, d.vpts_count.v, update)) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		// update before applying skipped
 | ||||
| 		// update web page anyway
 | ||||
| 		App::feedWebPage(d.vwebpage); | ||||
| 		_history->updatePreview(); | ||||
| 		webPagesOrGamesUpdate(); | ||||
| 
 | ||||
| 		if (!ptsUpdated(d.vpts.v, d.vpts_count.v, update)) { | ||||
| 			return; | ||||
| 		} | ||||
| 		ptsApplySkippedUpdates(); | ||||
| 	} break; | ||||
| 
 | ||||
|  | @ -4893,8 +4892,13 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { | |||
| 
 | ||||
| 	case mtpc_updateChannelWebPage: { | ||||
| 		auto &d = update.c_updateChannelWebPage(); | ||||
| 		auto channel = App::channelLoaded(d.vchannel_id.v); | ||||
| 
 | ||||
| 		// update web page anyway
 | ||||
| 		App::feedWebPage(d.vwebpage); | ||||
| 		_history->updatePreview(); | ||||
| 		webPagesOrGamesUpdate(); | ||||
| 
 | ||||
| 		auto channel = App::channelLoaded(d.vchannel_id.v); | ||||
| 		if (channel && !_handlingChannelDifference) { | ||||
| 			if (channel->ptsRequesting()) { // skip global updates while getting channel difference
 | ||||
| 				return; | ||||
|  | @ -4903,12 +4907,6 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| 		// update before applying skipped
 | ||||
| 		App::feedWebPage(d.vwebpage); | ||||
| 		_history->updatePreview(); | ||||
| 		webPagesOrGamesUpdate(); | ||||
| 
 | ||||
| 		if (channel && !_handlingChannelDifference) { | ||||
| 			channel->ptsApplySkippedUpdates(); | ||||
| 		} | ||||
|  |  | |||
|  | @ -238,17 +238,8 @@ mediaPlayerListMarginBottom: 10px; | |||
| mediaPlayerScrollShadow: icon {{ "playlist_shadow", windowShadowFg }}; | ||||
| 
 | ||||
| mediaPlayerListMarginTop: 8px; | ||||
| mediaPlayerListIconFg: #ffffff; | ||||
| mediaPlayerFileLayout: OverviewFileLayout(overviewFileLayout) { | ||||
| 	maxWidth: 344px; | ||||
| 	songPadding: margins(17px, 7px, 10px, 6px); | ||||
| 	songThumbSize: 36px; | ||||
| 	songNameTop: 7px; | ||||
| 	songStatusTop: 25px; | ||||
| 	songIconBg: mediaPlayerActiveFg; | ||||
| 	songOverBg: mediaPlayerActiveFg; | ||||
| 	songPause: icon {{ "playlist_pause", mediaPlayerListIconFg }}; | ||||
| 	songPlay: icon {{ "playlist_play", mediaPlayerListIconFg }}; | ||||
| 	songCancel: icon {{ "playlist_cancel", mediaPlayerListIconFg }}; | ||||
| 	songDownload: icon {{ "playlist_download", mediaPlayerListIconFg }}; | ||||
| } | ||||
|  |  | |||
|  | @ -2827,7 +2827,7 @@ void ConnectionPrivate::clearAuthKeyData() { | |||
| 		if (!_authKeyStrings->dh_prime.isEmpty()) SecureZeroMemory(_authKeyStrings->dh_prime.data(), _authKeyStrings->dh_prime.size()); | ||||
| 		if (!_authKeyStrings->g_a.isEmpty()) SecureZeroMemory(_authKeyStrings->g_a.data(), _authKeyStrings->g_a.size()); | ||||
| #else | ||||
| 		memset(authKeyData, 0, sizeof(AuthKeyCreateData)); | ||||
| 		memset(_authKeyData.get(), 0, sizeof(AuthKeyCreateData)); | ||||
| 		if (!_authKeyStrings->dh_prime.isEmpty()) memset(_authKeyStrings->dh_prime.data(), 0, _authKeyStrings->dh_prime.size()); | ||||
| 		if (!_authKeyStrings->g_a.isEmpty()) memset(_authKeyStrings->g_a.data(), 0, _authKeyStrings->g_a.size()); | ||||
| #endif | ||||
|  |  | |||
|  | @ -32,9 +32,13 @@ OverviewFileLayout { | |||
| 	songIconBg: color; | ||||
| 	songOverBg: color; | ||||
| 	songPause: icon; | ||||
| 	songPauseSelected: icon; | ||||
| 	songPlay: icon; | ||||
| 	songPlaySelected: icon; | ||||
| 	songCancel: icon; | ||||
| 	songCancelSelected: icon; | ||||
| 	songDownload: icon; | ||||
| 	songDownloadSelected: icon; | ||||
| 
 | ||||
| 	filePadding: margins; | ||||
| 	fileThumbSize: pixels; | ||||
|  | @ -43,6 +47,9 @@ OverviewFileLayout { | |||
| 	fileDateTop: pixels; | ||||
| } | ||||
| 
 | ||||
| overviewLeftMin: 28px; | ||||
| overviewLeftMax: 42px; | ||||
| 
 | ||||
| overviewCheckBg: #00000040; | ||||
| overviewCheckFg: windowBg; | ||||
| overviewCheckFgActive: windowBg; | ||||
|  | @ -70,18 +77,30 @@ overviewFileExtTop: 24px; | |||
| overviewFileExtFg: #ffffff; | ||||
| overviewFileExtFont: font(18px semibold); | ||||
| 
 | ||||
| overviewSongPause: icon {{ "playlist_pause", msgInBg }}; | ||||
| overviewSongPauseSelected: icon {{ "playlist_pause", msgInBgSelected }}; | ||||
| overviewSongPlay: icon {{ "playlist_play", msgInBg }}; | ||||
| overviewSongPlaySelected: icon {{ "playlist_play", msgInBgSelected }}; | ||||
| overviewSongCancel: icon {{ "playlist_cancel", msgInBg }}; | ||||
| overviewSongCancelSelected: icon {{ "playlist_cancel", msgInBgSelected }}; | ||||
| overviewSongDownload: icon {{ "playlist_download", msgInBg }}; | ||||
| overviewSongDownloadSelected: icon {{ "playlist_download", msgInBgSelected }}; | ||||
| overviewFileLayout: OverviewFileLayout { | ||||
| 	maxWidth: 410px; | ||||
| 	songPadding: msgFilePadding; | ||||
| 	songThumbSize: msgFileSize; | ||||
| 	songNameTop: msgFileNameTop; | ||||
| 	songStatusTop: msgFileStatusTop; | ||||
| 	maxWidth: 520px; | ||||
| 	songPadding: margins(17px, 7px, 10px, 6px); | ||||
| 	songThumbSize: 36px; | ||||
| 	songNameTop: 7px; | ||||
| 	songStatusTop: 25px; | ||||
| 	songIconBg: msgFileInBg; | ||||
| 	songOverBg: msgFileInBgOver; | ||||
| 	songPause: historyFileInPause; | ||||
| 	songPlay: historyFileInPlay; | ||||
| 	songCancel: historyFileInCancel; | ||||
| 	songDownload: historyFileInDownload; | ||||
| 	songPause: overviewSongPause; | ||||
| 	songPauseSelected: overviewSongPauseSelected; | ||||
| 	songPlay: overviewSongPlay; | ||||
| 	songPlaySelected: overviewSongPlaySelected; | ||||
| 	songCancel: overviewSongCancel; | ||||
| 	songCancelSelected: overviewSongCancelSelected; | ||||
| 	songDownload: overviewSongDownload; | ||||
| 	songDownloadSelected: overviewSongDownloadSelected; | ||||
| 
 | ||||
| 	filePadding: margins(0px, 3px, 16px, 3px); | ||||
| 	fileThumbSize: 70px; | ||||
|  | @ -97,7 +116,7 @@ overviewLoaderSkip: 4px; | |||
| playlistHoverBg: windowBgOver; | ||||
| playlistPadding: 10px; | ||||
| 
 | ||||
| linksSearchMargin: margins(20px, 20px, 20px, 0px); | ||||
| linksSearchTop: 30px; | ||||
| linksMaxWidth: 520px; | ||||
| linksLetterFg: #ffffff; | ||||
| linksLetterFont: font(24px); | ||||
|  |  | |||
|  | @ -466,9 +466,10 @@ void Video::updateStatusText() { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| Voice::Voice(DocumentData *voice, HistoryItem *parent) : RadialProgressItem(parent) | ||||
| Voice::Voice(DocumentData *voice, HistoryItem *parent, const style::OverviewFileLayout &st) : RadialProgressItem(parent) | ||||
| , _data(voice) | ||||
| , _namel(new DocumentOpenClickHandler(_data)) { | ||||
| , _namel(new DocumentOpenClickHandler(_data)) | ||||
| , _st(st) { | ||||
| 	AddComponents(Info::Bit()); | ||||
| 
 | ||||
| 	t_assert(_data->voice() != 0); | ||||
|  | @ -483,8 +484,8 @@ Voice::Voice(DocumentData *voice, HistoryItem *parent) : RadialProgressItem(pare | |||
| } | ||||
| 
 | ||||
| void Voice::initDimensions() { | ||||
| 	_maxw = st::overviewFileLayout.maxWidth; | ||||
| 	_minh = st::overviewFileLayout.songPadding.top() + st::overviewFileLayout.songThumbSize + st::overviewFileLayout.songPadding.bottom() + st::lineWidth; | ||||
| 	_maxw = _st.maxWidth; | ||||
| 	_minh = _st.songPadding.top() + _st.songThumbSize + _st.songPadding.bottom() + st::lineWidth; | ||||
| } | ||||
| 
 | ||||
| void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) { | ||||
|  | @ -508,16 +509,16 @@ void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const | |||
| 
 | ||||
| 	int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = -1; | ||||
| 
 | ||||
| 	nameleft = st::overviewFileLayout.songPadding.left() + st::overviewFileLayout.songThumbSize + st::overviewFileLayout.songPadding.right(); | ||||
| 	nameright = st::overviewFileLayout.songPadding.left(); | ||||
| 	nametop = st::overviewFileLayout.songNameTop; | ||||
| 	statustop = st::overviewFileLayout.songStatusTop; | ||||
| 	nameleft = _st.songPadding.left() + _st.songThumbSize + _st.songPadding.right(); | ||||
| 	nameright = _st.songPadding.left(); | ||||
| 	nametop = _st.songNameTop; | ||||
| 	statustop = _st.songStatusTop; | ||||
| 
 | ||||
| 	if (selected) { | ||||
| 		p.fillRect(clip.intersected(QRect(0, 0, _width, _height)), st::msgInBgSelected); | ||||
| 	} | ||||
| 
 | ||||
| 	QRect inner(rtlrect(st::overviewFileLayout.songPadding.left(), st::overviewFileLayout.songPadding.top(), st::overviewFileLayout.songThumbSize, st::overviewFileLayout.songThumbSize, _width)); | ||||
| 	QRect inner(rtlrect(_st.songPadding.left(), _st.songPadding.top(), _st.songThumbSize, _st.songThumbSize, _width)); | ||||
| 	if (clip.intersects(inner)) { | ||||
| 		p.setPen(Qt::NoPen); | ||||
| 		if (selected) { | ||||
|  | @ -540,13 +541,13 @@ void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const | |||
| 
 | ||||
| 		auto icon = ([showPause, this, selected] { | ||||
| 			if (showPause) { | ||||
| 				return &(selected ? st::historyFileInPauseSelected : st::historyFileInPause); | ||||
| 				return &(selected ? _st.songPauseSelected : _st.songPause); | ||||
| 			} else if (_status.size() < 0 || _status.size() == FileStatusSizeLoaded) { | ||||
| 				return &(selected ? st::historyFileInPlaySelected : st::historyFileInPlay); | ||||
| 				return &(selected ? _st.songPlaySelected : _st.songPlay); | ||||
| 			} else if (_data->loading()) { | ||||
| 				return &(selected ? st::historyFileInCancelSelected : st::historyFileInCancel); | ||||
| 				return &(selected ? _st.songCancelSelected : _st.songCancel); | ||||
| 			} | ||||
| 			return &(selected ? st::historyFileInDownloadSelected : st::historyFileInDownload); | ||||
| 			return &(selected ? _st.songDownloadSelected : _st.songDownload); | ||||
| 		})(); | ||||
| 		icon->paintInCenter(p, inner); | ||||
| 	} | ||||
|  | @ -589,12 +590,12 @@ void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i | |||
| 
 | ||||
| 	int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0; | ||||
| 
 | ||||
| 	nameleft = st::overviewFileLayout.songPadding.left() + st::overviewFileLayout.songThumbSize + st::overviewFileLayout.songPadding.right(); | ||||
| 	nameright = st::overviewFileLayout.songPadding.left(); | ||||
| 	nametop = st::overviewFileLayout.songNameTop; | ||||
| 	statustop = st::overviewFileLayout.songStatusTop; | ||||
| 	nameleft = _st.songPadding.left() + _st.songThumbSize + _st.songPadding.right(); | ||||
| 	nameright = _st.songPadding.left(); | ||||
| 	nametop = _st.songNameTop; | ||||
| 	statustop = _st.songStatusTop; | ||||
| 
 | ||||
| 	auto inner = rtlrect(st::overviewFileLayout.songPadding.left(), st::overviewFileLayout.songPadding.top(), st::overviewFileLayout.songThumbSize, st::overviewFileLayout.songThumbSize, _width); | ||||
| 	auto inner = rtlrect(_st.songPadding.left(), _st.songPadding.top(), _st.songThumbSize, _st.songThumbSize, _width); | ||||
| 	if (inner.contains(x, y)) { | ||||
| 		link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _openl); | ||||
| 		return; | ||||
|  | @ -747,13 +748,13 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con | |||
| 
 | ||||
| 			auto icon = ([showPause, loaded, this, selected] { | ||||
| 				if (showPause) { | ||||
| 					return &(selected ? st::historyFileInPauseSelected : _st.songPause); | ||||
| 					return &(selected ? _st.songPauseSelected : _st.songPause); | ||||
| 				} else if (loaded) { | ||||
| 					return &(selected ? st::historyFileInPlaySelected : _st.songPlay); | ||||
| 					return &(selected ? _st.songPlaySelected : _st.songPlay); | ||||
| 				} else if (_data->loading()) { | ||||
| 					return &(selected ? st::historyFileInCancelSelected : _st.songCancel); | ||||
| 					return &(selected ? _st.songCancelSelected : _st.songCancel); | ||||
| 				} | ||||
| 				return &(selected ? st::historyFileInDownloadSelected : _st.songDownload); | ||||
| 				return &(selected ? _st.songDownloadSelected : _st.songDownload); | ||||
| 			})(); | ||||
| 			icon->paintInCenter(p, inner); | ||||
| 		} | ||||
|  |  | |||
|  | @ -244,7 +244,7 @@ private: | |||
| 
 | ||||
| class Voice : public RadialProgressItem { | ||||
| public: | ||||
| 	Voice(DocumentData *voice, HistoryItem *parent); | ||||
| 	Voice(DocumentData *voice, HistoryItem *parent, const style::OverviewFileLayout &st); | ||||
| 
 | ||||
| 	void initDimensions() override; | ||||
| 	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; | ||||
|  | @ -269,6 +269,8 @@ private: | |||
| 	StatusText _status; | ||||
| 	ClickHandlerPtr _namel; | ||||
| 
 | ||||
| 	const style::OverviewFileLayout &_st; | ||||
| 
 | ||||
| 	Text _name, _details; | ||||
| 	int _nameVersion; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1276,14 +1276,21 @@ int32 OverviewInner::resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeigh | |||
| 	if (_type == OverviewPhotos || _type == OverviewVideos) { | ||||
| 		_photosInRow = int32(_width - st::overviewPhotoSkip) / int32(st::overviewPhotoMinSize + st::overviewPhotoSkip); | ||||
| 		_rowWidth = (int32(_width - st::overviewPhotoSkip) / _photosInRow) - st::overviewPhotoSkip; | ||||
| 	} else if (_type == OverviewLinks) { | ||||
| 		_rowWidth = qMin(_width - st::linksSearchMargin.left() - st::linksSearchMargin.right(), int32(st::linksMaxWidth)); | ||||
| 		_rowsLeft = st::overviewPhotoSkip; | ||||
| 	} else { | ||||
| 		_rowWidth = qMin(_width - st::profilePadding.left() - st::profilePadding.right(), st::overviewFileLayout.maxWidth); | ||||
| 		auto contentLeftMin = st::overviewLeftMin; | ||||
| 		auto contentLeftMax = st::overviewLeftMax; | ||||
| 		if (_type == OverviewMusicFiles || _type == OverviewVoiceFiles) { | ||||
| 			contentLeftMin -= st::overviewFileLayout.songPadding.left(); | ||||
| 			contentLeftMax -= st::overviewFileLayout.songPadding.left(); | ||||
| 		} | ||||
| 		auto widthWithMin = st::windowMinWidth; | ||||
| 		auto widthWithMax = st::overviewFileLayout.maxWidth + 2 * contentLeftMax; | ||||
| 		_rowsLeft = anim::interpolate(contentLeftMax, contentLeftMin, qMax(widthWithMax - _width, 0) / float64(widthWithMax - widthWithMin)); | ||||
| 		_rowWidth = qMin(_width - 2 * _rowsLeft, st::overviewFileLayout.maxWidth); | ||||
| 	} | ||||
| 	_rowsLeft = (_width - _rowWidth) / 2; | ||||
| 
 | ||||
| 	_search->setGeometry(_rowsLeft, st::linksSearchMargin.top(), _rowWidth, _search->height()); | ||||
| 	_search->setGeometry(_rowsLeft, st::linksSearchTop, _rowWidth, _search->height()); | ||||
| 	_cancelSearch->moveToLeft(_rowsLeft + _rowWidth - _cancelSearch->width(), _search->y()); | ||||
| 
 | ||||
| 	if (_type == OverviewPhotos || _type == OverviewVideos) { | ||||
|  | @ -1797,7 +1804,7 @@ void OverviewInner::recountMargins() { | |||
| 		_marginTop = st::playlistPadding; | ||||
| 		_marginBottom = qMax(_minHeight - _height - _marginTop, int32(st::playlistPadding)); | ||||
| 	} else if (_type == OverviewLinks || _type == OverviewFiles) { | ||||
| 		_marginTop = st::linksSearchMargin.top() + _search->height() + st::linksSearchMargin.bottom(); | ||||
| 		_marginTop = st::linksSearchTop + _search->height(); | ||||
| 		_marginBottom = qMax(_minHeight - _height - _marginTop, int32(st::playlistPadding)); | ||||
| 	} else { | ||||
| 		_marginBottom = st::playlistPadding; | ||||
|  | @ -1827,7 +1834,7 @@ Overview::Layout::ItemBase *OverviewInner::layoutPrepare(HistoryItem *item) { | |||
| 	} else if (_type == OverviewVoiceFiles) { | ||||
| 		if (media && (media->type() == MediaTypeVoiceFile)) { | ||||
| 			if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) { | ||||
| 				i = _layoutItems.insert(item, new Overview::Layout::Voice(media->getDocument(), item)); | ||||
| 				i = _layoutItems.insert(item, new Overview::Layout::Voice(media->getDocument(), item, st::overviewFileLayout)); | ||||
| 				i.value()->initDimensions(); | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -144,3 +144,14 @@ profileVerifiedCheck: icon { | |||
| 	{ "profile_verified_star", windowBgActive, point(0px, 7px) }, | ||||
| 	{ "profile_verified_check", windowFgActive, point(4px, 11px) } | ||||
| }; | ||||
| 
 | ||||
| profileCommonGroupsSkip: 24px; | ||||
| profileCommonGroupsLeftMin: 24px; | ||||
| profileCommonGroupsLeftMax: 36px; | ||||
| profileCommonGroupsWidthMax: 480px; | ||||
| profileCommonGroupsPadding: margins(7px, 7px, 7px, 7px); | ||||
| profileCommonGroupsPhotoSize: 42px; | ||||
| profileCommonGroupsNameTop: 12px; | ||||
| profileCommonGroupsNameLeft: 16px; | ||||
| profileCommonGroupsBgOver: windowBgOver; | ||||
| profileCommonGroupsRipple: defaultRippleAnimation; | ||||
|  |  | |||
|  | @ -0,0 +1,72 @@ | |||
| /*
 | ||||
| This file is part of Telegram Desktop, | ||||
| the official desktop version of Telegram messaging app, see https://telegram.org
 | ||||
| 
 | ||||
| Telegram Desktop is free software: you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation, either version 3 of the License, or | ||||
| (at your option) any later version. | ||||
| 
 | ||||
| It is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| GNU General Public License for more details. | ||||
| 
 | ||||
| In addition, as a special exception, the copyright holders give permission | ||||
| to link the code of portions of this program with the OpenSSL library. | ||||
| 
 | ||||
| Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | ||||
| Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 | ||||
| */ | ||||
| #include "stdafx.h" | ||||
| #include "profile/profile_back_button.h" | ||||
| 
 | ||||
| #include "window/top_bar_widget.h" | ||||
| #include "styles/style_widgets.h" | ||||
| #include "styles/style_window.h" | ||||
| #include "styles/style_profile.h" | ||||
| 
 | ||||
| namespace Profile { | ||||
| 
 | ||||
| BackButton::BackButton(QWidget *parent, const QString &text) : Ui::AbstractButton(parent) | ||||
| , _text(text.toUpper()) { | ||||
| 	setCursor(style::cur_pointer); | ||||
| 
 | ||||
| 	subscribe(Adaptive::Changed(), [this] { updateAdaptiveLayout(); }); | ||||
| 	updateAdaptiveLayout(); | ||||
| } | ||||
| 
 | ||||
| int BackButton::resizeGetHeight(int newWidth) { | ||||
| 	return st::profileTopBarHeight; | ||||
| } | ||||
| 
 | ||||
| void BackButton::paintEvent(QPaintEvent *e) { | ||||
| 	Painter p(this); | ||||
| 
 | ||||
| 	p.fillRect(e->rect(), st::profileBg); | ||||
| 	st::topBarBack.paint(p, (st::topBarArrowPadding.left() - st::topBarBack.width()) / 2, (st::topBarHeight - st::topBarBack.height()) / 2, width()); | ||||
| 
 | ||||
| 	p.setFont(st::topBarButton.font); | ||||
| 	p.setPen(st::topBarButton.textFg); | ||||
| 	p.drawTextLeft(st::topBarArrowPadding.left(), st::topBarButton.padding.top() + st::topBarButton.textTop, width(), _text); | ||||
| 
 | ||||
| 	Window::TopBarWidget::paintUnreadCounter(p, width()); | ||||
| } | ||||
| 
 | ||||
| void BackButton::onStateChanged(State was, StateChangeSource source) { | ||||
| 	if (isDown() && !(was & StateFlag::Down)) { | ||||
| 		emit clicked(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void BackButton::updateAdaptiveLayout() { | ||||
| 	if (!Adaptive::OneColumn()) { | ||||
| 		unsubscribe(base::take(_unreadCounterSubscription)); | ||||
| 	} else if (!_unreadCounterSubscription) { | ||||
| 		_unreadCounterSubscription = subscribe(Global::RefUnreadCounterUpdate(), [this] { | ||||
| 			rtlupdate(0, 0, st::titleUnreadCounterRight, st::titleUnreadCounterTop); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| } // namespace Profile
 | ||||
|  | @ -0,0 +1,45 @@ | |||
| /*
 | ||||
| This file is part of Telegram Desktop, | ||||
| the official desktop version of Telegram messaging app, see https://telegram.org
 | ||||
| 
 | ||||
| Telegram Desktop is free software: you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation, either version 3 of the License, or | ||||
| (at your option) any later version. | ||||
| 
 | ||||
| It is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| GNU General Public License for more details. | ||||
| 
 | ||||
| In addition, as a special exception, the copyright holders give permission | ||||
| to link the code of portions of this program with the OpenSSL library. | ||||
| 
 | ||||
| Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | ||||
| Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 | ||||
| */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "ui/abstract_button.h" | ||||
| 
 | ||||
| namespace Profile { | ||||
| 
 | ||||
| class BackButton final : public Ui::AbstractButton, private base::Subscriber { | ||||
| public: | ||||
| 	BackButton(QWidget *parent, const QString &text); | ||||
| 
 | ||||
| protected: | ||||
| 	void paintEvent(QPaintEvent *e) override; | ||||
| 
 | ||||
| 	int resizeGetHeight(int newWidth) override; | ||||
| 	void onStateChanged(State was, StateChangeSource source) override; | ||||
| 
 | ||||
| private: | ||||
| 	void updateAdaptiveLayout(); | ||||
| 
 | ||||
| 	int _unreadCounterSubscription = 0; | ||||
| 	QString _text; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| } // namespace Profile
 | ||||
|  | @ -1,175 +0,0 @@ | |||
| /*
 | ||||
| This file is part of Telegram Desktop, | ||||
| the official desktop version of Telegram messaging app, see https://telegram.org
 | ||||
| 
 | ||||
| Telegram Desktop is free software: you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation, either version 3 of the License, or | ||||
| (at your option) any later version. | ||||
| 
 | ||||
| It is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| GNU General Public License for more details. | ||||
| 
 | ||||
| In addition, as a special exception, the copyright holders give permission | ||||
| to link the code of portions of this program with the OpenSSL library. | ||||
| 
 | ||||
| Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | ||||
| Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 | ||||
| */ | ||||
| #include "stdafx.h" | ||||
| #include "profile/profile_block_common_groups.h" | ||||
| 
 | ||||
| #include "profile/profile_section_memento.h" | ||||
| #include "styles/style_widgets.h" | ||||
| #include "observer_peer.h" | ||||
| #include "apiwrap.h" | ||||
| #include "lang.h" | ||||
| 
 | ||||
| namespace Profile { | ||||
| namespace { | ||||
| 
 | ||||
| constexpr int kCommonGroupsPerPage = 20; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| CommonGroupsWidget::CommonGroupsWidget(QWidget *parent, PeerData *peer) | ||||
| : PeerListWidget(parent, peer, lang(lng_profile_common_groups_section)) { | ||||
| 	refreshVisibility(); | ||||
| 
 | ||||
| 	auto observeEvents = Notify::PeerUpdate::Flag::MembersChanged; | ||||
| 	subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) { | ||||
| 		notifyPeerUpdated(update); | ||||
| 	})); | ||||
| 
 | ||||
| 	setSelectedCallback([this](PeerData *selectedPeer) { | ||||
| 		Ui::showPeerHistory(selectedPeer, ShowAtUnreadMsgId, Ui::ShowWay::Forward); | ||||
| 	}); | ||||
| 	setPreloadMoreCallback([this] { | ||||
| 		preloadMore(); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| void CommonGroupsWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { | ||||
| 	for_const (auto item, items()) { | ||||
| 		if (item->peer == update.peer) { | ||||
| 			updateStatusText(item); | ||||
| 			this->update(); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int CommonGroupsWidget::resizeGetHeight(int newWidth) { | ||||
| 	auto result = PeerListWidget::resizeGetHeight(newWidth); | ||||
| 	return qRound(_height.current(result)); | ||||
| } | ||||
| 
 | ||||
| void CommonGroupsWidget::paintContents(Painter &p) { | ||||
| 	_height.animating(getms()); | ||||
| 	return PeerListWidget::paintContents(p); | ||||
| } | ||||
| 
 | ||||
| void CommonGroupsWidget::saveState(SectionMemento *memento) const { | ||||
| 	if (auto count = itemsCount()) { | ||||
| 		QList<PeerData*> groups; | ||||
| 		groups.reserve(count); | ||||
| 		for_const (auto item, items()) { | ||||
| 			groups.push_back(item->peer); | ||||
| 		} | ||||
| 		memento->setCommonGroups(groups); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void CommonGroupsWidget::restoreState(const SectionMemento *memento) { | ||||
| 	CommonGroupsEvent event; | ||||
| 	event.groups = memento->getCommonGroups(); | ||||
| 	if (!event.groups.empty()) { | ||||
| 		onShowCommonGroups(event); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void CommonGroupsWidget::onShowCommonGroups(const CommonGroupsEvent &event) { | ||||
| 	for_const (auto group, event.groups) { | ||||
| 		addItem(computeItem(group)); | ||||
| 		_preloadGroupId = group->bareId(); | ||||
| 	} | ||||
| 	refreshVisibility(); | ||||
| 	if (event.initialHeight >= 0) { | ||||
| 		_height.start([this] { contentSizeUpdated(); }, event.initialHeight, resizeGetHeight(width()), st::widgetSlideDuration); | ||||
| 	} | ||||
| 	contentSizeUpdated(); | ||||
| 	update(); | ||||
| } | ||||
| 
 | ||||
| void CommonGroupsWidget::preloadMore() { | ||||
| 	if (_preloadRequestId || !_preloadGroupId) { | ||||
| 		return; | ||||
| 	} | ||||
| 	auto user = peer()->asUser(); | ||||
| 	t_assert(user != nullptr); | ||||
| 	auto request = MTPmessages_GetCommonChats(user->inputUser, MTP_int(_preloadGroupId), MTP_int(kCommonGroupsPerPage)); | ||||
| 	_preloadRequestId = MTP::send(request, ::rpcDone(base::lambda_guarded(this, [this](const MTPmessages_Chats &result) { | ||||
| 		_preloadRequestId = 0; | ||||
| 		_preloadGroupId = 0; | ||||
| 
 | ||||
| 		if (auto chats = Api::getChatsFromMessagesChats(result)) { | ||||
| 			auto &list = chats->c_vector().v; | ||||
| 			if (!list.empty()) { | ||||
| 				reserveItemsForSize(itemsCount() + list.size()); | ||||
| 				for_const (auto &chatData, list) { | ||||
| 					if (auto chat = App::feedChat(chatData)) { | ||||
| 						addItem(computeItem(chat)); | ||||
| 						_preloadGroupId = chat->bareId(); | ||||
| 					} | ||||
| 				} | ||||
| 				contentSizeUpdated(); | ||||
| 			} | ||||
| 		} | ||||
| 	}))); | ||||
| } | ||||
| 
 | ||||
| void CommonGroupsWidget::updateStatusText(Item *item) { | ||||
| 	auto group = item->peer; | ||||
| 	if (auto chat = group->asChat()) { | ||||
| 		auto count = qMax(chat->count, chat->participants.size()); | ||||
| 		item->statusText = count ? lng_chat_status_members(lt_count, count) : lang(lng_group_status); | ||||
| 	} else if (auto megagroup = group->asMegagroup()) { | ||||
| 		auto count = megagroup->membersCount(); | ||||
| 		item->statusText = (count > 0) ? lng_chat_status_members(lt_count, count) : lang(lng_group_status); | ||||
| 
 | ||||
| 		// Request members count.
 | ||||
| 		if (!megagroup->wasFullUpdated()) App::api()->requestFullPeer(megagroup); | ||||
| 	} else if (auto channel = group->asChannel()) { | ||||
| 		auto count = channel->membersCount(); | ||||
| 		item->statusText = (count > 0) ? lng_chat_status_members(lt_count, count) : lang(lng_channel_status); | ||||
| 
 | ||||
| 		// Request members count.
 | ||||
| 		if (!channel->wasFullUpdated()) App::api()->requestFullPeer(channel); | ||||
| 	} else { | ||||
| 		t_assert(!"Users should not get to CommonGroupsWidget::updateStatusText()"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| CommonGroupsWidget::Item *CommonGroupsWidget::computeItem(PeerData *group) { | ||||
| 	// Skip groups that migrated to supergroups.
 | ||||
| 	if (group->migrateTo()) { | ||||
| 		return nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	auto it = _dataMap.constFind(group); | ||||
| 	if (it == _dataMap.cend()) { | ||||
| 		it = _dataMap.insert(group, new Item(group)); | ||||
| 		updateStatusText(it.value()); | ||||
| 	} | ||||
| 	return it.value(); | ||||
| } | ||||
| 
 | ||||
| CommonGroupsWidget::~CommonGroupsWidget() { | ||||
| 	for (auto item : base::take(_dataMap)) { | ||||
| 		delete item; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| } // namespace Profile
 | ||||
|  | @ -1,75 +0,0 @@ | |||
| /*
 | ||||
| This file is part of Telegram Desktop, | ||||
| the official desktop version of Telegram messaging app, see https://telegram.org
 | ||||
| 
 | ||||
| Telegram Desktop is free software: you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation, either version 3 of the License, or | ||||
| (at your option) any later version. | ||||
| 
 | ||||
| It is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| GNU General Public License for more details. | ||||
| 
 | ||||
| In addition, as a special exception, the copyright holders give permission | ||||
| to link the code of portions of this program with the OpenSSL library. | ||||
| 
 | ||||
| Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | ||||
| Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 | ||||
| */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "profile/profile_block_peer_list.h" | ||||
| 
 | ||||
| namespace Notify { | ||||
| struct PeerUpdate; | ||||
| } // namespace Notify
 | ||||
| 
 | ||||
| namespace Profile { | ||||
| 
 | ||||
| struct CommonGroupsEvent { | ||||
| 	QList<PeerData*> groups; | ||||
| 
 | ||||
| 	// If initialHeight >= 0 the common groups widget will
 | ||||
| 	// slide down starting from height() == initialHeight.
 | ||||
| 	// Otherwise it will just show instantly.
 | ||||
| 	int initialHeight = -1; | ||||
| }; | ||||
| 
 | ||||
| class CommonGroupsWidget : public PeerListWidget { | ||||
| public: | ||||
| 	CommonGroupsWidget(QWidget *parent, PeerData *peer); | ||||
| 
 | ||||
| 	void setShowCommonGroupsObservable(base::Observable<CommonGroupsEvent> *observable) { | ||||
| 		subscribe(observable, [this](const CommonGroupsEvent &event) { onShowCommonGroups(event); }); | ||||
| 	} | ||||
| 
 | ||||
| 	void saveState(SectionMemento *memento) const override; | ||||
| 	void restoreState(const SectionMemento *memento) override; | ||||
| 
 | ||||
| 	~CommonGroupsWidget(); | ||||
| 
 | ||||
| protected: | ||||
| 	int resizeGetHeight(int newWidth) override; | ||||
| 	void paintContents(Painter &p) override; | ||||
| 
 | ||||
| private: | ||||
| 	// Observed notifications.
 | ||||
| 	void notifyPeerUpdated(const Notify::PeerUpdate &update); | ||||
| 
 | ||||
| 	void updateStatusText(Item *item); | ||||
| 	void onShowCommonGroups(const CommonGroupsEvent &event); | ||||
| 	void preloadMore(); | ||||
| 
 | ||||
| 	Item *computeItem(PeerData *group); | ||||
| 	QMap<PeerData*, Item*> _dataMap; | ||||
| 
 | ||||
| 	Animation _height; | ||||
| 
 | ||||
| 	int32 _preloadGroupId = 0; | ||||
| 	mtpRequestId _preloadRequestId = 0; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| } // namespace Profile
 | ||||
|  | @ -21,13 +21,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | |||
| #include "stdafx.h" | ||||
| #include "profile/profile_block_info.h" | ||||
| 
 | ||||
| #include "profile/profile_block_common_groups.h" | ||||
| #include "profile/profile_common_groups_section.h" | ||||
| #include "profile/profile_section_memento.h" | ||||
| #include "styles/style_profile.h" | ||||
| #include "ui/widgets/labels.h" | ||||
| #include "ui/widgets/buttons.h" | ||||
| #include "ui/effects/widget_slide_wrap.h" | ||||
| #include "core/click_handler_types.h" | ||||
| #include "mainwidget.h" | ||||
| #include "observer_peer.h" | ||||
| #include "apiwrap.h" | ||||
| #include "lang.h" | ||||
|  | @ -69,12 +70,6 @@ void InfoWidget::slideCommonGroupsDown() { | |||
| 	contentSizeUpdated(); | ||||
| } | ||||
| 
 | ||||
| void InfoWidget::restoreState(const SectionMemento *memento) { | ||||
| 	if (!memento->getCommonGroups().isEmpty()) { | ||||
| 		onForceHideCommonGroups(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void InfoWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { | ||||
| 	if (update.peer != peer()) { | ||||
| 		return; | ||||
|  | @ -253,7 +248,7 @@ int InfoWidget::getCommonGroupsCount() const { | |||
| } | ||||
| 
 | ||||
| void InfoWidget::refreshCommonGroups() { | ||||
| 	if (auto count = (_forceHiddenCommonGroups ? 0 : getCommonGroupsCount())) { | ||||
| 	if (auto count = getCommonGroupsCount()) { | ||||
| 		auto text = lng_profile_common_groups(lt_count, count); | ||||
| 		if (_commonGroups) { | ||||
| 			_commonGroups->setText(text); | ||||
|  | @ -270,56 +265,15 @@ void InfoWidget::refreshCommonGroups() { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void InfoWidget::setShowCommonGroupsObservable(base::Observable<CommonGroupsEvent> *observable) { | ||||
| 	_showCommonGroupsObservable = observable; | ||||
| 	subscribe(_showCommonGroupsObservable, [this](const CommonGroupsEvent &event) { | ||||
| 		onForceHideCommonGroups(); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| void InfoWidget::onForceHideCommonGroups() { | ||||
| 	if (_forceHiddenCommonGroups) { | ||||
| 		return; | ||||
| 	} | ||||
| 	_forceHiddenCommonGroups = true; | ||||
| 	_commonGroups.destroyDelayed(); | ||||
| 	refreshVisibility(); | ||||
| 	contentSizeUpdated(); | ||||
| } | ||||
| 
 | ||||
| void InfoWidget::onShowCommonGroups() { | ||||
| 	auto count = getCommonGroupsCount(); | ||||
| 	if (count <= 0) { | ||||
| 		refreshCommonGroups(); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (_getCommonGroupsRequestId) { | ||||
| 		return; | ||||
| 	if (auto main = App::main()) { | ||||
| 		main->showWideSection(Profile::CommonGroups::SectionMemento(peer())); | ||||
| 	} | ||||
| 	auto user = peer()->asUser(); | ||||
| 	t_assert(user != nullptr); | ||||
| 	auto request = MTPmessages_GetCommonChats(user->inputUser, MTP_int(0), MTP_int(kCommonGroupsLimit)); | ||||
| 	_getCommonGroupsRequestId = MTP::send(request, ::rpcDone(base::lambda_guarded(this, [this](const MTPmessages_Chats &result) { | ||||
| 		_getCommonGroupsRequestId = 0; | ||||
| 
 | ||||
| 		CommonGroupsEvent event; | ||||
| 		if (auto chats = Api::getChatsFromMessagesChats(result)) { | ||||
| 			auto &list = chats->c_vector().v; | ||||
| 			event.groups.reserve(list.size()); | ||||
| 			for_const (auto &chatData, list) { | ||||
| 				if (auto chat = App::feedChat(chatData)) { | ||||
| 					event.groups.push_back(chat); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		auto oldHeight = height(); | ||||
| 		onForceHideCommonGroups(); | ||||
| 		if (!event.groups.empty() && _showCommonGroupsObservable) { | ||||
| 			event.initialHeight = oldHeight - (isHidden() ? 0 : height()); | ||||
| 			_showCommonGroupsObservable->notify(event, true); | ||||
| 		} | ||||
| 	}))); | ||||
| } | ||||
| 
 | ||||
| void InfoWidget::setLabeledText(ChildWidget<Ui::FlatLabel> *labelWidget, const QString &label, | ||||
|  |  | |||
|  | @ -36,17 +36,12 @@ class LeftOutlineButton; | |||
| 
 | ||||
| namespace Profile { | ||||
| 
 | ||||
| struct CommonGroupsEvent; | ||||
| class InfoWidget : public BlockWidget, public RPCSender { | ||||
| public: | ||||
| 	InfoWidget(QWidget *parent, PeerData *peer); | ||||
| 
 | ||||
| 	void setShowCommonGroupsObservable(base::Observable<CommonGroupsEvent> *observable); | ||||
| 
 | ||||
| 	void showFinished() override; | ||||
| 
 | ||||
| 	void restoreState(const SectionMemento *memento) override; | ||||
| 
 | ||||
| protected: | ||||
| 	// Resizes content and counts natural widget height for the desired width.
 | ||||
| 	int resizeGetHeight(int newWidth) override; | ||||
|  | @ -66,7 +61,6 @@ private: | |||
| 	void refreshVisibility(); | ||||
| 
 | ||||
| 	int getCommonGroupsCount() const; | ||||
| 	void onForceHideCommonGroups(); | ||||
| 	void onShowCommonGroups(); | ||||
| 	void slideCommonGroupsDown(); | ||||
| 
 | ||||
|  | @ -87,11 +81,6 @@ private: | |||
| 	Animation _height; | ||||
| 	bool _showFinished = false; | ||||
| 
 | ||||
| 	bool _forceHiddenCommonGroups = false; | ||||
| 	mtpRequestId _getCommonGroupsRequestId = 0; | ||||
| 
 | ||||
| 	base::Observable<CommonGroupsEvent> *_showCommonGroupsObservable = nullptr; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| } // namespace Profile
 | ||||
|  |  | |||
|  | @ -0,0 +1,446 @@ | |||
| /*
 | ||||
| This file is part of Telegram Desktop, | ||||
| the official desktop version of Telegram messaging app, see https://telegram.org
 | ||||
| 
 | ||||
| Telegram Desktop is free software: you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation, either version 3 of the License, or | ||||
| (at your option) any later version. | ||||
| 
 | ||||
| It is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| GNU General Public License for more details. | ||||
| 
 | ||||
| In addition, as a special exception, the copyright holders give permission | ||||
| to link the code of portions of this program with the OpenSSL library. | ||||
| 
 | ||||
| Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | ||||
| Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 | ||||
| */ | ||||
| #include "stdafx.h" | ||||
| #include "profile/profile_common_groups_section.h" | ||||
| 
 | ||||
| #include "profile/profile_section_memento.h" | ||||
| #include "profile/profile_back_button.h" | ||||
| #include "styles/style_widgets.h" | ||||
| #include "styles/style_profile.h" | ||||
| #include "styles/style_window.h" | ||||
| #include "styles/style_settings.h" | ||||
| #include "ui/effects/ripple_animation.h" | ||||
| #include "ui/widgets/scroll_area.h" | ||||
| #include "ui/widgets/shadow.h" | ||||
| #include "mainwidget.h" | ||||
| #include "observer_peer.h" | ||||
| #include "apiwrap.h" | ||||
| #include "lang.h" | ||||
| 
 | ||||
| namespace Profile { | ||||
| namespace CommonGroups { | ||||
| namespace { | ||||
| 
 | ||||
| constexpr int kCommonGroupsPerPage = 40; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| Window::SectionWidget *SectionMemento::createWidget(QWidget *parent, const QRect &geometry) const { | ||||
| 	auto result = new Widget(parent, _peer); | ||||
| 	result->setInternalState(geometry, this); | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| FixedBar::FixedBar(QWidget *parent) : TWidget(parent) | ||||
| , _backButton(this, lang(lng_profile_common_groups_section)) { | ||||
| 	_backButton->moveToLeft(0, 0); | ||||
| 	connect(_backButton, SIGNAL(clicked()), this, SLOT(onBack())); | ||||
| } | ||||
| 
 | ||||
| void FixedBar::onBack() { | ||||
| 	App::main()->showBackFromStack(); | ||||
| } | ||||
| 
 | ||||
| int FixedBar::resizeGetHeight(int newWidth) { | ||||
| 	auto newHeight = 0; | ||||
| 
 | ||||
| 	auto buttonLeft = newWidth; | ||||
| 	_backButton->resizeToWidth(newWidth); | ||||
| 	_backButton->moveToLeft(0, 0); | ||||
| 	newHeight += _backButton->height(); | ||||
| 
 | ||||
| 	return newHeight; | ||||
| } | ||||
| 
 | ||||
| void FixedBar::setAnimatingMode(bool enabled) { | ||||
| 	if (_animatingMode != enabled) { | ||||
| 		_animatingMode = enabled; | ||||
| 		setCursor(_animatingMode ? style::cur_pointer : style::cur_default); | ||||
| 		if (_animatingMode) { | ||||
| 			setAttribute(Qt::WA_OpaquePaintEvent, false); | ||||
| 			hideChildren(); | ||||
| 		} else { | ||||
| 			setAttribute(Qt::WA_OpaquePaintEvent); | ||||
| 			showChildren(); | ||||
| 		} | ||||
| 		show(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void FixedBar::mousePressEvent(QMouseEvent *e) { | ||||
| 	if (e->button() == Qt::LeftButton) { | ||||
| 		onBack(); | ||||
| 	} else { | ||||
| 		TWidget::mousePressEvent(e); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| InnerWidget::Item::Item(PeerData *peer) : peer(peer) { | ||||
| } | ||||
| 
 | ||||
| InnerWidget::Item::~Item() = default; | ||||
| 
 | ||||
| InnerWidget::InnerWidget(QWidget *parent, PeerData *peer) : TWidget(parent) | ||||
| , _peer(peer) { | ||||
| 	setMouseTracking(true); | ||||
| 	setAttribute(Qt::WA_OpaquePaintEvent); | ||||
| 	_rowHeight = st::profileCommonGroupsPadding.top() + st::profileCommonGroupsPhotoSize + st::profileCommonGroupsPadding.bottom(); | ||||
| 	_contentTop = st::profileCommonGroupsSkip; | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) { | ||||
| 	_visibleTop = visibleTop; | ||||
| 	_visibleBottom = visibleBottom; | ||||
| 
 | ||||
| 	checkPreloadMore(); | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::checkPreloadMore() { | ||||
| 	if (_visibleTop + PreloadHeightsCount * (_visibleBottom - _visibleTop) > height()) { | ||||
| 		preloadMore(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::saveState(SectionMemento *memento) const { | ||||
| 	if (auto count = _items.size()) { | ||||
| 		QList<PeerData*> groups; | ||||
| 		groups.reserve(count); | ||||
| 		for_const (auto item, _items) { | ||||
| 			groups.push_back(item->peer); | ||||
| 		} | ||||
| 		memento->setCommonGroups(groups); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::restoreState(const SectionMemento *memento) { | ||||
| 	auto list = memento->getCommonGroups(); | ||||
| 	_allLoaded = false; | ||||
| 	if (!list.empty()) { | ||||
| 		showInitial(list); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::showInitial(const QList<PeerData*> &list) { | ||||
| 	for_const (auto group, list) { | ||||
| 		_items.push_back(computeItem(group)); | ||||
| 		_preloadGroupId = group->bareId(); | ||||
| 	} | ||||
| 	updateSize(); | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::preloadMore() { | ||||
| 	if (_preloadRequestId || _allLoaded) { | ||||
| 		return; | ||||
| 	} | ||||
| 	auto user = peer()->asUser(); | ||||
| 	t_assert(user != nullptr); | ||||
| 	auto request = MTPmessages_GetCommonChats(user->inputUser, MTP_int(_preloadGroupId), MTP_int(kCommonGroupsPerPage)); | ||||
| 	_preloadRequestId = MTP::send(request, ::rpcDone(base::lambda_guarded(this, [this](const MTPmessages_Chats &result) { | ||||
| 		_preloadRequestId = 0; | ||||
| 		_preloadGroupId = 0; | ||||
| 		_allLoaded = true; | ||||
| 		if (auto chats = Api::getChatsFromMessagesChats(result)) { | ||||
| 			auto &list = chats->c_vector().v; | ||||
| 			if (!list.empty()) { | ||||
| 				_items.reserve(_items.size() + list.size()); | ||||
| 				for_const (auto &chatData, list) { | ||||
| 					if (auto chat = App::feedChat(chatData)) { | ||||
| 						auto found = false; | ||||
| 						for_const (auto item, _items) { | ||||
| 							if (item->peer == chat) { | ||||
| 								found = true; | ||||
| 								break; | ||||
| 							} | ||||
| 						} | ||||
| 						if (!found) { | ||||
| 							_items.push_back(computeItem(chat)); | ||||
| 						} | ||||
| 						_preloadGroupId = chat->bareId(); | ||||
| 						_allLoaded = false; | ||||
| 					} | ||||
| 				} | ||||
| 				updateSize(); | ||||
| 			} | ||||
| 		} | ||||
| 	}))); | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::updateSize() { | ||||
| 	TWidget::resizeToWidth(width()); | ||||
| 	checkPreloadMore(); | ||||
| } | ||||
| 
 | ||||
| int InnerWidget::resizeGetHeight(int newWidth) { | ||||
| 	update(); | ||||
| 
 | ||||
| 	auto contentLeftMin = st::profileCommonGroupsLeftMin; | ||||
| 	auto contentLeftMax = st::profileCommonGroupsLeftMax; | ||||
| 	auto widthWithMin = st::windowMinWidth; | ||||
| 	auto widthWithMax = st::profileCommonGroupsWidthMax + 2 * contentLeftMax; | ||||
| 	_contentLeft = anim::interpolate(contentLeftMax, contentLeftMin, qMax(widthWithMax - newWidth, 0) / float64(widthWithMax - widthWithMin)); | ||||
| 	_contentWidth = qMin(newWidth - 2 * _contentLeft, st::profileCommonGroupsWidthMax); | ||||
| 
 | ||||
| 	auto newHeight = _contentTop; | ||||
| 	newHeight += _items.size() * _rowHeight; | ||||
| 	newHeight += st::profileCommonGroupsSkip; | ||||
| 	return qMax(newHeight, _minHeight); | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::paintEvent(QPaintEvent *e) { | ||||
| 	Painter p(this); | ||||
| 
 | ||||
| 	auto ms = getms(); | ||||
| 	auto clip = e->rect(); | ||||
| 	p.fillRect(clip, st::profileBg); | ||||
| 
 | ||||
| 	auto from = floorclamp(clip.y() - _contentTop, _rowHeight, 0, _items.size()); | ||||
| 	auto to = ceilclamp(clip.y() + clip.height() - _contentTop, _rowHeight, 0, _items.size()); | ||||
| 	for (auto i = from; i != to; ++i) { | ||||
| 		paintRow(p, i, ms); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::paintRow(Painter &p, int index, TimeMs ms) { | ||||
| 	auto item = _items[index]; | ||||
| 	auto selected = (_pressed >= 0) ? (index == _pressed) : (index == _selected); | ||||
| 
 | ||||
| 	auto x = _contentLeft; | ||||
| 	auto y = _contentTop + index * _rowHeight; | ||||
| 	if (selected) { | ||||
| 		p.fillRect(myrtlrect(x, y, _contentWidth, _rowHeight), st::profileCommonGroupsBgOver); | ||||
| 	} | ||||
| 	if (auto &ripple = item->ripple) { | ||||
| 		ripple->paint(p, x, y, width(), ms); | ||||
| 		if (ripple->empty()) { | ||||
| 			ripple.reset(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	x += st::profileCommonGroupsPadding.left(); | ||||
| 	y += st::profileCommonGroupsPadding.top(); | ||||
| 	item->peer->paintUserpic(p, st::profileCommonGroupsPhotoSize, rtl() ? (width() - x - st::profileCommonGroupsPhotoSize) : x, y); | ||||
| 
 | ||||
| 	x += st::profileCommonGroupsPhotoSize + st::profileCommonGroupsNameLeft; | ||||
| 	y += st::profileCommonGroupsNameTop; | ||||
| 	auto nameWidth = _contentWidth - (x - _contentLeft) - st::profileCommonGroupsPadding.right(); | ||||
| 	if (item->name.isEmpty()) { | ||||
| 		item->name.setText(st::semiboldFont, App::peerName(item->peer), _textNameOptions); | ||||
| 	} | ||||
| 	_items[index]->name.drawLeftElided(p, x, y, nameWidth, width()); | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::keyPressEvent(QKeyEvent *e) { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::updateSelected(QPoint localPos) { | ||||
| 	auto selected = -1; | ||||
| 	auto selectedKick = false; | ||||
| 
 | ||||
| 	if (rtl()) localPos.setX(width() - localPos.x()); | ||||
| 	if (localPos.x() >= _contentLeft && localPos.x() < _contentLeft + _contentWidth && localPos.y() >= _contentTop) { | ||||
| 		selected = (localPos.y() - _contentTop) / _rowHeight; | ||||
| 		if (selected >= _items.size()) { | ||||
| 			selected = -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (_selected != selected) { | ||||
| 		updateRow(_selected); | ||||
| 		_selected = selected; | ||||
| 		updateRow(_selected); | ||||
| 		if (_pressed < 0) { | ||||
| 			setCursor((_selected >= 0) ? style::cur_pointer : style::cur_default); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::updateRow(int index) { | ||||
| 	rtlupdate(_contentLeft, _contentTop + index * _rowHeight, _contentWidth, _rowHeight); | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::mousePressEvent(QMouseEvent *e) { | ||||
| 	_pressed = _selected; | ||||
| 	if (_pressed >= 0) { | ||||
| 		auto item = _items[_pressed]; | ||||
| 		if (!item->ripple) { | ||||
| 			auto mask = Ui::RippleAnimation::rectMask(QSize(_contentWidth, _rowHeight)); | ||||
| 			item->ripple = std_::make_unique<Ui::RippleAnimation>(st::profileCommonGroupsRipple, std_::move(mask), [this, index = _pressed] { | ||||
| 				updateRow(index); | ||||
| 			}); | ||||
| 		} | ||||
| 		auto left = _contentLeft; | ||||
| 		auto top = _contentTop + _rowHeight * _pressed; | ||||
| 		item->ripple->add(e->pos() - QPoint(left, top)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::mouseMoveEvent(QMouseEvent *e) { | ||||
| 	updateSelected(e->pos()); | ||||
| } | ||||
| 
 | ||||
| void InnerWidget::mouseReleaseEvent(QMouseEvent *e) { | ||||
| 	updateRow(_pressed); | ||||
| 	auto pressed = base::take(_pressed, -1); | ||||
| 	if (pressed >= 0 && pressed < _items.size()) { | ||||
| 		if (auto &ripple = _items[pressed]->ripple) { | ||||
| 			ripple->lastStop(); | ||||
| 		} | ||||
| 		if (pressed == _selected) { | ||||
| 			Ui::showPeerHistory(_items[pressed]->peer, ShowAtUnreadMsgId, Ui::ShowWay::Forward); | ||||
| 		} | ||||
| 	} | ||||
| 	setCursor(_selected ? style::cur_pointer : style::cur_default); | ||||
| 	updateRow(_selected); | ||||
| } | ||||
| 
 | ||||
| InnerWidget::Item *InnerWidget::computeItem(PeerData *group) { | ||||
| 	// Skip groups that migrated to supergroups.
 | ||||
| 	if (group->migrateTo()) { | ||||
| 		return nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	auto it = _dataMap.constFind(group); | ||||
| 	if (it == _dataMap.cend()) { | ||||
| 		it = _dataMap.insert(group, new Item(group)); | ||||
| 	} | ||||
| 	return it.value(); | ||||
| } | ||||
| 
 | ||||
| InnerWidget::~InnerWidget() { | ||||
| 	for (auto item : base::take(_dataMap)) { | ||||
| 		delete item; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| Widget::Widget(QWidget *parent, PeerData *peer) : Window::SectionWidget(parent) | ||||
| , _scroll(this, st::settingsScroll) | ||||
| , _inner(this, peer) | ||||
| , _fixedBar(this) | ||||
| , _fixedBarShadow(this, st::shadowColor) { | ||||
| 	_fixedBar->move(0, 0); | ||||
| 	_fixedBar->resizeToWidth(width()); | ||||
| 	_fixedBar->show(); | ||||
| 
 | ||||
| 	_fixedBarShadow->raise(); | ||||
| 	updateAdaptiveLayout(); | ||||
| 	subscribe(Adaptive::Changed(), [this]() { updateAdaptiveLayout(); }); | ||||
| 
 | ||||
| 	_scroll->setOwnedWidget(_inner); | ||||
| 	_scroll->move(0, _fixedBar->height()); | ||||
| 	_scroll->show(); | ||||
| 
 | ||||
| 	connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); | ||||
| 	connect(_inner, SIGNAL(cancelled()), _fixedBar, SLOT(onBack())); | ||||
| } | ||||
| 
 | ||||
| void Widget::updateAdaptiveLayout() { | ||||
| 	_fixedBarShadow->moveToLeft(Adaptive::OneColumn() ? 0 : st::lineWidth, _fixedBar->height()); | ||||
| } | ||||
| 
 | ||||
| PeerData *Widget::peer() const { | ||||
| 	return _inner->peer(); | ||||
| } | ||||
| 
 | ||||
| QPixmap Widget::grabForShowAnimation(const Window::SectionSlideParams ¶ms) { | ||||
| 	if (params.withTopBarShadow) _fixedBarShadow->hide(); | ||||
| 	auto result = myGrab(this); | ||||
| 	if (params.withTopBarShadow) _fixedBarShadow->show(); | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| void Widget::setInnerFocus() { | ||||
| 	_inner->setFocus(); | ||||
| } | ||||
| 
 | ||||
| bool Widget::showInternal(const Window::SectionMemento *memento) { | ||||
| 	if (auto profileMemento = dynamic_cast<const SectionMemento*>(memento)) { | ||||
| 		if (profileMemento->getPeer() == peer()) { | ||||
| 			restoreState(profileMemento); | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| void Widget::setInternalState(const QRect &geometry, const SectionMemento *memento) { | ||||
| 	setGeometry(geometry); | ||||
| 	myEnsureResized(this); | ||||
| 	restoreState(memento); | ||||
| } | ||||
| 
 | ||||
| std_::unique_ptr<Window::SectionMemento> Widget::createMemento() const { | ||||
| 	auto result = std_::make_unique<SectionMemento>(peer()); | ||||
| 	saveState(result.get()); | ||||
| 	return std_::move(result); | ||||
| } | ||||
| 
 | ||||
| void Widget::saveState(SectionMemento *memento) const { | ||||
| 	memento->setScrollTop(_scroll->scrollTop()); | ||||
| 	_inner->saveState(memento); | ||||
| } | ||||
| 
 | ||||
| void Widget::restoreState(const SectionMemento *memento) { | ||||
| 	_inner->restoreState(memento); | ||||
| 	auto scrollTop = memento->getScrollTop(); | ||||
| 	_scroll->scrollToY(scrollTop); | ||||
| 	_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); | ||||
| } | ||||
| 
 | ||||
| void Widget::resizeEvent(QResizeEvent *e) { | ||||
| 	if (!width() || !height()) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	int newScrollTop = _scroll->scrollTop() + topDelta(); | ||||
| 	_fixedBar->resizeToWidth(width()); | ||||
| 	_fixedBarShadow->resize(width(), st::lineWidth); | ||||
| 
 | ||||
| 	QSize scrollSize(width(), height() - _fixedBar->height()); | ||||
| 	if (_scroll->size() != scrollSize) { | ||||
| 		_scroll->resize(scrollSize); | ||||
| 		_inner->resizeToWidth(scrollSize.width(), _scroll->height()); | ||||
| 	} | ||||
| 
 | ||||
| 	if (!_scroll->isHidden()) { | ||||
| 		if (topDelta()) { | ||||
| 			_scroll->scrollToY(newScrollTop); | ||||
| 		} | ||||
| 		int scrollTop = _scroll->scrollTop(); | ||||
| 		_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void Widget::onScroll() { | ||||
| 	int scrollTop = _scroll->scrollTop(); | ||||
| 	_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); | ||||
| } | ||||
| 
 | ||||
| void Widget::showAnimatedHook() { | ||||
| 	_fixedBar->setAnimatingMode(true); | ||||
| } | ||||
| 
 | ||||
| void Widget::showFinishedHook() { | ||||
| 	_fixedBar->setAnimatingMode(false); | ||||
| } | ||||
| 
 | ||||
| } // namespace CommonGroups
 | ||||
| } // namespace Profile
 | ||||
|  | @ -0,0 +1,216 @@ | |||
| /*
 | ||||
| This file is part of Telegram Desktop, | ||||
| the official desktop version of Telegram messaging app, see https://telegram.org
 | ||||
| 
 | ||||
| Telegram Desktop is free software: you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation, either version 3 of the License, or | ||||
| (at your option) any later version. | ||||
| 
 | ||||
| It is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| GNU General Public License for more details. | ||||
| 
 | ||||
| In addition, as a special exception, the copyright holders give permission | ||||
| to link the code of portions of this program with the OpenSSL library. | ||||
| 
 | ||||
| Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | ||||
| Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 | ||||
| */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "window/section_widget.h" | ||||
| #include "window/section_memento.h" | ||||
| 
 | ||||
| namespace Notify { | ||||
| struct PeerUpdate; | ||||
| } // namespace Notify
 | ||||
| 
 | ||||
| namespace Ui { | ||||
| class ScrollArea; | ||||
| class PlainShadow; | ||||
| } // namespace Ui
 | ||||
| 
 | ||||
| namespace Profile { | ||||
| 
 | ||||
| class BackButton; | ||||
| 
 | ||||
| namespace CommonGroups { | ||||
| 
 | ||||
| class SectionMemento : public Window::SectionMemento { | ||||
| public: | ||||
| 	SectionMemento(PeerData *peer) : _peer(peer) { | ||||
| 	} | ||||
| 
 | ||||
| 	Window::SectionWidget *createWidget(QWidget *parent, const QRect &geometry) const override; | ||||
| 
 | ||||
| 	PeerData *getPeer() const { | ||||
| 		return _peer; | ||||
| 	} | ||||
| 	void setScrollTop(int scrollTop) { | ||||
| 		_scrollTop = scrollTop; | ||||
| 	} | ||||
| 	int getScrollTop() const { | ||||
| 		return _scrollTop; | ||||
| 	} | ||||
| 	void setCommonGroups(const QList<PeerData*> &groups) { | ||||
| 		_commonGroups = groups; | ||||
| 	} | ||||
| 	const QList<PeerData*> &getCommonGroups() const { | ||||
| 		return _commonGroups; | ||||
| 	} | ||||
| 
 | ||||
| private: | ||||
| 	PeerData *_peer; | ||||
| 	int _scrollTop = 0; | ||||
| 	QList<PeerData*> _commonGroups; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| class FixedBar final : public TWidget, private base::Subscriber { | ||||
| 	Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
| 	FixedBar(QWidget *parent); | ||||
| 
 | ||||
| 	// When animating mode is enabled the content is hidden and the
 | ||||
| 	// whole fixed bar acts like a back button.
 | ||||
| 	void setAnimatingMode(bool enabled); | ||||
| 
 | ||||
| protected: | ||||
| 	void mousePressEvent(QMouseEvent *e) override; | ||||
| 	int resizeGetHeight(int newWidth) override; | ||||
| 
 | ||||
| public slots: | ||||
| 	void onBack(); | ||||
| 
 | ||||
| private: | ||||
| 	ChildWidget<BackButton> _backButton; | ||||
| 
 | ||||
| 	bool _animatingMode = false; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| class InnerWidget final : public TWidget { | ||||
| 	Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
| 	InnerWidget(QWidget *parent, PeerData *peer); | ||||
| 
 | ||||
| 	PeerData *peer() const { | ||||
| 		return _peer; | ||||
| 	} | ||||
| 
 | ||||
| 	// Updates the area that is visible inside the scroll container.
 | ||||
| 	void setVisibleTopBottom(int visibleTop, int visibleBottom) override; | ||||
| 
 | ||||
| 	void resizeToWidth(int newWidth, int minHeight) { | ||||
| 		_minHeight = minHeight; | ||||
| 		return TWidget::resizeToWidth(newWidth); | ||||
| 	} | ||||
| 
 | ||||
| 	void saveState(SectionMemento *memento) const; | ||||
| 	void restoreState(const SectionMemento *memento); | ||||
| 
 | ||||
| 	~InnerWidget(); | ||||
| 
 | ||||
| signals: | ||||
| 	void cancelled(); | ||||
| 
 | ||||
| protected: | ||||
| 	void paintEvent(QPaintEvent *e) override; | ||||
| 	void keyPressEvent(QKeyEvent *e) override; | ||||
| 	void mousePressEvent(QMouseEvent *e) override; | ||||
| 	void mouseMoveEvent(QMouseEvent *e) override; | ||||
| 	void mouseReleaseEvent(QMouseEvent *e) override; | ||||
| 
 | ||||
| 	// Resizes content and counts natural widget height for the desired width.
 | ||||
| 	int resizeGetHeight(int newWidth) override; | ||||
| 
 | ||||
| private: | ||||
| 	void updateSelected(QPoint localPos); | ||||
| 	void updateRow(int index); | ||||
| 	void showInitial(const QList<PeerData*> &list); | ||||
| 	void checkPreloadMore(); | ||||
| 	void preloadMore(); | ||||
| 	void updateSize(); | ||||
| 	void paintRow(Painter &p, int index, TimeMs ms); | ||||
| 
 | ||||
| 	PeerData *_peer; | ||||
| 
 | ||||
| 	int _minHeight = 0; | ||||
| 	int _rowHeight = 0; | ||||
| 	int _contentLeft = 0; | ||||
| 	int _contentTop = 0; | ||||
| 	int _contentWidth = 0; | ||||
| 	int _visibleTop = 0; | ||||
| 	int _visibleBottom = 0; | ||||
| 
 | ||||
| 	struct Item { | ||||
| 		explicit Item(PeerData *peer); | ||||
| 		~Item(); | ||||
| 
 | ||||
| 		PeerData * const peer; | ||||
| 		Text name; | ||||
| 		std_::unique_ptr<Ui::RippleAnimation> ripple; | ||||
| 	}; | ||||
| 	Item *computeItem(PeerData *group); | ||||
| 	QMap<PeerData*, Item*> _dataMap; | ||||
| 	QList<Item*> _items; | ||||
| 	int _selected = -1; | ||||
| 	int _pressed = -1; | ||||
| 
 | ||||
| 	int32 _preloadGroupId = 0; | ||||
| 	mtpRequestId _preloadRequestId = 0; | ||||
| 	bool _allLoaded = true; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| class Widget final : public Window::SectionWidget { | ||||
| 	Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
| 	Widget(QWidget *parent, PeerData *peer); | ||||
| 
 | ||||
| 	PeerData *peer() const; | ||||
| 	PeerData *peerForDialogs() const override { | ||||
| 		return peer(); | ||||
| 	} | ||||
| 
 | ||||
| 	bool hasTopBarShadow() const override { | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms) override; | ||||
| 
 | ||||
| 	void setInnerFocus() override; | ||||
| 
 | ||||
| 	bool showInternal(const Window::SectionMemento *memento) override; | ||||
| 	std_::unique_ptr<Window::SectionMemento> createMemento() const override; | ||||
| 
 | ||||
| 	void setInternalState(const QRect &geometry, const SectionMemento *memento); | ||||
| 
 | ||||
| protected: | ||||
| 	void resizeEvent(QResizeEvent *e) override; | ||||
| 
 | ||||
| 	void showAnimatedHook() override; | ||||
| 	void showFinishedHook() override; | ||||
| 
 | ||||
| 	private slots: | ||||
| 	void onScroll(); | ||||
| 
 | ||||
| private: | ||||
| 	void updateAdaptiveLayout(); | ||||
| 	void saveState(SectionMemento *memento) const; | ||||
| 	void restoreState(const SectionMemento *memento); | ||||
| 
 | ||||
| 	ChildWidget<Ui::ScrollArea> _scroll; | ||||
| 	ChildWidget<InnerWidget> _inner; | ||||
| 	ChildWidget<FixedBar> _fixedBar; | ||||
| 	ChildWidget<Ui::PlainShadow> _fixedBarShadow; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| } // namespace CommonGroups
 | ||||
| } // namespace Profile
 | ||||
|  | @ -29,59 +29,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | |||
| #include "boxes/addcontactbox.h" | ||||
| #include "boxes/confirmbox.h" | ||||
| #include "observer_peer.h" | ||||
| #include "window/top_bar_widget.h" | ||||
| #include "styles/style_boxes.h" | ||||
| #include "profile/profile_back_button.h" | ||||
| 
 | ||||
| namespace Profile { | ||||
| 
 | ||||
| class BackButton final : public Ui::AbstractButton, private base::Subscriber { | ||||
| public: | ||||
| 	BackButton(QWidget *parent) : Ui::AbstractButton(parent) | ||||
| 	, _text(lang(lng_menu_back).toUpper()) { | ||||
| 		setCursor(style::cur_pointer); | ||||
| 
 | ||||
| 		subscribe(Adaptive::Changed(), [this] { updateAdaptiveLayout(); }); | ||||
| 		updateAdaptiveLayout(); | ||||
| 	} | ||||
| 
 | ||||
| protected: | ||||
| 	int resizeGetHeight(int newWidth) override { | ||||
| 		return st::profileTopBarHeight; | ||||
| 	} | ||||
| 	void paintEvent(QPaintEvent *e) override { | ||||
| 		Painter p(this); | ||||
| 
 | ||||
| 		p.fillRect(e->rect(), st::profileBg); | ||||
| 		st::topBarBack.paint(p, (st::topBarArrowPadding.left() - st::topBarBack.width()) / 2, (st::topBarHeight - st::topBarBack.height()) / 2, width()); | ||||
| 
 | ||||
| 		p.setFont(st::topBarButton.font); | ||||
| 		p.setPen(st::topBarButton.textFg); | ||||
| 		p.drawTextLeft(st::topBarArrowPadding.left(), st::topBarButton.padding.top() + st::topBarButton.textTop, width(), _text); | ||||
| 
 | ||||
| 		Window::TopBarWidget::paintUnreadCounter(p, width()); | ||||
| 	} | ||||
| 	void onStateChanged(State was, StateChangeSource source) override { | ||||
| 		if (isDown() && !(was & StateFlag::Down)) { | ||||
| 			emit clicked(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| private: | ||||
| 	void updateAdaptiveLayout() { | ||||
| 		if (!Adaptive::OneColumn()) { | ||||
| 			unsubscribe(base::take(_unreadCounterSubscription)); | ||||
| 		} else if (!_unreadCounterSubscription) { | ||||
| 			_unreadCounterSubscription = subscribe(Global::RefUnreadCounterUpdate(), [this] { | ||||
| 				rtlupdate(0, 0, st::titleUnreadCounterRight, st::titleUnreadCounterTop); | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	int _unreadCounterSubscription = 0; | ||||
| 	QString _text; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| using UpdateFlag = Notify::PeerUpdate::Flag; | ||||
|  | @ -98,7 +49,7 @@ FixedBar::FixedBar(QWidget *parent, PeerData *peer) : TWidget(parent) | |||
| , _peerChat(peer->asChat()) | ||||
| , _peerChannel(peer->asChannel()) | ||||
| , _peerMegagroup(peer->isMegagroup() ? _peerChannel : nullptr) | ||||
| , _backButton(this) { | ||||
| , _backButton(this, lang(lng_menu_back)) { | ||||
| 	_backButton->moveToLeft(0, 0); | ||||
| 	connect(_backButton, SIGNAL(clicked()), this, SLOT(onBack())); | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,7 +24,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | |||
| #include "styles/style_profile.h" | ||||
| #include "styles/style_window.h" | ||||
| #include "profile/profile_cover.h" | ||||
| #include "profile/profile_block_common_groups.h" | ||||
| #include "profile/profile_block_info.h" | ||||
| #include "profile/profile_block_settings.h" | ||||
| #include "profile/profile_block_invite_link.h" | ||||
|  | @ -50,16 +49,7 @@ void InnerWidget::createBlocks() { | |||
| 	auto channel = _peer->asChannel(); | ||||
| 	auto megagroup = _peer->isMegagroup() ? channel : nullptr; | ||||
| 	if (user || channel || megagroup) { | ||||
| 		auto widget = new InfoWidget(this, _peer); | ||||
| 		widget->setShowCommonGroupsObservable(&_showCommonGroupsObservable); | ||||
| 		_blocks.push_back({ widget, BlockSide::Right }); | ||||
| 	} | ||||
| 	if (user) { | ||||
| 		_commonGroupsWidget = new CommonGroupsWidget(this, _peer); | ||||
| 		_commonGroupsWidget->setShowCommonGroupsObservable(&_showCommonGroupsObservable); | ||||
| 		_blocks.push_back({ _commonGroupsWidget, BlockSide::Right }); | ||||
| 	} else { | ||||
| 		_commonGroupsWidget = nullptr; | ||||
| 		_blocks.push_back({ new InfoWidget(this, _peer), BlockSide::Right }); | ||||
| 	} | ||||
| 	_blocks.push_back({ new SettingsWidget(this, _peer), BlockSide::Right }); | ||||
| 	if (chat || channel || megagroup) { | ||||
|  |  | |||
|  | @ -20,13 +20,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | |||
| */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "profile/profile_block_common_groups.h" | ||||
| 
 | ||||
| namespace Profile { | ||||
| 
 | ||||
| class CoverWidget; | ||||
| class BlockWidget; | ||||
| struct CommonGroupsEvent; | ||||
| class SectionMemento; | ||||
| 
 | ||||
| class InnerWidget final : public TWidget { | ||||
|  | @ -117,12 +114,8 @@ private: | |||
| 	}; | ||||
| 	QList<Block> _blocks; | ||||
| 
 | ||||
| 	// We need to save this pointer for getting common groups list for section memento.
 | ||||
| 	CommonGroupsWidget *_commonGroupsWidget = nullptr; | ||||
| 
 | ||||
| 	Mode _mode = Mode::OneColumn; | ||||
| 
 | ||||
| 	base::Observable<CommonGroupsEvent> _showCommonGroupsObservable; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Profile
 | ||||
|  |  | |||
|  | @ -42,17 +42,10 @@ public: | |||
| 	int getScrollTop() const { | ||||
| 		return _scrollTop; | ||||
| 	} | ||||
| 	void setCommonGroups(const QList<PeerData*> &groups) { | ||||
| 		_commonGroups = groups; | ||||
| 	} | ||||
| 	const QList<PeerData*> &getCommonGroups() const { | ||||
| 		return _commonGroups; | ||||
| 	} | ||||
| 
 | ||||
| private: | ||||
| 	PeerData *_peer; | ||||
| 	int _scrollTop = 0; | ||||
| 	QList<PeerData*> _commonGroups; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,6 +28,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | |||
| #include "mainwindow.h" | ||||
| #include "application.h" | ||||
| #include "ui/widgets/scroll_area.h" | ||||
| #include "ui/widgets/shadow.h" | ||||
| 
 | ||||
| namespace Profile { | ||||
| 
 | ||||
|  | @ -61,6 +62,10 @@ PeerData *Widget::peer() const { | |||
| 	return _inner->peer(); | ||||
| } | ||||
| 
 | ||||
| bool Widget::hasTopBarShadow() const { | ||||
| 	return _fixedBarShadow->isFullyShown(); | ||||
| } | ||||
| 
 | ||||
| QPixmap Widget::grabForShowAnimation(const Window::SectionSlideParams ¶ms) { | ||||
| 	if (params.withTopBarShadow) _fixedBarShadow->hide(); | ||||
| 	auto result = myGrab(this); | ||||
|  |  | |||
|  | @ -21,10 +21,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | |||
| #pragma once | ||||
| 
 | ||||
| #include "window/section_widget.h" | ||||
| #include "ui/widgets/shadow.h" | ||||
| 
 | ||||
| namespace Ui { | ||||
| class ScrollArea; | ||||
| class ToggleableShadow; | ||||
| } // namespace Ui
 | ||||
| 
 | ||||
| namespace Profile { | ||||
|  | @ -43,9 +43,7 @@ public: | |||
| 		return peer(); | ||||
| 	} | ||||
| 
 | ||||
| 	bool hasTopBarShadow() const override { | ||||
| 		return _fixedBarShadow->isFullyShown(); | ||||
| 	} | ||||
| 	bool hasTopBarShadow() const override; | ||||
| 
 | ||||
| 	QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms) override; | ||||
| 
 | ||||
|  |  | |||
|  | @ -179,7 +179,7 @@ void CreateImplementationsMap() { | |||
| 	Implementations.createIfNull(); | ||||
| 	Type recordTypes[] = { | ||||
| 		Type::RecordVideo, | ||||
| 		Type::RecordVoice | ||||
| 		Type::RecordVoice, | ||||
| 	}; | ||||
| 	for_const (auto type, recordTypes) { | ||||
| 		Implementations->insert(type, &RecordAnimation::kMeta); | ||||
|  | @ -188,7 +188,7 @@ void CreateImplementationsMap() { | |||
| 		Type::UploadFile, | ||||
| 		Type::UploadPhoto, | ||||
| 		Type::UploadVideo, | ||||
| 		Type::UploadVoice | ||||
| 		Type::UploadVoice, | ||||
| 	}; | ||||
| 	for_const (auto type, uploadTypes) { | ||||
| 		Implementations->insert(type, &UploadAnimation::kMeta); | ||||
|  |  | |||
|  | @ -882,17 +882,17 @@ historySendActionTypingLargeNumerator: 28px; | |||
| historySendActionTypingSmallNumerator: 16px; | ||||
| historySendActionTypingDenominator: 12.; | ||||
| 
 | ||||
| historySendActionRecordDuration: 300; | ||||
| historySendActionRecordDuration: 500; | ||||
| historySendActionRecordPosition: point(1px, -4px); | ||||
| historySendActionRecordDelta: 3px; | ||||
| historySendActionRecordStrokeNumerator: 12px; | ||||
| historySendActionRecordDelta: 4px; | ||||
| historySendActionRecordStrokeNumerator: 16px; | ||||
| historySendActionRecordDenominator: 8.; | ||||
| 
 | ||||
| historySendActionUploadDuration: 500; | ||||
| historySendActionUploadPosition: point(0px, -4px); | ||||
| historySendActionUploadDelta: 5px; | ||||
| historySendActionUploadStrokeNumerator: 12px; | ||||
| historySendActionUploadSizeNumerator: 28px; | ||||
| historySendActionUploadStrokeNumerator: 16px; | ||||
| historySendActionUploadSizeNumerator: 32px; | ||||
| historySendActionUploadDenominator: 8.; | ||||
| 
 | ||||
| MediaPlayerButton { | ||||
|  |  | |||
|  | @ -3,4 +3,4 @@ AppVersionStrMajor 0.10 | |||
| AppVersionStrSmall 0.10.20 | ||||
| AppVersionStr      0.10.20 | ||||
| AlphaChannel       0 | ||||
| BetaVersion        10019012 | ||||
| BetaVersion        10019013 | ||||
|  |  | |||
|  | @ -390,12 +390,12 @@ | |||
|       '<(src_loc)/platform/platform_main_window.h', | ||||
|       '<(src_loc)/platform/platform_notifications_manager.h', | ||||
|       '<(src_loc)/platform/platform_window_title.h', | ||||
|       '<(src_loc)/profile/profile_back_button.cpp', | ||||
|       '<(src_loc)/profile/profile_back_button.h', | ||||
|       '<(src_loc)/profile/profile_block_actions.cpp', | ||||
|       '<(src_loc)/profile/profile_block_actions.h', | ||||
|       '<(src_loc)/profile/profile_block_channel_members.cpp', | ||||
|       '<(src_loc)/profile/profile_block_channel_members.h', | ||||
|       '<(src_loc)/profile/profile_block_common_groups.cpp', | ||||
|       '<(src_loc)/profile/profile_block_common_groups.h', | ||||
|       '<(src_loc)/profile/profile_block_info.cpp', | ||||
|       '<(src_loc)/profile/profile_block_info.h', | ||||
|       '<(src_loc)/profile/profile_block_invite_link.cpp', | ||||
|  | @ -410,6 +410,8 @@ | |||
|       '<(src_loc)/profile/profile_block_shared_media.h', | ||||
|       '<(src_loc)/profile/profile_block_widget.cpp', | ||||
|       '<(src_loc)/profile/profile_block_widget.h', | ||||
|       '<(src_loc)/profile/profile_common_groups_section.cpp', | ||||
|       '<(src_loc)/profile/profile_common_groups_section.h', | ||||
|       '<(src_loc)/profile/profile_cover_drop_area.cpp', | ||||
|       '<(src_loc)/profile/profile_cover_drop_area.h', | ||||
|       '<(src_loc)/profile/profile_cover.cpp', | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue