1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4 
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #pragma once
9 
10 #include "base/weak_ptr.h"
11 #include "base/timer.h"
12 #include "base/flags.h"
13 #include "base/object_ptr.h"
14 #include "calls/group/calls_group_call.h"
15 #include "calls/group/calls_group_common.h"
16 #include "calls/group/calls_choose_join_as.h"
17 #include "calls/group/ui/desktop_capture_choose_source.h"
18 #include "ui/effects/animations.h"
19 #include "ui/gl/gl_window.h"
20 #include "ui/rp_widget.h"
21 
22 class Image;
23 
24 namespace Data {
25 class PhotoMedia;
26 class CloudImageView;
27 class GroupCall;
28 } // namespace Data
29 
30 namespace Ui {
31 class BoxContent;
32 enum class LayerOption;
33 using LayerOptions = base::flags<LayerOption>;
34 class AbstractButton;
35 class ImportantTooltip;
36 class DropdownMenu;
37 class CallButton;
38 class CallMuteButton;
39 class IconButton;
40 class FlatLabel;
41 class RpWidget;
42 template <typename Widget>
43 class FadeWrap;
44 template <typename Widget>
45 class PaddingWrap;
46 class ScrollArea;
47 class GenericBox;
48 class LayerManager;
49 class GroupCallScheduledLeft;
50 namespace Toast {
51 class Instance;
52 } // namespace Toast
53 namespace Platform {
54 class TitleControls;
55 } // namespace Platform
56 } // namespace Ui
57 
58 namespace style {
59 struct CallSignalBars;
60 struct CallBodyLayout;
61 } // namespace style
62 
63 namespace Calls::Group {
64 
65 class Toasts;
66 class Members;
67 class Viewport;
68 enum class PanelMode;
69 enum class StickedTooltip;
70 class MicLevelTester;
71 
72 class Panel final : private Ui::DesktopCapture::ChooseSourceDelegate {
73 public:
74 	Panel(not_null<GroupCall*> call);
75 	~Panel();
76 
77 	[[nodiscard]] not_null<GroupCall*> call() const;
78 	[[nodiscard]] bool isActive() const;
79 
80 	void showToast(TextWithEntities &&text, crl::time duration = 0);
81 	void showBox(object_ptr<Ui::BoxContent> box);
82 	void showBox(
83 		object_ptr<Ui::BoxContent> box,
84 		Ui::LayerOptions options,
85 		anim::type animated = anim::type::normal);
86 
87 	void minimize();
88 	void close();
89 	void showAndActivate();
90 	void closeBeforeDestroy();
91 
92 	rpl::lifetime &lifetime();
93 
94 private:
95 	using State = GroupCall::State;
96 	struct ControlsBackgroundNarrow;
97 
98 	enum class NiceTooltipType {
99 		Normal,
100 		Sticked,
101 	};
102 	enum class StickedTooltipHide {
103 		Unavailable,
104 		Activated,
105 		Discarded,
106 	};
107 
108 	[[nodiscard]] not_null<Ui::RpWindow*> window() const;
109 	[[nodiscard]] not_null<Ui::RpWidget*> widget() const;
110 
111 	[[nodiscard]] PanelMode mode() const;
112 
113 	void paint(QRect clip);
114 
115 	void initWindow();
116 	void initWidget();
117 	void initControls();
118 	void initShareAction();
119 	void initLayout();
120 	void initGeometry();
121 	void setupScheduledLabels(rpl::producer<TimeId> date);
122 	void setupMembers();
123 	void setupVideo(not_null<Viewport*> viewport);
124 	void setupRealMuteButtonState(not_null<Data::GroupCall*> real);
125 
126 	bool handleClose();
127 	void startScheduledNow();
128 	void trackControls(bool track);
129 	void raiseControls();
130 	void enlargeVideo();
131 	void minimizeVideo();
132 
133 	void trackControl(Ui::RpWidget *widget, rpl::lifetime &lifetime);
134 	void trackControlOver(not_null<Ui::RpWidget*> control, bool over);
135 	void showNiceTooltip(
136 		not_null<Ui::RpWidget*> control,
137 		NiceTooltipType type = NiceTooltipType::Normal);
138 	void showStickedTooltip();
139 	void hideStickedTooltip(StickedTooltipHide hide);
140 	void hideStickedTooltip(StickedTooltip type, StickedTooltipHide hide);
141 	void hideNiceTooltip();
142 
143 	bool updateMode();
144 	void updateControlsGeometry();
145 	void updateButtonsGeometry();
146 	void updateTooltipGeometry();
147 	void updateButtonsStyles();
148 	void updateMembersGeometry();
149 	void refreshControlsBackground();
150 	void setupControlsBackgroundWide();
151 	void setupControlsBackgroundNarrow();
152 	void showControls();
153 	void refreshLeftButton();
154 	void refreshVideoButtons(
155 		std::optional<bool> overrideWideMode = std::nullopt);
156 	void refreshTopButton();
157 	void toggleWideControls(bool shown);
158 	void updateWideControlsVisibility();
159 	[[nodiscard]] bool videoButtonInNarrowMode() const;
160 
161 	void endCall();
162 
163 	void showMainMenu();
164 	void chooseJoinAs();
165 	void chooseShareScreenSource();
166 	void screenSharingPrivacyRequest();
167 	void addMembers();
168 	void kickParticipant(not_null<PeerData*> participantPeer);
169 	void kickParticipantSure(not_null<PeerData*> participantPeer);
170 	[[nodiscard]] QRect computeTitleRect() const;
171 	void refreshTitle();
172 	void refreshTitleGeometry();
173 	void setupRealCallViewers();
174 	void subscribeToChanges(not_null<Data::GroupCall*> real);
175 
176 	void migrate(not_null<ChannelData*> channel);
177 	void subscribeToPeerChanges();
178 
179 	QWidget *chooseSourceParent() override;
180 	QString chooseSourceActiveDeviceId() override;
181 	bool chooseSourceActiveWithAudio() override;
182 	bool chooseSourceWithAudioSupported() override;
183 	rpl::lifetime &chooseSourceInstanceLifetime() override;
184 	void chooseSourceAccepted(
185 		const QString &deviceId,
186 		bool withAudio) override;
187 	void chooseSourceStop() override;
188 
189 	const not_null<GroupCall*> _call;
190 	not_null<PeerData*> _peer;
191 
192 	Ui::GL::Window _window;
193 	const std::unique_ptr<Ui::LayerManager> _layerBg;
194 	rpl::variable<PanelMode> _mode;
195 
196 #ifndef Q_OS_MAC
197 	std::unique_ptr<Ui::Platform::TitleControls> _controls;
198 #endif // !Q_OS_MAC
199 
200 	rpl::lifetime _callLifetime;
201 
202 	object_ptr<Ui::FlatLabel> _title = { nullptr };
203 	object_ptr<Ui::FlatLabel> _subtitle = { nullptr };
204 	object_ptr<Ui::AbstractButton> _recordingMark = { nullptr };
205 	object_ptr<Ui::IconButton> _menuToggle = { nullptr };
206 	object_ptr<Ui::DropdownMenu> _menu = { nullptr };
207 	rpl::variable<bool> _wideMenuShown = false;
208 	object_ptr<Ui::AbstractButton> _joinAsToggle = { nullptr };
209 	object_ptr<Members> _members = { nullptr };
210 	std::unique_ptr<Viewport> _viewport;
211 	rpl::lifetime _trackControlsLifetime;
212 	rpl::lifetime _trackControlsOverStateLifetime;
213 	rpl::lifetime _trackControlsMenuLifetime;
214 	object_ptr<Ui::FlatLabel> _startsIn = { nullptr };
215 	object_ptr<Ui::RpWidget> _countdown = { nullptr };
216 	std::shared_ptr<Ui::GroupCallScheduledLeft> _countdownData;
217 	object_ptr<Ui::FlatLabel> _startsWhen = { nullptr };
218 	ChooseJoinAsProcess _joinAsProcess;
219 	std::optional<QRect> _lastSmallGeometry;
220 	std::optional<QRect> _lastLargeGeometry;
221 	bool _lastLargeMaximized = false;
222 	bool _showWideControls = false;
223 	bool _trackControls = false;
224 	bool _wideControlsShown = false;
225 	Ui::Animations::Simple _wideControlsAnimation;
226 
227 	object_ptr<Ui::RpWidget> _controlsBackgroundWide = { nullptr };
228 	std::unique_ptr<ControlsBackgroundNarrow> _controlsBackgroundNarrow;
229 	object_ptr<Ui::CallButton> _settings = { nullptr };
230 	object_ptr<Ui::CallButton> _wideMenu = { nullptr };
231 	object_ptr<Ui::CallButton> _callShare = { nullptr };
232 	object_ptr<Ui::CallButton> _video = { nullptr };
233 	object_ptr<Ui::CallButton> _screenShare = { nullptr };
234 	std::unique_ptr<Ui::CallMuteButton> _mute;
235 	object_ptr<Ui::CallButton> _hangup;
236 	object_ptr<Ui::ImportantTooltip> _niceTooltip = { nullptr };
237 	QPointer<Ui::IconButton> _stickedTooltipClose;
238 	QPointer<Ui::RpWidget> _niceTooltipControl;
239 	StickedTooltips _stickedTooltipsShown;
240 	Fn<void()> _callShareLinkCallback;
241 
242 	const std::unique_ptr<Toasts> _toasts;
243 	base::weak_ptr<Ui::Toast::Instance> _lastToast;
244 
245 	std::unique_ptr<MicLevelTester> _micLevelTester;
246 
247 	rpl::lifetime _peerLifetime;
248 
249 };
250 
251 } // namespace Calls::Group
252