From a4017e930e54d65f0f6c19820de325502f1b4377 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 20 Aug 2024 16:11:11 +0200 Subject: [PATCH] Add device selectors to one-on-one calls. --- .../Resources/icons/calls/call_cancel.png | Bin 214 -> 1483 bytes .../Resources/icons/calls/call_cancel@2x.png | Bin 426 -> 1596 bytes .../Resources/icons/calls/call_cancel@3x.png | Bin 912 -> 1652 bytes .../icons/calls/mini_calls_arrow.png | Bin 0 -> 240 bytes .../icons/calls/mini_calls_arrow@2x.png | Bin 0 -> 324 bytes .../icons/calls/mini_calls_arrow@3x.png | Bin 0 -> 422 bytes Telegram/SourceFiles/calls/calls.style | 42 +++ Telegram/SourceFiles/calls/calls_call.cpp | 13 + Telegram/SourceFiles/calls/calls_call.h | 8 + Telegram/SourceFiles/calls/calls_panel.cpp | 55 ++++ Telegram/SourceFiles/calls/calls_panel.h | 11 + .../calls/ui/calls_device_menu.cpp | 250 ++++++++++++++++++ .../SourceFiles/calls/ui/calls_device_menu.h | 36 +++ Telegram/cmake/td_ui.cmake | 2 + Telegram/lib_ui | 2 +- 15 files changed, 418 insertions(+), 1 deletion(-) create mode 100644 Telegram/Resources/icons/calls/mini_calls_arrow.png create mode 100644 Telegram/Resources/icons/calls/mini_calls_arrow@2x.png create mode 100644 Telegram/Resources/icons/calls/mini_calls_arrow@3x.png create mode 100644 Telegram/SourceFiles/calls/ui/calls_device_menu.cpp create mode 100644 Telegram/SourceFiles/calls/ui/calls_device_menu.h diff --git a/Telegram/Resources/icons/calls/call_cancel.png b/Telegram/Resources/icons/calls/call_cancel.png index 607033d0fc9da3bd689b030e4b5215622bf61094..db5452f423f81c452db1975843105dda6bf5cf2e 100644 GIT binary patch literal 1483 zcmbVMONbmr7;ZxjW|NR1f-GLFbWAYBe%18sZr5y^Y^GOdB)x8SM|N{CSW{gy)9iFt zr@J;iv*5uzka!Z&i{zA`2M>~?5Mez?>-E+5 zzyH(obI)%bdtywIq^-58vmoZDvhnB!@edo@E{kbXR6U$X(&opq@rd;9nQ=+lc*n0V z^JVuSA}mm`#~M`a29ZEZ()7M=gvko!pg~)HXv?=RtjoanYTXn_ZNIt})5W#9 zI$2vGmM8Cf7EE`MAP6YOpc{0;1a)n>&x^!5JJw{-hwv3!p2-A)Wp^G_SWJPX8Vb>M z2qrBRPvD87HSr99Iy5!Cs2NbvCy_aYU=a*IS%{0hCR%Ww8wwLUTW)h6Ax%ruR85O2 zi(8suS(c_l4MIgAl%yAO+*QJ4=ZL|f35orP`z!<*BW|!&Zp%W|fek^F(}u~=Pr_qb z7e|_*>X}V_pht3Cv>JE%!abtV4h?9?6M;2yY}96)C2jUE)cN&20)%f}HL(&vy7|^C|DoFn$+yhv`nmolZooNYg zJvg5;=mB?pEmaI?yA}mT(p90nKvP^$=etWMemA5lNvvNdbenBuhpEHdiB#E z-zkrM0t$}3|BD-c-adQk)SFkgj6Hs(xZ`g72l^7)Ux3x8H#c>UGg@B1s2FF#M0wz%JZWx9U* y?4|BEpOwMK=PqBkcJ1aHzZVwQ$9J4uz9aoG{zrMKd}LeJZfmo1&W8tHIsP{tqu!wa delta 197 zcmX@jeT{K~WIY=L1H(gx88d*?Tu&Frkcif|(;c~-6?t5i?```YU&XI4wEm&`?w|`l zKSpz;%5`w7|8P+L!DKL@qg+kW;{}^gl1GQ4Vq1$u;=(BHGd<629^aI8OPO)Apl06H zyC-$rb|mb4=seSQ;mu?0Dc@T6vGSd?5&kvBO2zonR@;BiPS^#-z6#0x|GM3Izi{ diff --git a/Telegram/Resources/icons/calls/call_cancel@2x.png b/Telegram/Resources/icons/calls/call_cancel@2x.png index 611f89d36ca23e5e6585f8c2332b26aee7dda4f2..468337a51051fef56b1c22a2142aaf6a0b6f4fa6 100644 GIT binary patch literal 1596 zcmbVMX^hlV9IpzZ$SOgJ#%R)XO%S2eV>(BlGc3!@x-)?;%P{N__XBU*H`DG+`?_ss zXJ#cN9*JTUqREQ7CZZoDEFaK?gm5Ir#27R&N)S9FvVKs4pwYx5@pX;{3`(TQJNn-5 z{r>lV$KXJJ*W!B@Qxw&e&7^Z=&G_S%8_9fT*8@w*a;u#gbt&q$JN{wTwKvfJ%myWG);&#?XeAWQHROuh=Q18<{Bw zZJrv)t5aoF)|j3(bfOLjfr&gw*UgIMf_jo^@&dB=k2!{JLcDU4>GcKDBg!D1!VaS4 zkie=uFVZnN1fwt-mZPg_kryS74|9UZ@-ZOAff%OSA49}BS`p;ZkF-9|%GujThD%#CAY{cb|i>r=``X-5*-M%$8NI3|4*vVsD=|pOLrI2&jRZ_)MKRCEfgq5`t>Q(%^DU@?HKW)Fpc2c+SyAwz zkth(NS3pV9XwZY#1ZyfNV#kEUV#9_!Z~p1jraJiB_Xs5}VOPdsi{&W*Pvf`stlyR6njrW7@~Yb$g&iThkFC{f}_B zU@k6tHRzz;67klx^NAzcbABbZ4B`H1WApB^s_no@EAY2L6CyuB8$%Z9T@Gnd#-)4h59tMjj{zx_#m$-+_lrrGKHW|r^G9J%A2wd?L$+O=}o#UD;Q`~2&P_y64R zNwX)C>3Gk_bLMlxQ(G5BzWbth^0&X@!jjafDw2ovbMDTCYc3R5)W=@PJ!BtPwrcGA zksseJL=$IM41f9S(3WRTpIF_U|7KE0k8c?(KKtv#D!L%YvZi_@py zUcYz$zK7?)#A8aF%r2fjJAZO~;`3c!CtljQPkT@5-}LkR8;!%KwyiB6%^61*l(*06 z+x79;o3-8Y%#k-g`rSM*{ORb+AIu&q9po?mv2n+vPN4byxc}QrFaE-Pw#Prp_6?+G I*KK{`Z_~RHv;Y7A literal 426 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2U@Y`>aSW-L^Y-?^u0sYQZV%7o ze2!6kFTLw+_SAPqF^(ERpSNFK7XDnOK)EQ{zUM}Ry<&^hi_HBOwlI6JOyE!ubWmz= zVd!KKVpL(mE3k{XSL~^QH#vI=gA+-c{*#Nj;@9$FqDdhZLV{zwWJhH!Z^K za@zdA{|?{eo)YwG(_#g=n$8;{!LZ8V)zIq&DB zyoWbFzu!^*J7a;E-)qzVkJ=xJ$+Ua?E10AB^GIRK6Y=Ammv(a7$nAW0G*hwm=)~8b zF8tFtCw1w%%&q$q+Y&2IPun1Awp!Tl>Hj39yf9Z{{0RAMC{$yhHtJa z$&{TEHUSA~9#KYV=qYK2BSb_xONJ=rp-rY?R?(x>;_;IdsmM`kvtM8ZBL;Iy|CkAf z#|DzpSY8UtROd!AQUX|k25pfnX{v64Qk1Ib1$gfqGZa~Y*!d{c#w+Ttz2vIH{7)I`i!(Znod3_VMcjW~iBQjv)bWAD5bF9ZQ3bjucX2`1uE3X}FI ziVP%wFc^|qo=%5YNXyVC(xEUPq(hldI^*^Eq;y8E%g2#4>ZGaF zV;4mec4cw2Ze33d_MUM%u}XybC&$X&4P9G@<5A#j8$$^HG{zXz@$543keYj{=>$PE zbtK|l$`njElKKwNLiM#0f;fyO6NQ>vTj&F}&9J%m{d#5XKcwg+q47zmQj(FPAbG^S_ z=$xFp1SWlIpZoZ_)QhukKeRq_ecCng*dV*A`?R{e`G|Yv7lq`({RhUI-76!94vf$2 zXvu8o*t0OT|FwxDtKJv~e;i!Mzw;>h;I-k@(_QX-%UtS_?!K4a`mFEt^oH5q-wMqy z%;)kW6T)P(8r;aeyM1xyr}+oAy+a*( zAJ~4`{#tdPlk=n4;v?RR{O>8Rxc{h|-)`+qiqT^ySN!=ZAUkoKh??tNB?{ zqVl6Ze`+$A+26cSkweuP(iF|9<(+n>Qz4zYy`%W1(fu zG5urP#g|1yM@wtIeefVbCsS(iM$LKi<|UPunz~0;as{tQ%!=tceE2ZG=jDx3lOKKj zXeia|wr4x_9_xbPoEsQaU)Jg1m`t<3JojX0dcI?>k!kz1B zfZnag$2o&_bajt@{aPC2!POhe_bAz&D_BQQuTS;ut5>V+r~TTo@etc3l?7VUr%&Iw zVS~f8qhiY@G-#bSkqusb^~ENp{jLg1zXG4`c+d3f=F-b^{5uV z{OC2#*tE}tRmkk!(ffgy-o1NQ^RZlL)3MmNpKal9K2N{;w(R&M(+(}}84FA|)~J7% zTz&Ta(%xH243VYhijzXW6;}xRsRgDUpR#>ts?a?TE@87*yz94TrJE_%OE9Ue`O(xb z{a4p_t7*GT_2jp!UFsL`0|mFXT*@)~e|n{-Y1G=VZ>ul;vp;9>N0*7pX%vy}Cu(#( aQt#E4+I&yTc@i+EF?hQAxvXb4y$E4b&+ z>yk44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSVF5FO4N|zKE$K6mTIcEF7~;YE zc9J3AVFdve-Tw_@-)oe3?H{BE{3=}dRQBYnb53IFb3Ar>=;d*rmN~snvNF=g?EuG} zo&(Ka*7u*X-0x9w@x8{<0xSECSKdfmnreOSrGL==u0ytMUwT`_=JL%vcjw}w3x?j; zU+(bxzg2nZ6+vd!hBN<8G>Yzopr0IjxfS^xk5 literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/calls/mini_calls_arrow@3x.png b/Telegram/Resources/icons/calls/mini_calls_arrow@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..87dd6a9cb411c0ce82d6b2868eb1434cba414a94 GIT binary patch literal 422 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1SD@HB~Jt)g!KQTYJhje{O9;u7a=eE+BLkmG?Q zCZ7gQ14gw2EbrzXIQ;kXB8^j0e#!J@N{3Yj@Sswmx3#N3dT;o$xhC^w@Lim9F2%7}DOjSdG*(})?~bPBRhztjk3&NbUemd uniqueId) { _videoOutgoing->setState(Webrtc::VideoState::Active); } +auto Call::playbackDeviceIdValue() const +-> rpl::producer { + return _playbackDeviceId.value(); +} + +rpl::producer Call::captureDeviceIdValue() const { + return _captureDeviceId.value(); +} + +rpl::producer Call::cameraDeviceIdValue() const { + return _cameraDeviceId.value(); +} + void Call::finish(FinishType type, const MTPPhoneCallDiscardReason &reason) { Expects(type != FinishType::None); diff --git a/Telegram/SourceFiles/calls/calls_call.h b/Telegram/SourceFiles/calls/calls_call.h index 0a99c8067..1d01d6d5f 100644 --- a/Telegram/SourceFiles/calls/calls_call.h +++ b/Telegram/SourceFiles/calls/calls_call.h @@ -31,6 +31,7 @@ enum class AudioState; namespace Webrtc { enum class VideoState; class VideoTrack; +struct DeviceResolvedId; } // namespace Webrtc namespace Calls { @@ -220,6 +221,13 @@ public: void toggleCameraSharing(bool enabled); void toggleScreenSharing(std::optional uniqueId); + [[nodiscard]] auto playbackDeviceIdValue() const + -> rpl::producer; + [[nodiscard]] auto captureDeviceIdValue() const + -> rpl::producer; + [[nodiscard]] auto cameraDeviceIdValue() const + -> rpl::producer; + [[nodiscard]] rpl::lifetime &lifetime() { return _lifetime; } diff --git a/Telegram/SourceFiles/calls/calls_panel.cpp b/Telegram/SourceFiles/calls/calls_panel.cpp index 1a442cfc2..c3f94e0ec 100644 --- a/Telegram/SourceFiles/calls/calls_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_panel.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_cloud_file.h" #include "data/data_changes.h" #include "calls/group/calls_group_common.h" +#include "calls/ui/calls_device_menu.h" #include "calls/calls_emoji_fingerprint.h" #include "calls/calls_signal_bars.h" #include "calls/calls_userpic.h" @@ -24,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/call_button.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" +#include "ui/widgets/popup_menu.h" #include "ui/widgets/shadow.h" #include "ui/widgets/rp_window.h" #include "ui/layers/layer_manager.h" @@ -130,6 +132,7 @@ Panel::Panel(not_null call) initWidget(); initControls(); initLayout(); + initMediaDeviceToggles(); showAndActivate(); } @@ -736,6 +739,58 @@ void Panel::initGeometry() { updateControlsGeometry(); } +void Panel::initMediaDeviceToggles() { + _cameraDeviceToggle = _camera->addCornerButton( + st::callCornerButton, + &st::callCornerButtonInactive); + _audioDeviceToggle = _mute->entity()->addCornerButton( + st::callCornerButton, + &st::callCornerButtonInactive); + + _cameraDeviceToggle->setClickedCallback([=] { + showDevicesMenu(_cameraDeviceToggle, { + { Webrtc::DeviceType::Camera, _call->cameraDeviceIdValue() }, + }); + }); + _audioDeviceToggle->setClickedCallback([=] { + showDevicesMenu(_audioDeviceToggle, { + { Webrtc::DeviceType::Playback, _call->playbackDeviceIdValue() }, + { Webrtc::DeviceType::Capture, _call->captureDeviceIdValue() }, + }); + }); +} + +void Panel::showDevicesMenu( + not_null button, + std::vector types) { + if (!_call || _devicesMenu) { + return; + } + const auto chosen = [=](Webrtc::DeviceType type, QString id) { + switch (type) { + case Webrtc::DeviceType::Playback: + Core::App().settings().setCallPlaybackDeviceId(id); + break; + case Webrtc::DeviceType::Capture: + Core::App().settings().setCallCaptureDeviceId(id); + break; + case Webrtc::DeviceType::Camera: + Core::App().settings().setCameraDeviceId(id); + break; + } + Core::App().saveSettingsDelayed(); + }; + _devicesMenu = MakeDeviceSelectionMenu( + widget(), + &Core::App().mediaDevices(), + std::move(types), + chosen); + _devicesMenu->setForcedVerticalOrigin( + Ui::PopupMenu::VerticalOrigin::Bottom); + _devicesMenu->popup(button->mapToGlobal(QPoint()) + - QPoint(st::callDeviceSelectionMenu.menu.widthMin / 2, 0)); +} + void Panel::refreshOutgoingPreviewInBody(State state) { const auto inBody = (state != State::Established) && (_call->videoOutgoing()->state() != Webrtc::VideoState::Inactive) diff --git a/Telegram/SourceFiles/calls/calls_panel.h b/Telegram/SourceFiles/calls/calls_panel.h index 11c6dceae..e53045a44 100644 --- a/Telegram/SourceFiles/calls/calls_panel.h +++ b/Telegram/SourceFiles/calls/calls_panel.h @@ -37,6 +37,7 @@ class FadeWrap; template class PaddingWrap; class RpWindow; +class PopupMenu; namespace GL { enum class Backend; } // namespace GL @@ -55,6 +56,7 @@ namespace Calls { class Userpic; class SignalBars; class VideoBubble; +struct DeviceSelection; class Panel final : private Group::Ui::DesktopCapture::ChooseSourceDelegate { public: @@ -104,6 +106,7 @@ private: void initControls(); void reinitWithCall(Call *call); void initLayout(); + void initMediaDeviceToggles(); void initGeometry(); [[nodiscard]] bool handleClose() const; @@ -126,6 +129,10 @@ private: void showRemoteLowBattery(); void refreshAnswerHangupRedialLabel(); + void showDevicesMenu( + not_null button, + std::vector types); + [[nodiscard]] QRect incomingFrameGeometry() const; [[nodiscard]] QRect outgoingFrameGeometry() const; @@ -156,8 +163,10 @@ private: Ui::Animations::Simple _hangupShownProgress; object_ptr> _screencast; object_ptr _camera; + Ui::CallButton *_cameraDeviceToggle = nullptr; base::unique_qptr _startVideo; object_ptr> _mute; + Ui::CallButton *_audioDeviceToggle = nullptr; object_ptr _name; object_ptr _status; object_ptr _fingerprint = { nullptr }; @@ -170,6 +179,8 @@ private: int _bodyTop = 0; int _buttonsTop = 0; + base::unique_qptr _devicesMenu; + base::Timer _updateDurationTimer; base::Timer _updateOuterRippleTimer; diff --git a/Telegram/SourceFiles/calls/ui/calls_device_menu.cpp b/Telegram/SourceFiles/calls/ui/calls_device_menu.cpp new file mode 100644 index 000000000..1db1941c0 --- /dev/null +++ b/Telegram/SourceFiles/calls/ui/calls_device_menu.cpp @@ -0,0 +1,250 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "calls/ui/calls_device_menu.h" + +#include "lang/lang_keys.h" +#include "ui/widgets/menu/menu_item_base.h" +#include "ui/widgets/checkbox.h" +#include "ui/widgets/labels.h" +#include "ui/widgets/popup_menu.h" +#include "ui/widgets/scroll_area.h" +#include "ui/wrap/vertical_layout.h" +#include "webrtc/webrtc_device_common.h" +#include "webrtc/webrtc_environment.h" +#include "styles/style_calls.h" +#include "styles/style_layers.h" + +namespace Calls { +namespace { + +class Subsection final : public Ui::Menu::ItemBase { +public: + Subsection( + not_null parent, + const style::Menu &st, + const QString &text); + + not_null action() const override; + bool isEnabled() const override; + +private: + int contentHeight() const override; + + const style::Menu &_st; + const base::unique_qptr _text; + const not_null _dummyAction; + +}; + +class Selector final : public Ui::Menu::ItemBase { +public: + Selector( + not_null parent, + const style::Menu &st, + rpl::producer> devices, + rpl::producer chosen, + Fn selected); + + not_null action() const override; + bool isEnabled() const override; + +private: + int contentHeight() const override; + [[nodiscard]] int registerId(const QString &id); + + const base::unique_qptr _scroll; + const not_null _list; + const not_null _dummyAction; + + base::flat_map _ids; + +}; + +Subsection::Subsection( + not_null parent, + const style::Menu &st, + const QString &text) +: Ui::Menu::ItemBase(parent, st) +, _st(st) +, _text(base::make_unique_q( + this, + text, + st::callDeviceSelectionLabel)) +, _dummyAction(new QAction(parent)) { + setPointerCursor(false); + + initResizeHook(parent->sizeValue()); + + _text->resizeToWidth(st::callDeviceSelectionLabel.minWidth); + _text->moveToLeft(st.itemPadding.left(), st.itemPadding.top()); +} + +not_null Subsection::action() const { + return _dummyAction; +} + +bool Subsection::isEnabled() const { + return false; +} + +int Subsection::contentHeight() const { + return _st.itemPadding.top() + + _text->height() + + _st.itemPadding.bottom(); +} + +Selector::Selector( + not_null parent, + const style::Menu &st, + rpl::producer> devices, + rpl::producer chosen, + Fn selected) +: Ui::Menu::ItemBase(parent, st) +, _scroll(base::make_unique_q(this)) +, _list(_scroll->setOwnedWidget(object_ptr(this))) +, _dummyAction(new QAction(parent)) { + setPointerCursor(false); + + initResizeHook(parent->sizeValue()); + + const auto padding = st.itemPadding; + const auto group = std::make_shared(); + std::move( + chosen + ) | rpl::start_with_next([=](Webrtc::DeviceResolvedId id) { + const auto value = id.isDefault() ? 0 : registerId(id.value); + if (!group->hasValue() || group->current() != value) { + group->setValue(value); + } + }, lifetime()); + + group->setChangedCallback([=](int value) { + if (value == 0) { + selected({}); + } else { + for (const auto &[id, index] : _ids) { + if (index == value) { + selected(id); + break; + } + } + } + }); + + std::move( + devices + ) | rpl::start_with_next([=](const std::vector &v) { + while (_list->count()) { + delete _list->widgetAt(0); + } + _list->add( + object_ptr( + _list.get(), + group, + 0, + tr::lng_settings_call_device_default(tr::now), + st::groupCallCheckbox, + st::groupCallRadio), + padding); + for (const auto &device : v) { + if (device.inactive) { + continue; + } + _list->add( + object_ptr( + _list.get(), + group, + registerId(device.id), + device.name, + st::groupCallCheckbox, + st::groupCallRadio), + padding); + } + resize(width(), contentHeight()); + }, lifetime()); +} + +not_null Selector::action() const { + return _dummyAction; +} + +bool Selector::isEnabled() const { + return false; +} + +int Selector::contentHeight() const { + _list->resizeToWidth(width()); + if (_list->count() <= 3) { + _scroll->resize(width(), _list->height()); + } else { + _scroll->resize( + width(), + 3.5 * st::defaultRadio.diameter); + } + return _scroll->height(); +} + +int Selector::registerId(const QString &id) { + auto &result = _ids[id]; + if (!result) { + result = int(_ids.size()); + } + return result; +} + +void AddDeviceSelection( + not_null menu, + not_null environment, + DeviceSelection type, + Fn selected) { + const auto title = [&] { + switch (type.type) { + case Webrtc::DeviceType::Camera: + return tr::lng_settings_call_camera(tr::now); + case Webrtc::DeviceType::Playback: + return tr::lng_settings_call_section_output(tr::now); + case Webrtc::DeviceType::Capture: + return tr::lng_settings_call_section_input(tr::now); + } + Unexpected("Type in AddDeviceSelection."); + }(); + menu->addAction( + base::make_unique_q(menu, menu->st().menu, title)); + menu->addAction( + base::make_unique_q( + menu, + menu->st().menu, + environment->devicesValue(type.type), + std::move(type.chosen), + selected)); +} + +} // namespace + +base::unique_qptr MakeDeviceSelectionMenu( + not_null parent, + not_null environment, + std::vector types, + Fn choose) { + auto result = base::make_unique_q( + parent, + st::callDeviceSelectionMenu); + const auto raw = result.get(); + for (auto type : types) { + if (!raw->empty()) { + raw->addSeparator(); + } + const auto selected = [=, type = type.type](QString id) { + choose(type, id); + }; + AddDeviceSelection(raw, environment, std::move(type), selected); + } + return result; +} + +} // namespace Calls diff --git a/Telegram/SourceFiles/calls/ui/calls_device_menu.h b/Telegram/SourceFiles/calls/ui/calls_device_menu.h new file mode 100644 index 000000000..bff2fcc42 --- /dev/null +++ b/Telegram/SourceFiles/calls/ui/calls_device_menu.h @@ -0,0 +1,36 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "base/unique_qptr.h" + +namespace Webrtc { +class Environment; +struct DeviceResolvedId; +enum class DeviceType : uchar; +} // namespace Webrtc + +namespace Ui { +class RpWidget; +class PopupMenu; +} // namespace Ui + +namespace Calls { + +struct DeviceSelection { + Webrtc::DeviceType type; + rpl::producer chosen; +}; + +[[nodiscard]] base::unique_qptr MakeDeviceSelectionMenu( + not_null parent, + not_null environment, + std::vector types, + Fn choose); + +} // namespace Calls diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index ca583b017..8ec670702 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -64,6 +64,8 @@ PRIVATE calls/group/ui/calls_group_scheduled_labels.h calls/group/ui/desktop_capture_choose_source.cpp calls/group/ui/desktop_capture_choose_source.h + calls/ui/calls_device_menu.cpp + calls/ui/calls_device_menu.h chat_helpers/field_characters_count_manager.cpp chat_helpers/field_characters_count_manager.h diff --git a/Telegram/lib_ui b/Telegram/lib_ui index fc5386f1f..47ec1b045 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit fc5386f1fd4a17fafa88f1bca544e92c4c0ddf99 +Subproject commit 47ec1b0455ac1f2faab68a4c859baab7eef9e136