Add shared media empty placeholders.

This commit is contained in:
John Preston 2017-11-14 21:22:44 +04:00
parent fafcd02e7c
commit 8dfccf55d1
29 changed files with 257 additions and 18 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -590,8 +590,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_profile_files_header" = "Files";
"lng_profile_audios#one" = "{count} voice message";
"lng_profile_audios#other" = "{count} voice messages";
"lng_profile_rounds#one" = "{count} video message";
"lng_profile_rounds#other" = "{count} video messages";
//"lng_profile_rounds#one" = "{count} video message";
//"lng_profile_rounds#other" = "{count} video messages";
"lng_profile_audios_header" = "Voice messages";
"lng_profile_shared_links#one" = "{count} shared link";
"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_audio#one" = "{count} Voice message";
"lng_media_selected_audio#other" = "{count} Voice messages";
"lng_media_selected_round#one" = "{count} Video message";
"lng_media_selected_round#other" = "{count} video messages";
//"lng_media_selected_round#one" = "{count} Video message";
//"lng_media_selected_round#other" = "{count} Video messages";
"lng_media_selected_link#one" = "{count} Shared link";
"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_channel_title" = "Manage Channel";

View File

@ -390,7 +390,7 @@ void DelayedSearchController::setQuery(
void DelayedSearchController::setQueryFast(const Query &query) {
_controller.setQuery(query);
_sourceChanges.fire({});
_currentQueryChanges.fire_copy(query.query);
}
} // namespace Api

View File

@ -162,8 +162,9 @@ public:
limitAfter);
}
rpl::producer<> sourceChanged() const {
return _sourceChanges.events();
rpl::producer<QString> currentQueryValue() const {
return _currentQueryChanges.events_starting_with(
currentQuery().query);
}
SavedState saveState() {
@ -178,7 +179,7 @@ private:
SearchController _controller;
Query _nextQuery;
base::Timer _timer;
rpl::event_stream<> _sourceChanges;
rpl::event_stream<QString> _currentQueryChanges;
};

View File

@ -548,6 +548,21 @@ managePeerButtonLabel: FlatLabel(defaultFlatLabel) {
}
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);
editPeerDeleteButton: sessionTerminateAllButton;
editPeerPhotoMargins: margins(23px, 16px, 23px, 8px);

View File

