mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-09-01 15:05:56 +00:00
Show context menu for topics in new tabs.
This commit is contained in:
@@ -170,7 +170,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
"lng_group_status" = "group";
|
"lng_group_status" = "group";
|
||||||
"lng_scam_badge" = "SCAM";
|
"lng_scam_badge" = "SCAM";
|
||||||
"lng_fake_badge" = "FAKE";
|
"lng_fake_badge" = "FAKE";
|
||||||
"lng_direct_badge" = "MESSAGES";
|
"lng_direct_badge" = "DIRECT";
|
||||||
|
|
||||||
"lng_remember" = "Remember this choice";
|
"lng_remember" = "Remember this choice";
|
||||||
|
|
||||||
|
@@ -113,6 +113,7 @@ struct EntryState {
|
|||||||
Replies,
|
Replies,
|
||||||
SavedSublist,
|
SavedSublist,
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
|
SubsectionTabsMenu,
|
||||||
ShortcutMessages,
|
ShortcutMessages,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -23,13 +23,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "ui/controls/subsection_tabs_slider.h"
|
#include "ui/controls/subsection_tabs_slider.h"
|
||||||
#include "ui/effects/ripple_animation.h"
|
#include "ui/effects/ripple_animation.h"
|
||||||
|
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
|
||||||
|
#include "ui/widgets/menu/menu_add_action_callback.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/discrete_sliders.h"
|
#include "ui/widgets/discrete_sliders.h"
|
||||||
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
#include "ui/widgets/shadow.h"
|
#include "ui/widgets/shadow.h"
|
||||||
#include "ui/dynamic_image.h"
|
#include "ui/dynamic_image.h"
|
||||||
#include "ui/dynamic_thumbnails.h"
|
#include "ui/dynamic_thumbnails.h"
|
||||||
|
#include "window/window_peer_menu.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
|
|
||||||
@@ -188,6 +192,12 @@ void SubsectionTabs::setupSlider(
|
|||||||
}
|
}
|
||||||
}, slider->lifetime());
|
}, slider->lifetime());
|
||||||
|
|
||||||
|
slider->sectionContextMenu() | rpl::start_with_next([=](int index) {
|
||||||
|
if (index >= 0 && index < _slice.size()) {
|
||||||
|
showThreadContextMenu(_slice[index].thread);
|
||||||
|
}
|
||||||
|
}, slider->lifetime());
|
||||||
|
|
||||||
rpl::merge(
|
rpl::merge(
|
||||||
scroll->scrolls(),
|
scroll->scrolls(),
|
||||||
_scrollCheckRequests.events(),
|
_scrollCheckRequests.events(),
|
||||||
@@ -363,6 +373,27 @@ void SubsectionTabs::setupSlider(
|
|||||||
}, scroll->lifetime());
|
}, scroll->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SubsectionTabs::showThreadContextMenu(not_null<Data::Thread*> thread) {
|
||||||
|
_menu = nullptr;
|
||||||
|
_menu = base::make_unique_q<Ui::PopupMenu>(
|
||||||
|
_horizontal ? _horizontal : _vertical,
|
||||||
|
st::popupMenuExpandedSeparator);
|
||||||
|
|
||||||
|
const auto addAction = Ui::Menu::CreateAddActionCallback(_menu);
|
||||||
|
Window::FillDialogsEntryMenu(
|
||||||
|
_controller,
|
||||||
|
Dialogs::EntryState{
|
||||||
|
.key = Dialogs::Key{ thread },
|
||||||
|
.section = Dialogs::EntryState::Section::SubsectionTabsMenu,
|
||||||
|
},
|
||||||
|
addAction);
|
||||||
|
if (_menu->empty()) {
|
||||||
|
_menu = nullptr;
|
||||||
|
} else {
|
||||||
|
_menu->popup(QCursor::pos());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SubsectionTabs::loadMore() {
|
void SubsectionTabs::loadMore() {
|
||||||
if (const auto forum = _history->peer->forum()) {
|
if (const auto forum = _history->peer->forum()) {
|
||||||
forum->requestTopics();
|
forum->requestTopics();
|
||||||
|
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/unique_qptr.h"
|
||||||
#include "dialogs/dialogs_common.h"
|
#include "dialogs/dialogs_common.h"
|
||||||
|
|
||||||
class History;
|
class History;
|
||||||
@@ -21,6 +22,7 @@ class SessionController;
|
|||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class RpWidget;
|
class RpWidget;
|
||||||
|
class PopupMenu;
|
||||||
class ScrollArea;
|
class ScrollArea;
|
||||||
class SubsectionSlider;
|
class SubsectionSlider;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
@@ -83,10 +85,13 @@ private:
|
|||||||
not_null<Ui::ScrollArea*> scroll,
|
not_null<Ui::ScrollArea*> scroll,
|
||||||
not_null<Ui::SubsectionSlider*> slider,
|
not_null<Ui::SubsectionSlider*> slider,
|
||||||
bool vertical);
|
bool vertical);
|
||||||
|
void showThreadContextMenu(not_null<Data::Thread*> thread);
|
||||||
|
|
||||||
const not_null<Window::SessionController*> _controller;
|
const not_null<Window::SessionController*> _controller;
|
||||||
const not_null<History*> _history;
|
const not_null<History*> _history;
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
|
|
||||||
Ui::RpWidget *_horizontal = nullptr;
|
Ui::RpWidget *_horizontal = nullptr;
|
||||||
Ui::RpWidget *_vertical = nullptr;
|
Ui::RpWidget *_vertical = nullptr;
|
||||||
Ui::RpWidget *_shadow = nullptr;
|
Ui::RpWidget *_shadow = nullptr;
|
||||||
|
@@ -270,6 +270,10 @@ void SubsectionButton::setActiveShown(float64 activeShown) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SubsectionButton::contextMenuEvent(QContextMenuEvent *e) {
|
||||||
|
_delegate->buttonContextMenu(this, e);
|
||||||
|
}
|
||||||
|
|
||||||
SubsectionSlider::SubsectionSlider(not_null<QWidget*> parent, bool vertical)
|
SubsectionSlider::SubsectionSlider(not_null<QWidget*> parent, bool vertical)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _vertical(vertical)
|
, _vertical(vertical)
|
||||||
@@ -407,6 +411,10 @@ rpl::producer<int> SubsectionSlider::sectionActivated() const {
|
|||||||
return _sectionActivated.events();
|
return _sectionActivated.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<int> SubsectionSlider::sectionContextMenu() const {
|
||||||
|
return _sectionContextMenu.events();
|
||||||
|
}
|
||||||
|
|
||||||
int SubsectionSlider::lookupSectionPosition(int index) const {
|
int SubsectionSlider::lookupSectionPosition(int index) const {
|
||||||
Expects(index >= 0 && index < _tabs.size());
|
Expects(index >= 0 && index < _tabs.size());
|
||||||
|
|
||||||
@@ -472,6 +480,19 @@ float64 SubsectionSlider::buttonActive(not_null<SubsectionButton*> button) {
|
|||||||
: 0.;
|
: 0.;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SubsectionSlider::buttonContextMenu(
|
||||||
|
not_null<SubsectionButton*> button,
|
||||||
|
not_null<QContextMenuEvent*> e) {
|
||||||
|
const auto i = ranges::find(
|
||||||
|
_tabs,
|
||||||
|
button.get(),
|
||||||
|
&std::unique_ptr<SubsectionButton>::get);
|
||||||
|
Assert(i != end(_tabs));
|
||||||
|
|
||||||
|
_sectionContextMenu.fire(int(i - begin(_tabs)));
|
||||||
|
e->accept();
|
||||||
|
}
|
||||||
|
|
||||||
Text::MarkedContext SubsectionSlider::buttonContext() {
|
Text::MarkedContext SubsectionSlider::buttonContext() {
|
||||||
return _context;
|
return _context;
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,9 @@ public:
|
|||||||
virtual bool buttonPaused() = 0;
|
virtual bool buttonPaused() = 0;
|
||||||
virtual float64 buttonActive(not_null<SubsectionButton*> button) = 0;
|
virtual float64 buttonActive(not_null<SubsectionButton*> button) = 0;
|
||||||
virtual Text::MarkedContext buttonContext() = 0;
|
virtual Text::MarkedContext buttonContext() = 0;
|
||||||
|
virtual void buttonContextMenu(
|
||||||
|
not_null<SubsectionButton*> button,
|
||||||
|
not_null<QContextMenuEvent*> e) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SubsectionButton : public RippleButton {
|
class SubsectionButton : public RippleButton {
|
||||||
@@ -60,6 +63,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void dataUpdatedHook() = 0;
|
virtual void dataUpdatedHook() = 0;
|
||||||
|
|
||||||
|
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||||
|
|
||||||
const not_null<SubsectionButtonDelegate*> _delegate;
|
const not_null<SubsectionButtonDelegate*> _delegate;
|
||||||
SubsectionTab _data;
|
SubsectionTab _data;
|
||||||
float64 _activeShown = 0.;
|
float64 _activeShown = 0.;
|
||||||
@@ -79,10 +84,14 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] int sectionsCount() const;
|
[[nodiscard]] int sectionsCount() const;
|
||||||
[[nodiscard]] rpl::producer<int> sectionActivated() const;
|
[[nodiscard]] rpl::producer<int> sectionActivated() const;
|
||||||
|
[[nodiscard]] rpl::producer<int> sectionContextMenu() const;
|
||||||
[[nodiscard]] int lookupSectionPosition(int index) const;
|
[[nodiscard]] int lookupSectionPosition(int index) const;
|
||||||
|
|
||||||
bool buttonPaused() override;
|
bool buttonPaused() override;
|
||||||
float64 buttonActive(not_null<SubsectionButton*> button) override;
|
float64 buttonActive(not_null<SubsectionButton*> button) override;
|
||||||
|
void buttonContextMenu(
|
||||||
|
not_null<SubsectionButton*> button,
|
||||||
|
not_null<QContextMenuEvent*> e) override;
|
||||||
Text::MarkedContext buttonContext() override;
|
Text::MarkedContext buttonContext() override;
|
||||||
[[nodiscard]] not_null<SubsectionButton*> buttonAt(int index);
|
[[nodiscard]] not_null<SubsectionButton*> buttonAt(int index);
|
||||||
|
|
||||||
@@ -125,6 +134,7 @@ protected:
|
|||||||
bool _reorderAllowed = false;
|
bool _reorderAllowed = false;
|
||||||
|
|
||||||
rpl::event_stream<int> _sectionActivated;
|
rpl::event_stream<int> _sectionActivated;
|
||||||
|
rpl::event_stream<int> _sectionContextMenu;
|
||||||
Fn<bool()> _paused;
|
Fn<bool()> _paused;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@@ -495,6 +495,10 @@ void Filler::addToggleTopicClosed() {
|
|||||||
void Filler::addTogglePin() {
|
void Filler::addTogglePin() {
|
||||||
if ((!_sublist && !_peer) || (_topic && !_topic->canTogglePinned())) {
|
if ((!_sublist && !_peer) || (_topic && !_topic->canTogglePinned())) {
|
||||||
return;
|
return;
|
||||||
|
} else if (_request.section == Section::SubsectionTabsMenu
|
||||||
|
&& !_sublist
|
||||||
|
&& !_topic) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
const auto controller = _controller;
|
const auto controller = _controller;
|
||||||
const auto filterId = _request.filterId;
|
const auto filterId = _request.filterId;
|
||||||
@@ -602,6 +606,10 @@ void Filler::addToggleFolder() {
|
|||||||
|| !history->owner().chatsFilters().has()
|
|| !history->owner().chatsFilters().has()
|
||||||
|| !history->inChatList()) {
|
|| !history->inChatList()) {
|
||||||
return;
|
return;
|
||||||
|
} else if (_request.section == Section::SubsectionTabsMenu
|
||||||
|
&& !_sublist
|
||||||
|
&& !_topic) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
_addAction(PeerMenuCallback::Args{
|
_addAction(PeerMenuCallback::Args{
|
||||||
.text = tr::lng_filters_menu_add(tr::now),
|
.text = tr::lng_filters_menu_add(tr::now),
|
||||||
@@ -689,7 +697,9 @@ void Filler::addNewWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Filler::addToggleArchive() {
|
void Filler::addToggleArchive() {
|
||||||
if (!_peer || _topic) {
|
if (!_peer
|
||||||
|
|| _topic
|
||||||
|
|| _request.section == Section::SubsectionTabsMenu) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto peer = _peer;
|
const auto peer = _peer;
|
||||||
@@ -721,7 +731,7 @@ void Filler::addToggleArchive() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Filler::addClearHistory() {
|
void Filler::addClearHistory() {
|
||||||
if (_topic) {
|
if (_topic || _peer->isMonoforum()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto channel = _peer->asChannel();
|
const auto channel = _peer->asChannel();
|
||||||
@@ -1261,7 +1271,8 @@ void Filler::fill() {
|
|||||||
case Section::Profile: fillProfileActions(); break;
|
case Section::Profile: fillProfileActions(); break;
|
||||||
case Section::Replies: fillRepliesActions(); break;
|
case Section::Replies: fillRepliesActions(); break;
|
||||||
case Section::Scheduled: fillScheduledActions(); break;
|
case Section::Scheduled: fillScheduledActions(); break;
|
||||||
case Section::ContextMenu: fillContextMenuActions(); break;
|
case Section::ContextMenu:
|
||||||
|
case Section::SubsectionTabsMenu: fillContextMenuActions(); break;
|
||||||
default: Unexpected("_request.section in Filler::fill.");
|
default: Unexpected("_request.section in Filler::fill.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user