Add shared media empty placeholders.
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 952 B |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 894 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.7 KiB |
|
@ -590,8 +590,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
"lng_profile_files_header" = "Files";
|
"lng_profile_files_header" = "Files";
|
||||||
"lng_profile_audios#one" = "{count} voice message";
|
"lng_profile_audios#one" = "{count} voice message";
|
||||||
"lng_profile_audios#other" = "{count} voice messages";
|
"lng_profile_audios#other" = "{count} voice messages";
|
||||||
"lng_profile_rounds#one" = "{count} video message";
|
//"lng_profile_rounds#one" = "{count} video message";
|
||||||
"lng_profile_rounds#other" = "{count} video messages";
|
//"lng_profile_rounds#other" = "{count} video messages";
|
||||||
"lng_profile_audios_header" = "Voice messages";
|
"lng_profile_audios_header" = "Voice messages";
|
||||||
"lng_profile_shared_links#one" = "{count} shared link";
|
"lng_profile_shared_links#one" = "{count} shared link";
|
||||||
"lng_profile_shared_links#other" = "{count} shared links";
|
"lng_profile_shared_links#other" = "{count} shared links";
|
||||||
|
@ -645,10 +645,19 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
"lng_media_selected_file#other" = "{count} Files";
|
"lng_media_selected_file#other" = "{count} Files";
|
||||||
"lng_media_selected_audio#one" = "{count} Voice message";
|
"lng_media_selected_audio#one" = "{count} Voice message";
|
||||||
"lng_media_selected_audio#other" = "{count} Voice messages";
|
"lng_media_selected_audio#other" = "{count} Voice messages";
|
||||||
"lng_media_selected_round#one" = "{count} Video message";
|
//"lng_media_selected_round#one" = "{count} Video message";
|
||||||
"lng_media_selected_round#other" = "{count} video messages";
|
//"lng_media_selected_round#other" = "{count} Video messages";
|
||||||
"lng_media_selected_link#one" = "{count} Shared link";
|
"lng_media_selected_link#one" = "{count} Shared link";
|
||||||
"lng_media_selected_link#other" = "{count} Shared links";
|
"lng_media_selected_link#other" = "{count} Shared links";
|
||||||
|
"lng_media_photo_empty" = "No photos here yet";
|
||||||
|
"lng_media_video_empty" = "No videos here yet";
|
||||||
|
"lng_media_song_empty" = "No music files here yet";
|
||||||
|
"lng_media_file_empty" = "No files here yet";
|
||||||
|
"lng_media_audio_empty" = "No voice messages here yet";
|
||||||
|
"lng_media_link_empty" = "No shared links here yet";
|
||||||
|
"lng_media_song_empty_search" = "No music files found";
|
||||||
|
"lng_media_file_empty_search" = "No files found";
|
||||||
|
"lng_media_link_empty_search" = "No shared links found";
|
||||||
|
|
||||||
"lng_manage_group_title" = "Manage Group";
|
"lng_manage_group_title" = "Manage Group";
|
||||||
"lng_manage_channel_title" = "Manage Channel";
|
"lng_manage_channel_title" = "Manage Channel";
|
||||||
|
|
|
@ -390,7 +390,7 @@ void DelayedSearchController::setQuery(
|
||||||
|
|
||||||
void DelayedSearchController::setQueryFast(const Query &query) {
|
void DelayedSearchController::setQueryFast(const Query &query) {
|
||||||
_controller.setQuery(query);
|
_controller.setQuery(query);
|
||||||
_sourceChanges.fire({});
|
_currentQueryChanges.fire_copy(query.query);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Api
|
} // namespace Api
|
||||||
|
|
|
@ -162,8 +162,9 @@ public:
|
||||||
limitAfter);
|
limitAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<> sourceChanged() const {
|
rpl::producer<QString> currentQueryValue() const {
|
||||||
return _sourceChanges.events();
|
return _currentQueryChanges.events_starting_with(
|
||||||
|
currentQuery().query);
|
||||||
}
|
}
|
||||||
|
|
||||||
SavedState saveState() {
|
SavedState saveState() {
|
||||||
|
@ -178,7 +179,7 @@ private:
|
||||||
SearchController _controller;
|
SearchController _controller;
|
||||||
Query _nextQuery;
|
Query _nextQuery;
|
||||||
base::Timer _timer;
|
base::Timer _timer;
|
||||||
rpl::event_stream<> _sourceChanges;
|
rpl::event_stream<QString> _currentQueryChanges;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -548,6 +548,21 @@ managePeerButtonLabel: FlatLabel(defaultFlatLabel) {
|
||||||
}
|
}
|
||||||
managePeerButtonLabelPosition: point(25px, 10px);
|
managePeerButtonLabelPosition: point(25px, 10px);
|
||||||
|
|
||||||
|
infoEmptyFg: windowSubTextFg;
|
||||||
|
infoEmptyPhoto: icon {{ "info_media_photo_empty", infoEmptyFg }};
|
||||||
|
infoEmptyVideo: icon {{ "info_media_video_empty", infoEmptyFg }};
|
||||||
|
infoEmptyAudio: icon {{ "info_media_audio_empty", infoEmptyFg }};
|
||||||
|
infoEmptyFile: icon {{ "info_media_file_empty", infoEmptyFg }};
|
||||||
|
infoEmptyVoice: icon {{ "info_media_voice_empty", infoEmptyFg }};
|
||||||
|
infoEmptyLink: icon {{ "info_media_link_empty", infoEmptyFg }};
|
||||||
|
infoEmptyIconTop: 120px;
|
||||||
|
infoEmptyLabelTop: 40px;
|
||||||
|
infoEmptyLabelSkip: 20px;
|
||||||
|
infoEmptyLabel: FlatLabel(defaultFlatLabel) {
|
||||||
|
minWidth: 220px;
|
||||||
|
textFg: windowSubTextFg;
|
||||||
|
}
|
||||||
|
|
||||||
editPeerDeleteButtonMargins: margins(23px, 16px, 23px, 16px);
|
editPeerDeleteButtonMargins: margins(23px, 16px, 23px, 16px);
|
||||||
editPeerDeleteButton: sessionTerminateAllButton;
|
editPeerDeleteButton: sessionTerminateAllButton;
|
||||||
editPeerPhotoMargins: margins(23px, 16px, 23px, 8px);
|
editPeerPhotoMargins: margins(23px, 16px, 23px, 8px);
|
||||||
|
|
|
@ -150,6 +150,10 @@ rpl::producer<Section> ContentWidget::sectionRequest() const {
|
||||||
return rpl::never<Section>();
|
return rpl::never<Section>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<int> ContentWidget::scrollHeightValue() const {
|
||||||
|
return _scroll->heightValue();
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<int> ContentWidget::desiredHeightValue() const {
|
rpl::producer<int> ContentWidget::desiredHeightValue() const {
|
||||||
using namespace rpl::mappers;
|
using namespace rpl::mappers;
|
||||||
return rpl::combine(
|
return rpl::combine(
|
||||||
|
|
|
@ -52,6 +52,7 @@ public:
|
||||||
virtual void setIsStackBottom(bool isStackBottom) {
|
virtual void setIsStackBottom(bool isStackBottom) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<int> scrollHeightValue() const;
|
||||||
rpl::producer<int> desiredHeightValue() const override;
|
rpl::producer<int> desiredHeightValue() const override;
|
||||||
rpl::producer<bool> desiredShadowVisibility() const;
|
rpl::producer<bool> desiredShadowVisibility() const;
|
||||||
bool hasTopBarShadow() const;
|
bool hasTopBarShadow() const;
|
||||||
|
|
|
@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
|
|
||||||
|
#include <rpl/range.h>
|
||||||
|
#include <rpl/then.h>
|
||||||
#include "ui/search_field_controller.h"
|
#include "ui/search_field_controller.h"
|
||||||
#include "data/data_shared_media.h"
|
#include "data/data_shared_media.h"
|
||||||
#include "info/info_content_widget.h"
|
#include "info/info_content_widget.h"
|
||||||
|
|
|
@ -116,8 +116,8 @@ public:
|
||||||
SparseIdsMergedSlice::UniversalMsgId aroundId,
|
SparseIdsMergedSlice::UniversalMsgId aroundId,
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
int limitAfter) const;
|
int limitAfter) const;
|
||||||
rpl::producer<> mediaSourceChanged() const {
|
rpl::producer<QString> mediaSourceQueryValue() const {
|
||||||
return _searchController->sourceChanged();
|
return _searchController->currentQueryValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveSearchState(not_null<ContentMemento*> memento);
|
void saveSearchState(not_null<ContentMemento*> memento);
|
||||||
|
|
|
@ -65,7 +65,7 @@ QString TopBarOverride::generateText() const {
|
||||||
case Type::MusicFile: return lng_media_selected_song;
|
case Type::MusicFile: return lng_media_selected_song;
|
||||||
case Type::Link: return lng_media_selected_link;
|
case Type::Link: return lng_media_selected_link;
|
||||||
case Type::VoiceFile: return lng_media_selected_audio;
|
case Type::VoiceFile: return lng_media_selected_audio;
|
||||||
case Type::RoundFile: return lng_media_selected_round;
|
// case Type::RoundFile: return lng_media_selected_round;
|
||||||
}
|
}
|
||||||
Unexpected("Type in TopBarOverride::generateText()");
|
Unexpected("Type in TopBarOverride::generateText()");
|
||||||
}();
|
}();
|
||||||
|
|
|
@ -46,7 +46,7 @@ inline auto MediaTextPhrase(Type type) {
|
||||||
case Type::MusicFile: return lng_profile_songs;
|
case Type::MusicFile: return lng_profile_songs;
|
||||||
case Type::Link: return lng_profile_shared_links;
|
case Type::Link: return lng_profile_shared_links;
|
||||||
case Type::VoiceFile: return lng_profile_audios;
|
case Type::VoiceFile: return lng_profile_audios;
|
||||||
case Type::RoundFile: return lng_profile_rounds;
|
// case Type::RoundFile: return lng_profile_rounds;
|
||||||
}
|
}
|
||||||
Unexpected("Type in MediaTextPhrase()");
|
Unexpected("Type in MediaTextPhrase()");
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
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-2017 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#include "info/media/info_media_empty_widget.h"
|
||||||
|
|
||||||
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "styles/style_info.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
|
||||||
|
namespace Info {
|
||||||
|
namespace Media {
|
||||||
|
|
||||||
|
EmptyWidget::EmptyWidget(QWidget *parent)
|
||||||
|
: RpWidget(parent)
|
||||||
|
, _text(this, st::infoEmptyLabel) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmptyWidget::setFullHeight(rpl::producer<int> fullHeightValue) {
|
||||||
|
std::move(fullHeightValue)
|
||||||
|
| rpl::start_with_next([this](int fullHeight) {
|
||||||
|
// Make icon center be on 1/3 height.
|
||||||
|
auto iconCenter = fullHeight / 3;
|
||||||
|
auto iconHeight = st::infoEmptyFile.height();
|
||||||
|
auto iconTop = iconCenter - iconHeight / 2;
|
||||||
|
_height = iconTop + st::infoEmptyIconTop;
|
||||||
|
resizeToWidth(width());
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmptyWidget::setType(Type type) {
|
||||||
|
_type = type;
|
||||||
|
using Data = std::pair<const style::icon*, LangKey>;
|
||||||
|
_icon = [&] {
|
||||||
|
switch (_type) {
|
||||||
|
case Type::Photo: return &st::infoEmptyPhoto;
|
||||||
|
case Type::Video: return &st::infoEmptyVideo;
|
||||||
|
case Type::MusicFile: return &st::infoEmptyAudio;
|
||||||
|
case Type::File: return &st::infoEmptyFile;
|
||||||
|
case Type::Link: return &st::infoEmptyLink;
|
||||||
|
case Type::VoiceFile: return &st::infoEmptyVoice;
|
||||||
|
}
|
||||||
|
Unexpected("Bad type in EmptyWidget::setType()");
|
||||||
|
}();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmptyWidget::setSearchQuery(const QString &query) {
|
||||||
|
auto key = [&] {
|
||||||
|
switch (_type) {
|
||||||
|
case Type::Photo:
|
||||||
|
return lng_media_photo_empty;
|
||||||
|
case Type::Video:
|
||||||
|
return lng_media_video_empty;
|
||||||
|
case Type::MusicFile:
|
||||||
|
return query.isEmpty()
|
||||||
|
? lng_media_song_empty
|
||||||
|
: lng_media_song_empty_search;
|
||||||
|
case Type::File:
|
||||||
|
return query.isEmpty()
|
||||||
|
? lng_media_file_empty
|
||||||
|
: lng_media_file_empty_search;
|
||||||
|
case Type::Link:
|
||||||
|
return query.isEmpty()
|
||||||
|
? lng_media_link_empty
|
||||||
|
: lng_media_link_empty_search;
|
||||||
|
case Type::VoiceFile:
|
||||||
|
return lng_media_audio_empty;
|
||||||
|
}
|
||||||
|
Unexpected("Bad type in EmptyWidget::setSearchQuery()");
|
||||||
|
}();
|
||||||
|
_text->setText(lang(key));
|
||||||
|
resizeToWidth(width());
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmptyWidget::paintEvent(QPaintEvent *e) {
|
||||||
|
if (!_icon) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Painter p(this);
|
||||||
|
|
||||||
|
auto iconLeft = (width() - _icon->width()) / 2;
|
||||||
|
auto iconTop = height() - st::infoEmptyIconTop;
|
||||||
|
_icon->paint(p, iconLeft, iconTop, width());
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmptyWidget::resizeGetHeight(int newWidth) {
|
||||||
|
auto labelTop = _height - st::infoEmptyLabelTop;
|
||||||
|
auto labelWidth = newWidth - 2 * st::infoEmptyLabelSkip;
|
||||||
|
_text->resizeToNaturalWidth(labelWidth);
|
||||||
|
|
||||||
|
auto labelLeft = (newWidth - _text->width()) / 2;
|
||||||
|
_text->moveToLeft(labelLeft, labelTop, newWidth);
|
||||||
|
|
||||||
|
update();
|
||||||
|
return _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Media
|
||||||
|
} // namespace Info
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
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-2017 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
|
#include "info/media/info_media_widget.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class FlatLabel;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
|
namespace Info {
|
||||||
|
namespace Media {
|
||||||
|
|
||||||
|
class EmptyWidget : public Ui::RpWidget {
|
||||||
|
public:
|
||||||
|
EmptyWidget(QWidget *parent);
|
||||||
|
|
||||||
|
void setFullHeight(rpl::producer<int> fullHeightValue);
|
||||||
|
void setType(Type type);
|
||||||
|
void setSearchQuery(const QString &query);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
|
int resizeGetHeight(int newWidth) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
object_ptr<Ui::FlatLabel> _text;
|
||||||
|
Type _type = Type::kCount;
|
||||||
|
const style::icon *_icon = nullptr;
|
||||||
|
int _height = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Media
|
||||||
|
} // namespace Info
|
|
@ -24,6 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "boxes/abstract_box.h"
|
#include "boxes/abstract_box.h"
|
||||||
#include "info/media/info_media_list_widget.h"
|
#include "info/media/info_media_list_widget.h"
|
||||||
#include "info/media/info_media_buttons.h"
|
#include "info/media/info_media_buttons.h"
|
||||||
|
#include "info/media/info_media_empty_widget.h"
|
||||||
#include "info/profile/info_profile_button.h"
|
#include "info/profile/info_profile_button.h"
|
||||||
#include "info/profile/info_profile_icon.h"
|
#include "info/profile/info_profile_icon.h"
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
|
@ -41,7 +42,8 @@ InnerWidget::InnerWidget(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<Controller*> controller)
|
not_null<Controller*> controller)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _controller(controller) {
|
, _controller(controller)
|
||||||
|
, _empty(this) {
|
||||||
_list = setupList();
|
_list = setupList();
|
||||||
setupOtherTypes();
|
setupOtherTypes();
|
||||||
}
|
}
|
||||||
|
@ -253,6 +255,12 @@ object_ptr<ListWidget> InnerWidget::setupList() {
|
||||||
_scrollToRequests,
|
_scrollToRequests,
|
||||||
result->lifetime());
|
result->lifetime());
|
||||||
_selectedLists.fire(result->selectedListValue());
|
_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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,6 +295,7 @@ int InnerWidget::resizeGetHeight(int newWidth) {
|
||||||
_searchField->resizeToWidth(newWidth);
|
_searchField->resizeToWidth(newWidth);
|
||||||
}
|
}
|
||||||
_list->resizeToWidth(newWidth);
|
_list->resizeToWidth(newWidth);
|
||||||
|
_empty->resizeToWidth(newWidth);
|
||||||
return recountHeight();
|
return recountHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,12 +317,30 @@ int InnerWidget::recountHeight() {
|
||||||
_searchField->moveToLeft(0, top);
|
_searchField->moveToLeft(0, top);
|
||||||
top += _searchField->heightNoMargins() - st::lineWidth;
|
top += _searchField->heightNoMargins() - st::lineWidth;
|
||||||
}
|
}
|
||||||
|
auto listHeight = 0;
|
||||||
if (_list) {
|
if (_list) {
|
||||||
_list->moveToLeft(0, top);
|
_list->moveToLeft(0, top);
|
||||||
top += _list->heightNoMargins();
|
listHeight = _list->heightNoMargins();
|
||||||
|
top += listHeight;
|
||||||
|
}
|
||||||
|
if (listHeight > 0) {
|
||||||
|
_empty->hide();
|
||||||
|
} else {
|
||||||
|
_empty->show();
|
||||||
|
_empty->moveToLeft(0, top);
|
||||||
|
top += _empty->heightNoMargins();
|
||||||
}
|
}
|
||||||
return top;
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Media
|
} // namespace Media
|
||||||
} // namespace Info
|
} // namespace Info
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace Media {
|
||||||
|
|
||||||
class Memento;
|
class Memento;
|
||||||
class ListWidget;
|
class ListWidget;
|
||||||
|
class EmptyWidget;
|
||||||
|
|
||||||
class InnerWidget final : public Ui::RpWidget {
|
class InnerWidget final : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
|
@ -52,6 +53,8 @@ public:
|
||||||
void saveState(not_null<Memento*> memento);
|
void saveState(not_null<Memento*> memento);
|
||||||
void restoreState(not_null<Memento*> memento);
|
void restoreState(not_null<Memento*> memento);
|
||||||
|
|
||||||
|
void setScrollHeightValue(rpl::producer<int> value);
|
||||||
|
|
||||||
rpl::producer<Ui::ScrollToRequest> scrollToRequests() const {
|
rpl::producer<Ui::ScrollToRequest> scrollToRequests() const {
|
||||||
return _scrollToRequests.events();
|
return _scrollToRequests.events();
|
||||||
}
|
}
|
||||||
|
@ -88,12 +91,14 @@ private:
|
||||||
object_ptr<Ui::PlainShadow> _otherTabsShadow = { nullptr };
|
object_ptr<Ui::PlainShadow> _otherTabsShadow = { nullptr };
|
||||||
base::unique_qptr<Ui::RpWidget> _searchField = nullptr;
|
base::unique_qptr<Ui::RpWidget> _searchField = nullptr;
|
||||||
object_ptr<ListWidget> _list = { nullptr };
|
object_ptr<ListWidget> _list = { nullptr };
|
||||||
|
object_ptr<EmptyWidget> _empty;
|
||||||
bool _searchEnabled = false;
|
bool _searchEnabled = false;
|
||||||
|
|
||||||
bool _inResize = false;
|
bool _inResize = false;
|
||||||
|
|
||||||
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
|
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
|
||||||
rpl::event_stream<rpl::producer<SelectedItems>> _selectedLists;
|
rpl::event_stream<rpl::producer<SelectedItems>> _selectedLists;
|
||||||
|
rpl::event_stream<rpl::producer<int>> _listTops;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -549,7 +549,6 @@ ListWidget::ListWidget(
|
||||||
, _slice(sliceKey(_universalAroundId)) {
|
, _slice(sliceKey(_universalAroundId)) {
|
||||||
setAttribute(Qt::WA_MouseTracking);
|
setAttribute(Qt::WA_MouseTracking);
|
||||||
start();
|
start();
|
||||||
refreshViewer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::start() {
|
void ListWidget::start() {
|
||||||
|
@ -574,7 +573,7 @@ void ListWidget::start() {
|
||||||
| rpl::start_with_next([this](auto item) {
|
| rpl::start_with_next([this](auto item) {
|
||||||
repaintItem(item);
|
repaintItem(item);
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
_controller->mediaSourceChanged()
|
_controller->mediaSourceQueryValue()
|
||||||
| rpl::start_with_next([this]{
|
| rpl::start_with_next([this]{
|
||||||
restart();
|
restart();
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
@ -2014,8 +2013,9 @@ int ListWidget::recountHeight() {
|
||||||
section.setTop(result);
|
section.setTop(result);
|
||||||
result += section.height();
|
result += section.height();
|
||||||
}
|
}
|
||||||
return result
|
return (result > cachedPadding.top())
|
||||||
+ cachedPadding.bottom();
|
? (result + cachedPadding.bottom())
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::mouseActionUpdate() {
|
void ListWidget::mouseActionUpdate() {
|
||||||
|
|
|
@ -87,6 +87,7 @@ Widget::Widget(
|
||||||
_inner = setInnerWidget(object_ptr<InnerWidget>(
|
_inner = setInnerWidget(object_ptr<InnerWidget>(
|
||||||
this,
|
this,
|
||||||
controller));
|
controller));
|
||||||
|
_inner->setScrollHeightValue(scrollHeightValue());
|
||||||
_inner->scrollToRequests()
|
_inner->scrollToRequests()
|
||||||
| rpl::start_with_next([this](Ui::ScrollToRequest request) {
|
| rpl::start_with_next([this](Ui::ScrollToRequest request) {
|
||||||
scrollTo(request);
|
scrollTo(request);
|
||||||
|
|
|
@ -240,6 +240,8 @@
|
||||||
<(src_loc)/info/common_groups/info_common_groups_widget.cpp
|
<(src_loc)/info/common_groups/info_common_groups_widget.cpp
|
||||||
<(src_loc)/info/common_groups/info_common_groups_widget.h
|
<(src_loc)/info/common_groups/info_common_groups_widget.h
|
||||||
<(src_loc)/info/media/info_media_buttons.h
|
<(src_loc)/info/media/info_media_buttons.h
|
||||||
|
<(src_loc)/info/media/info_media_empty_widget.cpp
|
||||||
|
<(src_loc)/info/media/info_media_empty_widget.h
|
||||||
<(src_loc)/info/media/info_media_inner_widget.cpp
|
<(src_loc)/info/media/info_media_inner_widget.cpp
|
||||||
<(src_loc)/info/media/info_media_inner_widget.h
|
<(src_loc)/info/media/info_media_inner_widget.h
|
||||||
<(src_loc)/info/media/info_media_list_widget.cpp
|
<(src_loc)/info/media/info_media_list_widget.cpp
|
||||||
|
|