Send chosen venues.

This commit is contained in:
John Preston 2024-07-12 12:23:47 +02:00
parent a130bb1be6
commit 8ce10d5503
6 changed files with 73 additions and 64 deletions

View file

@ -54,6 +54,10 @@ struct InputVenue {
QString id; QString id;
QString venueType; QString venueType;
[[nodiscard]] bool justLocation() const {
return id.isEmpty() && title.isEmpty() && address.isEmpty();
}
friend inline bool operator==( friend inline bool operator==(
const InputVenue &, const InputVenue &,
const InputVenue &) = default; const InputVenue &) = default;

View file

@ -158,12 +158,16 @@ constexpr auto kRefreshBotsTimeout = 60 * 60 * crl::time(1000);
return result; return result;
} }
[[nodiscard]] QString ResolveMapsToken(not_null<Main::Session*> session) { [[nodiscard]] Ui::LocationPickerConfig ResolveMapsConfig(
return u""_q; not_null<Main::Session*> session) {
} const auto &appConfig = session->appConfig();
auto map = appConfig.get<base::flat_map<QString, QString>>(
[[nodiscard]] QString ResolveGeocodingToken(not_null<Main::Session*> session) { u"tdesktop_config_map"_q,
return u""_q; base::flat_map<QString, QString>());
return {
.mapsToken = map[u"maps"_q],
.geoToken = map[u"geo"_q],
};
} }
void ShowChooseBox( void ShowChooseBox(
@ -1806,12 +1810,18 @@ void AttachWebView::toggleInMenu(
void ChooseAndSendLocation( void ChooseAndSendLocation(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
const Ui::LocationPickerConfig &config,
Api::SendAction action) { Api::SendAction action) {
const auto callback = [=](Ui::LocationInfo info) { const auto callback = [=](Data::InputVenue venue) {
Api::SendLocation(action, info.lat, info.lon); if (venue.justLocation()) {
Api::SendLocation(action, venue.lat, venue.lon);
} else {
Api::SendVenue(action, venue);
}
}; };
Ui::LocationPicker::Show({ Ui::LocationPicker::Show({
.parent = controller->widget(), .parent = controller->widget(),
.config = config,
.session = &controller->session(), .session = &controller->session(),
.callback = crl::guard(controller, callback), .callback = crl::guard(controller, callback),
.quit = [] { Shortcuts::Launch(Shortcuts::Command::Quit); }, .quit = [] { Shortcuts::Launch(Shortcuts::Command::Quit); },
@ -1876,12 +1886,11 @@ std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
} }
const auto session = &controller->session(); const auto session = &controller->session();
const auto locationType = ChatRestriction::SendOther; const auto locationType = ChatRestriction::SendOther;
const auto config = ResolveMapsConfig(session);
if (Data::CanSendAnyOf(peer, locationType) if (Data::CanSendAnyOf(peer, locationType)
&& Ui::LocationPicker::Available( && Ui::LocationPicker::Available(config)) {
ResolveMapsToken(session),
ResolveGeocodingToken(session))) {
raw->addAction(tr::lng_maps_point(tr::now), [=] { raw->addAction(tr::lng_maps_point(tr::now), [=] {
ChooseAndSendLocation(controller, actionFactory()); ChooseAndSendLocation(controller, config, actionFactory());
}, &st::menuIconAddress); }, &st::menuIconAddress);
} }
for (const auto &bot : bots->attachBots()) { for (const auto &bot : bots->attachBots()) {

View file

@ -144,28 +144,22 @@ std::vector<QString> AppConfig::getStringArray(
}); });
} }
std::vector<std::map<QString, QString>> AppConfig::getStringMapArray( base::flat_map<QString, QString> AppConfig::getStringMap(
const QString &key, const QString &key,
std::vector<std::map<QString, QString>> &&fallback) const { base::flat_map<QString, QString> &&fallback) const {
return getValue(key, [&](const MTPJSONValue &value) { return getValue(key, [&](const MTPJSONValue &value) {
return value.match([&](const MTPDjsonArray &data) { return value.match([&](const MTPDjsonObject &data) {
auto result = std::vector<std::map<QString, QString>>(); auto result = base::flat_map<QString, QString>();
result.reserve(data.vvalue().v.size()); result.reserve(data.vvalue().v.size());
for (const auto &entry : data.vvalue().v) { for (const auto &entry : data.vvalue().v) {
if (entry.type() != mtpc_jsonObject) { const auto &data = entry.data();
const auto &value = data.vvalue();
if (value.type() != mtpc_jsonString) {
return std::move(fallback); return std::move(fallback);
} }
auto element = std::map<QString, QString>(); result.emplace(
for (const auto &field : entry.c_jsonObject().vvalue().v) { qs(data.vkey()),
const auto &data = field.c_jsonObjectValue(); qs(value.c_jsonString().vvalue()));
if (data.vvalue().type() != mtpc_jsonString) {
return std::move(fallback);
}
element.emplace(
qs(data.vkey()),
qs(data.vvalue().c_jsonString().vvalue()));
}
result.push_back(std::move(element));
} }
return result; return result;
}, [&](const auto &data) { }, [&](const auto &data) {

View file

@ -35,12 +35,11 @@ public:
return getString(key, fallback); return getString(key, fallback);
} else if constexpr (std::is_same_v<Type, std::vector<QString>>) { } else if constexpr (std::is_same_v<Type, std::vector<QString>>) {
return getStringArray(key, std::move(fallback)); return getStringArray(key, std::move(fallback));
} else if constexpr (
std::is_same_v<Type, base::flat_map<QString, QString>>) {
return getStringMap(key, std::move(fallback));
} else if constexpr (std::is_same_v<Type, std::vector<int>>) { } else if constexpr (std::is_same_v<Type, std::vector<int>>) {
return getIntArray(key, std::move(fallback)); return getIntArray(key, std::move(fallback));
} else if constexpr (std::is_same_v<
Type,
std::vector<std::map<QString, QString>>>) {
return getStringMapArray(key, std::move(fallback));
} else if constexpr (std::is_same_v<Type, bool>) { } else if constexpr (std::is_same_v<Type, bool>) {
return getBool(key, fallback); return getBool(key, fallback);
} }
@ -78,9 +77,9 @@ private:
[[nodiscard]] std::vector<QString> getStringArray( [[nodiscard]] std::vector<QString> getStringArray(
const QString &key, const QString &key,
std::vector<QString> &&fallback) const; std::vector<QString> &&fallback) const;
[[nodiscard]] std::vector<std::map<QString, QString>> getStringMapArray( [[nodiscard]] base::flat_map<QString, QString> getStringMap(
const QString &key, const QString &key,
std::vector<std::map<QString, QString>> &&fallback) const; base::flat_map<QString, QString> &&fallback) const;
[[nodiscard]] std::vector<int> getIntArray( [[nodiscard]] std::vector<int> getIntArray(
const QString &key, const QString &key,
std::vector<int> &&fallback) const; std::vector<int> &&fallback) const;

View file

@ -56,8 +56,6 @@ const auto kProtocolOverride = "";
#endif // Q_OS_MAC #endif // Q_OS_MAC
Core::GeoLocation LastExactLocation; Core::GeoLocation LastExactLocation;
QString MapsProviderToken;
QString GeocodingProviderToken;
using VenueData = Data::InputVenue; using VenueData = Data::InputVenue;
@ -136,7 +134,8 @@ class VenuesController final
public: public:
VenuesController( VenuesController(
not_null<Main::Session*> session, not_null<Main::Session*> session,
rpl::producer<std::vector<VenueData>> content); rpl::producer<std::vector<VenueData>> content,
Fn<void(VenueData)> callback);
void prepare() override; void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override; void rowClicked(not_null<PeerListRow*> row) override;
@ -165,6 +164,7 @@ private:
void rebuild(const std::vector<VenueData> &rows); void rebuild(const std::vector<VenueData> &rows);
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
const Fn<void(VenueData)> _callback;
rpl::variable<std::vector<VenueData>> _rows; rpl::variable<std::vector<VenueData>> _rows;
base::flat_map<QString, VenueIcon> _icons; base::flat_map<QString, VenueIcon> _icons;
@ -179,8 +179,10 @@ private:
VenuesController::VenuesController( VenuesController::VenuesController(
not_null<Main::Session*> session, not_null<Main::Session*> session,
rpl::producer<std::vector<VenueData>> content) rpl::producer<std::vector<VenueData>> content,
Fn<void(VenueData)> callback)
: _session(session) : _session(session)
, _callback(std::move(callback))
, _rows(std::move(content)) { , _rows(std::move(content)) {
} }
@ -211,8 +213,7 @@ void VenuesController::rebuild(const std::vector<VenueData> &rows) {
} }
void VenuesController::rowClicked(not_null<PeerListRow*> row) { void VenuesController::rowClicked(not_null<PeerListRow*> row) {
const auto venue = static_cast<VenueRow*>(row.get())->data(); _callback(static_cast<VenueRow*>(row.get())->data());
venue;
} }
void VenuesController::rowRightActionClicked(not_null<PeerListRow*> row) { void VenuesController::rowRightActionClicked(not_null<PeerListRow*> row) {
@ -468,13 +469,15 @@ void VenuesController::rowPaintIcon(
void SetupVenues( void SetupVenues(
not_null<VerticalLayout*> container, not_null<VerticalLayout*> container,
std::shared_ptr<Main::SessionShow> show, std::shared_ptr<Main::SessionShow> show,
rpl::producer<std::vector<VenueData>> value) { rpl::producer<std::vector<VenueData>> value,
Fn<void(VenueData)> callback) {
auto &lifetime = container->lifetime(); auto &lifetime = container->lifetime();
const auto delegate = lifetime.make_state<PeerListContentDelegateShow>( const auto delegate = lifetime.make_state<PeerListContentDelegateShow>(
show); show);
const auto controller = lifetime.make_state<VenuesController>( const auto controller = lifetime.make_state<VenuesController>(
&show->session(), &show->session(),
std::move(value)); std::move(value),
std::move(callback));
controller->setStyleOverrides(&st::pickLocationVenueList); controller->setStyleOverrides(&st::pickLocationVenueList);
const auto content = container->add(object_ptr<PeerListContent>( const auto content = container->add(object_ptr<PeerListContent>(
container, container,
@ -520,7 +523,8 @@ void SetupVenues(
} // namespace } // namespace
LocationPicker::LocationPicker(Descriptor &&descriptor) LocationPicker::LocationPicker(Descriptor &&descriptor)
: _callback(std::move(descriptor.callback)) : _config(std::move(descriptor.config))
, _callback(std::move(descriptor.callback))
, _quit(std::move(descriptor.quit)) , _quit(std::move(descriptor.quit))
, _window(std::make_unique<SeparatePanel>()) , _window(std::make_unique<SeparatePanel>())
, _body((_window->setInnerSize(st::pickLocationWindow) , _body((_window->setInnerSize(st::pickLocationWindow)
@ -550,13 +554,9 @@ std::shared_ptr<Main::SessionShow> LocationPicker::uiShow() {
return Main::MakeSessionShow(nullptr, _session); return Main::MakeSessionShow(nullptr, _session);
} }
bool LocationPicker::Available( bool LocationPicker::Available(const LocationPickerConfig &config) {
const QString &mapsToken,
const QString &geocodingToken) {
static const auto Supported = Webview::NavigateToDataSupported(); static const auto Supported = Webview::NavigateToDataSupported();
MapsProviderToken = mapsToken; return Supported && !config.mapsToken.isEmpty();
GeocodingProviderToken = geocodingToken;
return Supported && !MapsProviderToken.isEmpty();
} }
void LocationPicker::setup(const Descriptor &descriptor) { void LocationPicker::setup(const Descriptor &descriptor) {
@ -606,7 +606,10 @@ void LocationPicker::setupWindow(const Descriptor &descriptor) {
return v::is<PickerVenueList>(state); return v::is<PickerVenueList>(state);
}) | rpl::map([=](PickerVenueState &&state) { }) | rpl::map([=](PickerVenueState &&state) {
return std::move(v::get<PickerVenueList>(state).list); return std::move(v::get<PickerVenueList>(state).list);
})); }), [=](VenueData info) {
_callback(std::move(info));
close();
});
rpl::combine( rpl::combine(
_body->sizeValue(), _body->sizeValue(),
@ -810,14 +813,14 @@ void LocationPicker::resolveAddress(Core::GeoLocation location) {
Core::ResolveLocationAddress( Core::ResolveLocationAddress(
location, location,
langId, langId,
GeocodingProviderToken, _config.geoToken,
crl::guard(this, done)); crl::guard(this, done));
} }
void LocationPicker::mapReady() { void LocationPicker::mapReady() {
Expects(_scroll != nullptr); Expects(_scroll != nullptr);
const auto token = MapsProviderToken.toUtf8(); const auto token = _config.mapsToken.toUtf8();
const auto center = DefaultCenter(); const auto center = DefaultCenter();
const auto bounds = DefaultBounds(); const auto bounds = DefaultBounds();
const auto protocol = *kProtocolOverride const auto protocol = *kProtocolOverride

View file

@ -33,11 +33,6 @@ class SeparatePanel;
class RpWidget; class RpWidget;
class ScrollArea; class ScrollArea;
struct LocationInfo {
float64 lat = 0.;
float64 lon = 0.;
};
struct PickerVenueLoading { struct PickerVenueLoading {
friend inline bool operator==( friend inline bool operator==(
PickerVenueLoading, PickerVenueLoading,
@ -72,20 +67,24 @@ using PickerVenueState = std::variant<
PickerVenueWaitingForLocation, PickerVenueWaitingForLocation,
PickerVenueList>; PickerVenueList>;
struct LocationPickerConfig {
QString mapsToken;
QString geoToken;
};
class LocationPicker final : public base::has_weak_ptr { class LocationPicker final : public base::has_weak_ptr {
public: public:
struct Descriptor { struct Descriptor {
RpWidget *parent = nullptr; RpWidget *parent = nullptr;
LocationPickerConfig config;
not_null<Main::Session*> session; not_null<Main::Session*> session;
Fn<void(LocationInfo)> callback; Fn<void(Data::InputVenue)> callback;
Fn<void()> quit; Fn<void()> quit;
Webview::StorageId storageId; Webview::StorageId storageId;
rpl::producer<> closeRequests; rpl::producer<> closeRequests;
}; };
[[nodiscard]] static bool Available( [[nodiscard]] static bool Available(const LocationPickerConfig &config);
const QString &mapsToken,
const QString &geocodingToken);
static not_null<LocationPicker*> Show(Descriptor &&descriptor); static not_null<LocationPicker*> Show(Descriptor &&descriptor);
void close(); void close();
@ -114,9 +113,8 @@ private:
void venuesRequest(Core::GeoLocation location, QString query = {}); void venuesRequest(Core::GeoLocation location, QString query = {});
void venuesSendRequest(); void venuesSendRequest();
rpl::lifetime _lifetime; LocationPickerConfig _config;
Fn<void(Data::InputVenue)> _callback;
Fn<void(LocationInfo)> _callback;
Fn<void()> _quit; Fn<void()> _quit;
std::unique_ptr<SeparatePanel> _window; std::unique_ptr<SeparatePanel> _window;
not_null<RpWidget*> _body; not_null<RpWidget*> _body;
@ -143,6 +141,8 @@ private:
QString _venuesRequestQuery; QString _venuesRequestQuery;
base::flat_map<QString, std::vector<VenuesCacheEntry>> _venuesCache; base::flat_map<QString, std::vector<VenuesCacheEntry>> _venuesCache;
rpl::lifetime _lifetime;
}; };
} // namespace Ui } // namespace Ui