mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 23:27:09 +02:00
Darken and pause on reply field focus.
This commit is contained in:
parent
0ca40e9d34
commit
bab66c4ff6
12 changed files with 83 additions and 17 deletions
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@ public:
|
|||
|
||||
void show(ReplyAreaData data);
|
||||
|
||||
[[nodiscard]] rpl::producer<bool> focusedValue() const;
|
||||
|
||||
private:
|
||||
using VoiceToSend = HistoryView::Controls::VoiceToSend;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -165,6 +165,7 @@ private:
|
|||
QRectF rect;
|
||||
qreal rotation = 0.;
|
||||
qreal controlsOpacity = 0.;
|
||||
qreal fade = 0.;
|
||||
};
|
||||
struct StartStreaming {
|
||||
StartStreaming() : continueStreaming(false), startTime(0) {
|
||||
|
|
Loading…
Add table
Reference in a new issue