Handle clicks on location areas in stories.

This commit is contained in:
John Preston 2023-08-07 11:21:03 +02:00
parent ebe2088561
commit 066dbfe8fc
6 changed files with 89 additions and 2 deletions

View File

@ -33,8 +33,11 @@ using UpdateFlag = StoryUpdate::Flag;
[[nodiscard]] StoryArea ParseArea(const MTPMediaAreaCoordinates &area) {
const auto &data = area.data();
const auto center = QPointF(data.vx().v, data.vy().v);
const auto size = QSizeF(data.vw().v, data.vh().v);
const auto corner = center - QPointF(size.width(), size.height()) / 2.;
return {
.geometry = { data.vx().v, data.vy().v, data.vw().v, data.vh().v },
.geometry = { corner / 100., size / 100. },
.rotation = data.vrotation().v,
};
}

View File

@ -118,6 +118,19 @@ struct SameDayRange {
return { QString() + QChar(10084) };
}
[[nodiscard]] QPoint Rotated(QPoint point, QPoint origin, float64 angle) {
if (std::abs(angle) < 1.) {
return point;
}
const auto alpha = angle / 180. * M_PI;
const auto acos = cos(alpha);
const auto asin = sin(alpha);
point -= origin;
return origin + QPoint(
int(base::SafeRound(acos * point.x() - asin * point.y())),
int(base::SafeRound(asin * point.x() + acos * point.y())));
}
} // namespace
class Controller::PhotoPlayback final {
@ -531,11 +544,30 @@ void Controller::initLayout() {
.nameBoundingRect = nameBoundingRect(right, false),
.nameFontSize = nameFontSize,
};
if (!_locationAreas.empty()) {
rebuildLocationAreas(layout);
}
return layout;
});
}
void Controller::rebuildLocationAreas(const Layout &layout) const {
Expects(_locations.size() == _locationAreas.size());
const auto origin = layout.content.topLeft();
const auto scale = layout.content.size();
for (auto i = 0, count = int(_locations.size()); i != count; ++i) {
auto &area = _locationAreas[i];
const auto &general = _locations[i].area.geometry;
area.geometry = QRect(
int(base::SafeRound(general.x() * scale.width())),
int(base::SafeRound(general.y() * scale.height())),
int(base::SafeRound(general.width() * scale.width())),
int(base::SafeRound(general.height() * scale.height()))
).translated(origin);
}
}
Data::Story *Controller::story() const {
if (!_session) {
return nullptr;
@ -918,6 +950,14 @@ bool Controller::changeShown(Data::Story *story) {
Data::Stories::Polling::Viewer);
}
_liked = false;
const auto &locations = story
? story->locations()
: std::vector<Data::StoryLocation>();
if (_locations != locations) {
_locations = locations;
_locationAreas.clear();
}
return true;
}
@ -1082,6 +1122,32 @@ void Controller::updatePlayback(const Player::TrackState &state) {
}
}
ClickHandlerPtr Controller::lookupLocationHandler(QPoint point) const {
const auto &layout = _layout.current();
if (_locations.empty() || !layout) {
return nullptr;
} else if (_locationAreas.empty()) {
_locationAreas = _locations | ranges::views::transform([](
const Data::StoryLocation &location) {
return LocationArea{
.rotation = location.area.rotation,
.handler = std::make_shared<LocationClickHandler>(
location.point),
};
}) | ranges::to_vector;
rebuildLocationAreas(*layout);
}
for (const auto &area : _locationAreas) {
const auto center = area.geometry.center();
const auto angle = -area.rotation;
if (area.geometry.contains(Rotated(point, center, angle))) {
return area.handler;
}
}
return nullptr;
}
void Controller::maybeMarkAsRead(const Player::TrackState &state) {
const auto length = state.length;
const auto position = Player::IsStoppedAtEnd(state.state)

View File

@ -135,6 +135,7 @@ public:
void ready();
void updateVideoPlayback(const Player::TrackState &state);
[[nodiscard]] ClickHandlerPtr lookupLocationHandler(QPoint point) const;
[[nodiscard]] bool subjumpAvailable(int delta) const;
[[nodiscard]] bool subjumpFor(int delta);
@ -188,6 +189,11 @@ private:
return peerId != 0;
}
};
struct LocationArea {
QRect geometry;
float64 rotation = 0.;
ClickHandlerPtr handler;
};
class PhotoPlayback;
class Unsupported;
@ -203,6 +209,7 @@ private:
void updateContentFaded();
void updatePlayingAllowed();
void setPlayingAllowed(bool allowed);
void rebuildLocationAreas(const Layout &layout) const;
void hideSiblings();
void showSiblings(not_null<Main::Session*> session);
@ -275,6 +282,9 @@ private:
bool _started = false;
bool _viewed = false;
std::vector<Data::StoryLocation> _locations;
mutable std::vector<LocationArea> _locationAreas;
std::vector<CachedSource> _cachedSourcesList;
int _cachedSourceIndex = -1;
bool _showingUnreadSources = false;

View File

@ -59,6 +59,10 @@ void View::updatePlayback(const Player::TrackState &state) {
_controller->updateVideoPlayback(state);
}
ClickHandlerPtr View::lookupLocationHandler(QPoint point) const {
return _controller->lookupLocationHandler(point);
}
bool View::subjumpAvailable(int delta) const {
return _controller->subjumpAvailable(delta);
}

View File

@ -73,6 +73,7 @@ public:
void showFullCaption();
void updatePlayback(const Player::TrackState &state);
[[nodiscard]] ClickHandlerPtr lookupLocationHandler(QPoint point) const;
[[nodiscard]] bool subjumpAvailable(int delta) const;
[[nodiscard]] bool subjumpFor(int delta) const;

View File

@ -5666,6 +5666,9 @@ void OverlayWidget::updateOver(QPoint pos) {
const auto point = pos - QPoint(_groupThumbsLeft, _groupThumbsTop);
lnk = _groupThumbs->getState(point);
lnkhost = this;
} else if (_stories) {
lnk = _stories->lookupLocationHandler(pos);
lnkhost = this;
}