Darken and pause on reply field focus.

This commit is contained in:
John Preston 2023-05-10 14:33:17 +04:00
parent 0ca40e9d34
commit bab66c4ff6
12 changed files with 83 additions and 17 deletions

View File

@ -1108,6 +1108,11 @@ bool ComposeControls::focus() {
return true;
}
rpl::producer<bool> ComposeControls::focusedValue() const {
return rpl::single(Ui::InFocusChain(_wrap.get()))
| rpl::then(_focusChanges.events());
}
rpl::producer<> ComposeControls::cancelRequests() const {
return _cancelRequests.events();
}
@ -1596,6 +1601,8 @@ void ComposeControls::initKeyHandler() {
});
return Result::Cancel;
}
} else if (k->key() == Qt::Key_Escape) {
return Result::Cancel;
}
return Result::Continue;
});
@ -1608,7 +1615,12 @@ void ComposeControls::initField() {
Ui::Connect(_field, &Ui::InputField::cancelled, [=] { escape(); });
Ui::Connect(_field, &Ui::InputField::tabbed, [=] { fieldTabbed(); });
Ui::Connect(_field, &Ui::InputField::resized, [=] { updateHeight(); });
//Ui::Connect(_field, &Ui::InputField::focused, [=] { fieldFocused(); });
Ui::Connect(_field, &Ui::InputField::focused, [=] {
_focusChanges.fire(true);
});
Ui::Connect(_field, &Ui::InputField::blurred, [=] {
_focusChanges.fire(false);
});
Ui::Connect(_field, &Ui::InputField::changed, [=] { fieldChanged(); });
InitMessageField(_show, _field, [=](not_null<DocumentData*> emoji) {
if (_history && Data::AllowEmojiWithoutPremium(_history->peer)) {

View File

@ -136,6 +136,7 @@ public:
[[nodiscard]] int heightCurrent() const;
bool focus();
[[nodiscard]] rpl::producer<bool> focusedValue() const;
[[nodiscard]] rpl::producer<> cancelRequests() const;
[[nodiscard]] rpl::producer<Api::SendOptions> sendRequests() const;
[[nodiscard]] rpl::producer<VoiceToSend> sendVoiceRequests() const;
@ -390,6 +391,7 @@ private:
std::unique_ptr<WebpageProcessor> _preview;
Fn<void()> _raiseEmojiSuggestions;
rpl::event_stream<bool> _focusChanges;
rpl::lifetime _historyLifetime;
rpl::lifetime _uploaderSubscriptions;

View File

@ -29,6 +29,7 @@ namespace {
constexpr auto kPhotoProgressInterval = crl::time(100);
constexpr auto kPhotoDuration = 5 * crl::time(1000);
constexpr auto kSiblingMultiplier = 0.448;
constexpr auto kFullContentFade = 0.2;
} // namespace
@ -108,6 +109,19 @@ Controller::Controller(not_null<Delegate*> delegate)
, _slider(std::make_unique<Slider>(this))
, _replyArea(std::make_unique<ReplyArea>(this)) {
initLayout();
_replyArea->focusedValue(
) | rpl::start_with_next([=](bool focused) {
_contentFaded = focused;
_contentFadeAnimation.start(
[=] { _delegate->storiesRepaint(); },
focused ? 0. : 1.,
focused ? 1. : 0.,
st::fadeWrapDuration);
togglePaused(focused);
}, _lifetime);
_contentFadeAnimation.stop();
}
Controller::~Controller() = default;
@ -223,6 +237,11 @@ rpl::producer<Layout> Controller::layoutValue() const {
return _layout.value() | rpl::filter_optional();
}
float64 Controller::contentFade() const {
return _contentFadeAnimation.value(_contentFaded ? 1. : 0.)
* kFullContentFade;
}
std::shared_ptr<ChatHelpers::Show> Controller::uiShow() const {
return _delegate->storiesShow();
}
@ -406,6 +425,10 @@ SiblingView Controller::siblingRight() const {
return {};
}
void Controller::unfocusReply() {
_wrap->setFocus();
}
rpl::lifetime &Controller::lifetime() {
return _lifetime;
}

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "data/data_stories.h"
#include "ui/effects/animations.h"
namespace base {
class PowerSaveBlocker;
@ -66,6 +67,7 @@ public:
[[nodiscard]] not_null<Ui::RpWidget*> wrap() const;
[[nodiscard]] Layout layout() const;
[[nodiscard]] rpl::producer<Layout> layoutValue() const;
[[nodiscard]] float64 contentFade() const;
[[nodiscard]] std::shared_ptr<ChatHelpers::Show> uiShow() const;
[[nodiscard]] auto stickerOrEmojiChosen() const
@ -91,6 +93,8 @@ public:
[[nodiscard]] SiblingView siblingLeft() const;
[[nodiscard]] SiblingView siblingRight() const;
void unfocusReply();
[[nodiscard]] rpl::lifetime &lifetime();
private:
@ -118,6 +122,9 @@ private:
const std::unique_ptr<ReplyArea> _replyArea;
std::unique_ptr<PhotoPlayback> _photoPlayback;
Ui::Animations::Simple _contentFadeAnimation;
bool _contentFaded = false;
Data::FullStoryId _shown;
std::optional<Data::StoriesList> _list;
int _index = 0;

View File

@ -68,7 +68,7 @@ void ReplyArea::chooseAttach(std::optional<bool> overrideCompress) {
void ReplyArea::initActions() {
_controls->cancelRequests(
) | rpl::start_with_next([=] {
// #TODO stories
_controller->unfocusReply();
}, _lifetime);
_controls->sendRequests(
@ -157,6 +157,10 @@ void ReplyArea::show(ReplyAreaData data) {
_controls->clear();
}
rpl::producer<bool> ReplyArea::focusedValue() const {
return _controls->focusedValue();
}
void ReplyArea::showPremiumToast(not_null<DocumentData*> emoji) {
// #TODO stories
}

View File

@ -40,6 +40,8 @@ public:
void show(ReplyAreaData data);
[[nodiscard]] rpl::producer<bool> focusedValue() const;
private:
using VoiceToSend = HistoryView::Controls::VoiceToSend;

View File

@ -47,6 +47,10 @@ rpl::producer<QRect> View::contentGeometryValue() const {
}) | rpl::distinct_until_changed();
}
float64 View::contentFade() const {
return _controller->contentFade();
}
void View::updatePlayback(const Player::TrackState &state) {
_controller->updateVideoPlayback(state);
}

View File

@ -46,6 +46,7 @@ public:
[[nodiscard]] bool canDownload() const;
[[nodiscard]] QRect contentGeometry() const;
[[nodiscard]] rpl::producer<QRect> contentGeometryValue() const;
[[nodiscard]] float64 contentFade() const;
[[nodiscard]] SiblingView siblingLeft() const;
[[nodiscard]] SiblingView siblingRight() const;

View File

@ -35,12 +35,13 @@ constexpr auto kControlValues = 4 * 4 + 4 * 4; // over + icon
.header = R"(
uniform sampler2D f_texture;
uniform vec4 shadowTopRect;
uniform vec2 shadowBottomAndOpacity;
uniform vec3 shadowBottomOpacityFullFade;
)",
.body = R"(
float topHeight = shadowTopRect.w;
float bottomHeight = shadowBottomAndOpacity.x;
float opacity = shadowBottomAndOpacity.y;
float bottomHeight = shadowBottomOpacityFullFade.x;
float opacity = shadowBottomOpacityFullFade.y;
float fullFade = shadowBottomOpacityFullFade.z;
float viewportHeight = shadowTopRect.y + topHeight;
float fullHeight = topHeight + bottomHeight;
float topY = min(
@ -50,7 +51,8 @@ uniform vec2 shadowBottomAndOpacity;
vec4 fadeTop = texture2D(f_texture, vec2(topX, topY)) * opacity;
float bottomY = max(fullHeight - gl_FragCoord.y, topHeight) / fullHeight;
vec4 fadeBottom = texture2D(f_texture, vec2(0.5, bottomY)) * opacity;
result.rgb = result.rgb * (1. - fadeTop.a) * (1. - fadeBottom.a);
float fade = min((1. - fadeTop.a) * (1. - fadeBottom.a), fullFade);
result.rgb = result.rgb * fade;
)",
};
}
@ -113,10 +115,12 @@ OverlayWidget::RendererGL::RendererGL(not_null<OverlayWidget*> owner)
invalidateControls();
}, _lifetime);
_owner->_storiesChanged.events(
) | rpl::start_with_next([=] {
invalidateControls();
}, _lifetime);
crl::on_main(this, [=] {
_owner->_storiesChanged.events(
) | rpl::start_with_next([=] {
invalidateControls();
}, _lifetime);
});
}
void OverlayWidget::RendererGL::init(
@ -478,14 +482,17 @@ void OverlayWidget::RendererGL::paintTransformedContent(
program->setUniformValue("viewport", _uniformViewport);
const auto &top = st::mediaviewShadowTop.size();
const auto point = QPoint(_shadowTopFlip ? 0 : (_viewport.width() - top.width()), 0);
const auto point = QPoint(
_shadowTopFlip ? 0 : (_viewport.width() - top.width()),
0);
program->setUniformValue(
"shadowTopRect",
Uniform(transformRect(QRect(point, top))));
const auto &bottom = st::mediaviewShadowBottom;
program->setUniformValue(
"shadowBottomAndOpacity",
QVector2D(bottom.height() * _factor, geometry.controlsOpacity));
program->setUniformValue("shadowBottomOpacityFullFade", QVector3D(
bottom.height() * _factor,
geometry.controlsOpacity,
1.f - float(geometry.fade)));
FillTexturedRectangle(*_f, &*program);
}

View File

@ -15,7 +15,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Media::View {
class OverlayWidget::RendererGL final : public OverlayWidget::Renderer {
class OverlayWidget::RendererGL final
: public OverlayWidget::Renderer
, public base::has_weak_ptr {
public:
explicit RendererGL(not_null<OverlayWidget*> owner);

View File

@ -1492,6 +1492,7 @@ QRect OverlayWidget::finalContentRect() const {
}
OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
const auto fade = _stories ? _stories->contentFade() : 0.;
const auto controlsOpacity = _controlsOpacity.current();
const auto toRotation = qreal(finalContentRotation());
const auto toRectRotated = QRectF(finalContentRect());
@ -1504,7 +1505,7 @@ OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
toRectRotated.width())
: toRectRotated;
if (!_geometryAnimation.animating()) {
return { toRect, toRotation, controlsOpacity };
return { toRect, toRotation, controlsOpacity, fade };
}
const auto fromRect = _oldGeometry.rect;
const auto fromRotation = _oldGeometry.rotation;
@ -1527,7 +1528,7 @@ OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
fromRect.width() + (toRect.width() - fromRect.width()) * progress,
fromRect.height() + (toRect.height() - fromRect.height()) * progress
);
return { useRect, useRotation, controlsOpacity };
return { useRect, useRotation, controlsOpacity, fade };
}
void OverlayWidget::updateContentRect() {

View File

@ -165,6 +165,7 @@ private:
QRectF rect;
qreal rotation = 0.;
qreal controlsOpacity = 0.;
qreal fade = 0.;
};
struct StartStreaming {
StartStreaming() : continueStreaming(false), startTime(0) {