diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 68a98cebf..94cd8ad64 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1811,6 +1811,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_call_microphone_off" = "{user}'s microphone is off"; +"lng_group_call_title" = "Voice Chat"; +"lng_group_call_active" = "speaking"; +"lng_group_call_inactive" = "listening"; +"lng_group_call_settings" = "Settings"; +"lng_group_call_unmute" = "Unmute"; +"lng_group_call_you_are_live" = "You are Live"; +"lng_group_call_connecting" = "Connecting..."; +"lng_group_call_leave" = "Leave"; +"lng_group_call_leave_title" = "Leave voice chat"; +"lng_group_call_leave_sure" = "Are you sure you want to leave this voice chat?"; +"lng_group_call_also_end" = "End voice chat"; +"lng_group_call_settings_title" = "Settings"; +"lng_group_call_speakers" = "Speakers"; +"lng_group_call_microphone" = "Microphone"; +"lng_group_call_share" = "Share Invite Link"; +"lng_group_call_end" = "End Voice Chat"; +"lng_group_call_join" = "Join"; + "lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages."; "lng_player_message_today" = "Today at {time}"; diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index ad0a7aeea..8ee01a845 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -455,6 +455,7 @@ groupCallHeaderLabel: FlatLabel(defaultFlatLabel) { } } groupCallAddButtonPosition: point(10px, 7px); +groupCallMembersWidthMax: 360px; groupCallInactiveButton: IconButton { width: 36px; diff --git a/Telegram/SourceFiles/calls/calls_group_members.cpp b/Telegram/SourceFiles/calls/calls_group_members.cpp index f522dcd64..39278f799 100644 --- a/Telegram/SourceFiles/calls/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/calls_group_members.cpp @@ -142,10 +142,10 @@ void Row::refreshStatus() { setCustomStatus([&] { switch (_state) { case State::Inactive: - case State::Muted: return "listening"; - case State::Active: return "speaking"; + case State::Muted: return tr::lng_group_call_inactive(tr::now); + case State::Active: return tr::lng_group_call_active(tr::now); } - return ""; + Unexpected("State in Row::refreshStatus."); }()); } @@ -510,11 +510,11 @@ std::vector> GroupMembers::peerListCollectSelectedRows() { } void GroupMembers::peerListAddSelectedPeerInBunch(not_null peer) { - Unexpected("Item selection in Info::Profile::Members."); + Unexpected("Item selection in Calls::GroupMembers."); } void GroupMembers::peerListAddSelectedRowInBunch(not_null row) { - Unexpected("Item selection in Info::Profile::Members."); + Unexpected("Item selection in Calls::GroupMembers."); } void GroupMembers::peerListFinishSelectedRowsBunch() { diff --git a/Telegram/SourceFiles/calls/calls_group_panel.cpp b/Telegram/SourceFiles/calls/calls_group_panel.cpp index 167173a63..fbedf2e0f 100644 --- a/Telegram/SourceFiles/calls/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_group_panel.cpp @@ -249,8 +249,10 @@ void GroupPanel::initWindow() { _window->setAttribute(Qt::WA_NoSystemBackground); _window->setWindowIcon( QIcon(QPixmap::fromImage(Image::Empty()->original(), Qt::ColorOnly))); - _window->setTitle(u" "_q); _window->setTitleStyle(st::callTitle); + _window->setTitle(computeTitleRect() + ? u" "_q + : tr::lng_group_call_title(tr::now)); base::install_event_filter(_window.get(), [=](not_null e) { if (e->type() == QEvent::Close && handleClose()) { @@ -366,22 +368,43 @@ void GroupPanel::initGeometry() { updateControlsGeometry(); } +int GroupPanel::computeMembersListTop() const { +#ifdef Q_OS_WIN + return st::callTitleButton.height + st::groupCallMembersMargin.top() / 2; +#elif defined Q_OS_MAC // Q_OS_WIN + return st::groupCallMembersMargin.top() * 2; +#else // Q_OS_WIN || Q_OS_MAC + return st::groupCallMembersMargin.top(); +#endif // Q_OS_WIN || Q_OS_MAC +} + +std::optional GroupPanel::computeTitleRect() const { +#ifdef Q_OS_WIN + const auto controls = _controls->geometry(); + return QRect(0, 0, controls.x(), controls.height()); +#else // Q_OS_WIN + return std::nullopt; +#endif // Q_OS_WIN +} + void GroupPanel::updateControlsGeometry() { if (widget()->size().isEmpty()) { return; } const auto desiredHeight = _members->desiredHeight(); - const auto membersWidth = widget()->width() + const auto membersWidthAvailable = widget()->width() - st::groupCallMembersMargin.left() - st::groupCallMembersMargin.right(); + const auto membersWidthMin = st::groupCallWidth + - st::groupCallMembersMargin.left() + - st::groupCallMembersMargin.right(); + const auto membersWidth = std::clamp( + membersWidthAvailable, + membersWidthMin, + st::groupCallMembersWidthMax); const auto muteTop = widget()->height() - 2 * _mute->height(); const auto buttonsTop = muteTop; -#ifdef Q_OS_WIN - const auto membersTop = st::callTitleButton.height - + st::groupCallMembersMargin.top() / 2; -#else // Q_OS_WIN - const auto membersTop = st::groupCallMembersMargin.top(); -#endif // Q_OS_WIN + const auto membersTop = computeMembersListTop(); const auto availableHeight = buttonsTop - membersTop - st::groupCallMembersMargin.bottom(); @@ -393,6 +416,39 @@ void GroupPanel::updateControlsGeometry() { _mute->move((widget()->width() - _mute->width()) / 2, muteTop); _settings->moveToLeft(_settings->width(), buttonsTop); _hangup->moveToRight(_settings->width(), buttonsTop); + refreshTitle(); +} + +void GroupPanel::refreshTitle() { + if (const auto titleRect = computeTitleRect()) { + if (!_title) { + _title.create( + widget(), + tr::lng_group_call_title(), + st::groupCallHeaderLabel); + _window->setTitle(u" "_q); + } + const auto best = _title->naturalWidth(); + const auto from = (widget()->width() - best) / 2; + const auto top = (computeMembersListTop() - _title->height()) / 2; + const auto left = titleRect->x(); + if (from >= left && from + best <= left + titleRect->width()) { + _title->resizeToWidth(best); + _title->moveToLeft(from, top); + } else if (titleRect->width() < best) { + _title->resizeToWidth(titleRect->width()); + _title->moveToLeft(left, top); + } else if (from < left) { + _title->resizeToWidth(best); + _title->moveToLeft(left, top); + } else { + _title->resizeToWidth(best); + _title->moveToLeft(left + titleRect->width() - best, top); + } + } else if (_title) { + _title.destroy(); + _window->setTitle(tr::lng_group_call_title(tr::now)); + } } void GroupPanel::paint(QRect clip) { diff --git a/Telegram/SourceFiles/calls/calls_group_panel.h b/Telegram/SourceFiles/calls/calls_group_panel.h index 54d98a343..d4c87dd63 100644 --- a/Telegram/SourceFiles/calls/calls_group_panel.h +++ b/Telegram/SourceFiles/calls/calls_group_panel.h @@ -76,6 +76,10 @@ private: void stateChanged(State state); void showControls(); + [[nodiscard]] int computeMembersListTop() const; + [[nodiscard]] std::optional computeTitleRect() const; + void refreshTitle(); + GroupCall *_call = nullptr; not_null _channel; @@ -87,6 +91,7 @@ private: rpl::lifetime _callLifetime; + object_ptr _title = { nullptr }; object_ptr _members; object_ptr