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 venueType;
[[nodiscard]] bool justLocation() const {
return id.isEmpty() && title.isEmpty() && address.isEmpty();
}
friend inline bool operator==(
const InputVenue &,
const InputVenue &) = default;

View file

@ -158,12 +158,16 @@ constexpr auto kRefreshBotsTimeout = 60 * 60 * crl::time(1000);
return result;
}
[[nodiscard]] QString ResolveMapsToken(not_null<Main::Session*> session) {
return u""_q;
}
[[nodiscard]] QString ResolveGeocodingToken(not_null<Main::Session*> session) {
return u""_q;
[[nodiscard]] Ui::LocationPickerConfig ResolveMapsConfig(
not_null<Main::Session*> session) {
const auto &appConfig = session->appConfig();
auto map = appConfig.get<base::flat_map<QString, QString>>(
u"tdesktop_config_map"_q,
base::flat_map<QString, QString>());
return {
.mapsToken = map[u"maps"_q],
.geoToken = map[u"geo"_q],
};
}
void ShowChooseBox(
@ -1806,12 +1810,18 @@ void AttachWebView::toggleInMenu(
void ChooseAndSendLocation(
not_null<Window::SessionController*> controller,
const Ui::LocationPickerConfig &config,
Api::SendAction action) {
const auto callback = [=](Ui::LocationInfo info) {
Api::SendLocation(action, info.lat, info.lon);
const auto callback = [=](Data::InputVenue venue) {
if (venue.justLocation()) {
Api::SendLocation(action, venue.lat, venue.lon);
} else {
Api::SendVenue(action, venue);
}
};
Ui::LocationPicker::Show({
.parent = controller->widget(),
.config = config,
.session = &controller->session(),
.callback = crl::guard(controller, callback),
.quit = [] { Shortcuts::Launch(Shortcuts::Command::Quit); },
@ -1876,12 +1886,11 @@ std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
}
const auto session = &controller->session();
const auto locationType = ChatRestriction::SendOther;
const auto config = ResolveMapsConfig(session);
if (Data::CanSendAnyOf(peer, locationType)
&& Ui::LocationPicker::Available(
ResolveMapsToken(session),
ResolveGeocodingToken(session))) {
&& Ui::LocationPicker::Available(config)) {
raw->addAction(tr::lng_maps_point(tr::now), [=] {
ChooseAndSendLocation(controller, actionFactory());
ChooseAndSendLocation(controller, config, actionFactory());
}, &st::menuIconAddress);
}
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,
std::vector<std::map<QString, QString>> &&fallback) const {
base::flat_map<QString, QString> &&fallback) const {
return getValue(key, [&](const MTPJSONValue &value) {
return value.match([&](const MTPDjsonArray &data) {
auto result = std::vector<std::map<QString, QString>>();
return value.match([&](const MTPDjsonObject &data) {
auto result = base::flat_map<QString, QString>();
result.reserve(data.vvalue().v.size());
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);
}
auto element = std::map<QString, QString>();
for (const auto &field : entry.c_jsonObject().vvalue().v) {
const auto &data = field.c_jsonObjectValue();
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));
result.emplace(
qs(data.vkey()),
qs(value.c_jsonString().vvalue()));
}
return result;
}, [&](const auto &data) {

View file

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

View file

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

View file

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