@ -150,6 +150,10 @@ rpl::producer<Section> ContentWidget::sectionRequest() const {
return rpl::never<Section>();
}
rpl::producer<int> ContentWidget::scrollHeightValue() const {
return _scroll->heightValue();
}
rpl::producer<int> ContentWidget::desiredHeightValue() const {
using namespace rpl::mappers;
return rpl::combine(

View File

@ -52,6 +52,7 @@ public:
virtual void setIsStackBottom(bool isStackBottom) {
}
rpl::producer<int> scrollHeightValue() const;
rpl::producer<int> desiredHeightValue() const override;
rpl::producer<bool> desiredShadowVisibility() const;
bool hasTopBarShadow() const;

View File

@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "info/info_controller.h"
#include <rpl/range.h>
#include <rpl/then.h>
#include "ui/search_field_controller.h"
#include "data/data_shared_media.h"
#include "info/info_content_widget.h"

View File

@ -116,8 +116,8 @@ public:
SparseIdsMergedSlice::UniversalMsgId aroundId,
int limitBefore,
int limitAfter) const;
rpl::producer<> mediaSourceChanged() const {
return _searchController->sourceChanged();
rpl::producer<QString> mediaSourceQueryValue() const {
return _searchController->currentQueryValue();
}
void saveSearchState(not_null<ContentMemento*> memento);

View File

@ -65,7 +65,7 @@ QString TopBarOverride::generateText() const {
case Type::MusicFile: return lng_media_selected_song;
case Type::Link: return lng_media_selected_link;
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()");
}();

View File

@ -46,7 +46,7 @@ inline auto MediaTextPhrase(Type type) {
case Type::MusicFile: return lng_profile_songs;
case Type::Link: return lng_profile_shared_links;
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()");
};

View File

@ -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

View File

@ -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

View File

@ -24,6 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "boxes/abstract_box.h"
#include "info/media/info_media_list_widget.h"
#include "info/media/info_media_buttons.h"
#include "info/media/info_media_empty_widget.h"
#include "info/profile/info_profile_button.h"
#include "info/profile/info_profile_icon.h"
#include "info/info_controller.h"
@ -41,7 +42,8 @@ InnerWidget::InnerWidget(
QWidget *parent,
not_null<Controller*> controller)
: RpWidget(parent)
, _controller(controller) {
, _controller(controller)
, _empty(this) {
_list = setupList();
setupOtherTypes();
}
@ -253,6 +255,12 @@ object_ptr<ListWidget> InnerWidget::setupList() {
_scrollToRequests,
result->lifetime());
_selectedLists.fire(result->selectedListValue());
_listTops.fire(result->topValue());
_empty->setType(_controller->section().mediaType());
_controller->mediaSourceQueryValue()
| rpl::start_with_next([this](const QString &query) {
_empty->setSearchQuery(query);
}, result->lifetime());
return result;
}
@ -287,6 +295,7 @@ int InnerWidget::resizeGetHeight(int newWidth) {
_searchField->resizeToWidth(newWidth);
}
_list->resizeToWidth(newWidth);
_empty->resizeToWidth(newWidth);
return recountHeight();
}
@ -308,12 +317,30 @@ int InnerWidget::recountHeight() {
_searchField->moveToLeft(0, top);
top += _searchField->heightNoMargins() - st::lineWidth;
}
auto listHeight = 0;
if (_list) {
_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;
}
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 Info

View File

@ -40,6 +40,7 @@ namespace Media {
class Memento;
class ListWidget;
class EmptyWidget;
class InnerWidget final : public Ui::RpWidget {
public:
@ -52,6 +53,8 @@ public:
void saveState(not_null<Memento*> memento);
void restoreState(not_null<Memento*> memento);
void setScrollHeightValue(rpl::producer<int> value);
rpl::producer<Ui::ScrollToRequest> scrollToRequests() const {
return _scrollToRequests.events();
}
@ -88,12 +91,14 @@ private:
object_ptr<Ui::PlainShadow> _otherTabsShadow = { nullptr };
base::unique_qptr<Ui::RpWidget> _searchField = nullptr;
object_ptr<ListWidget> _list = { nullptr };
object_ptr<EmptyWidget> _empty;
bool _searchEnabled = false;
bool _inResize = false;
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
rpl::event_stream<rpl::producer<SelectedItems>> _selectedLists;
rpl::event_stream<rpl::producer<int>> _listTops;
};

View File

@ -549,7 +549,6 @@ ListWidget::ListWidget(
, _slice(sliceKey(_universalAroundId)) {
setAttribute(Qt::WA_MouseTracking);
start();
refreshViewer();
}
void ListWidget::start() {
@ -574,7 +573,7 @@ void ListWidget::start() {
| rpl::start_with_next([this](auto item) {
repaintItem(item);
}, lifetime());
_controller->mediaSourceChanged()
_controller->mediaSourceQueryValue()
| rpl::start_with_next([this]{
restart();
}, lifetime());
@ -2014,8 +2013,9 @@ int ListWidget::recountHeight() {
section.setTop(result);
result += section.height();
}
return result
+ cachedPadding.bottom();
return (result > cachedPadding.top())
? (result + cachedPadding.bottom())
: 0;
}
void ListWidget::mouseActionUpdate() {

View File

@ -87,6 +87,7 @@ Widget::Widget(
_inner = setInnerWidget(object_ptr<InnerWidget>(
this,
controller));
_inner->setScrollHeightValue(scrollHeightValue());
_inner->scrollToRequests()
| rpl::start_with_next([this](Ui::ScrollToRequest request) {
scrollTo(request);

View File

@ -240,6 +240,8 @@
<(src_loc)/info/common_groups/info_common_groups_widget.cpp
<(src_loc)/info/common_groups/info_common_groups_widget.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.h
<(src_loc)/info/media/info_media_list_widget.cpp