Add shared media empty placeholders.
BIN
Telegram/Resources/icons/info_media_audio_empty.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
Telegram/Resources/icons/info_media_audio_empty@2x.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
Telegram/Resources/icons/info_media_file_empty.png
Normal file
After Width: | Height: | Size: 952 B |
BIN
Telegram/Resources/icons/info_media_file_empty@2x.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
Telegram/Resources/icons/info_media_link_empty.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Telegram/Resources/icons/info_media_link_empty@2x.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
Telegram/Resources/icons/info_media_photo_empty.png
Normal file
After Width: | Height: | Size: 894 B |
BIN
Telegram/Resources/icons/info_media_photo_empty@2x.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
Telegram/Resources/icons/info_media_video_empty.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
Telegram/Resources/icons/info_media_video_empty@2x.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Telegram/Resources/icons/info_media_voice_empty.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Telegram/Resources/icons/info_media_voice_empty@2x.png
Normal file
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_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";
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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()");
|
||||
}();
|
||||
|
@ -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()");
|
||||
};
|
||||
|
117
Telegram/SourceFiles/info/media/info_media_empty_widget.cpp
Normal 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
|
55
Telegram/SourceFiles/info/media/info_media_empty_widget.h
Normal 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
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|