location_picker.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "base/invoke_queued.h"
  9. #include "base/timer.h"
  10. #include "base/weak_ptr.h"
  11. #include "core/current_geo_location.h"
  12. #include "mtproto/sender.h"
  13. #include "webview/webview_common.h"
  14. namespace Data {
  15. struct InputVenue;
  16. } // namespace Data
  17. namespace Main {
  18. class Session;
  19. class SessionShow;
  20. } // namespace Main
  21. namespace Webview {
  22. class Window;
  23. } // namespace Webview
  24. namespace Ui {
  25. class AbstractButton;
  26. class SeparatePanel;
  27. class RpWidget;
  28. class ScrollArea;
  29. class VerticalLayout;
  30. template <typename Widget>
  31. class SlideWrap;
  32. struct PickerVenueLoading {
  33. friend inline bool operator==(
  34. PickerVenueLoading,
  35. PickerVenueLoading) = default;
  36. };
  37. struct PickerVenueNothingFound {
  38. QString query;
  39. friend inline bool operator==(
  40. const PickerVenueNothingFound&,
  41. const PickerVenueNothingFound&) = default;
  42. };
  43. struct PickerVenueWaitingForLocation {
  44. friend inline bool operator==(
  45. PickerVenueWaitingForLocation,
  46. PickerVenueWaitingForLocation) = default;
  47. };
  48. struct PickerVenueList {
  49. std::vector<Data::InputVenue> list;
  50. friend inline bool operator==(
  51. const PickerVenueList&,
  52. const PickerVenueList&) = default;
  53. };
  54. using PickerVenueState = std::variant<
  55. PickerVenueLoading,
  56. PickerVenueNothingFound,
  57. PickerVenueWaitingForLocation,
  58. PickerVenueList>;
  59. struct LocationPickerConfig {
  60. QString mapsToken;
  61. QString geoToken;
  62. };
  63. class LocationPicker final : public base::has_weak_ptr {
  64. public:
  65. struct Descriptor {
  66. RpWidget *parent = nullptr;
  67. LocationPickerConfig config;
  68. rpl::producer<QString> chooseLabel;
  69. PeerData *recipient = nullptr;
  70. not_null<Main::Session*> session;
  71. Core::GeoLocation initial;
  72. Fn<void(Data::InputVenue)> callback;
  73. Fn<void()> quit;
  74. Webview::StorageId storageId;
  75. rpl::producer<> closeRequests;
  76. };
  77. [[nodiscard]] static bool Available(const LocationPickerConfig &config);
  78. static not_null<LocationPicker*> Show(Descriptor &&descriptor);
  79. void activate();
  80. void close();
  81. void minimize();
  82. void quit();
  83. private:
  84. struct VenuesCacheEntry {
  85. Core::GeoLocation location;
  86. PickerVenueList result;
  87. };
  88. explicit LocationPicker(Descriptor &&descriptor);
  89. [[nodiscard]] std::shared_ptr<Main::SessionShow> uiShow();
  90. void setup(const Descriptor &descriptor);
  91. void setupWindow(const Descriptor &descriptor);
  92. void setupWebview();
  93. void processKey(const QString &key, const QString &modifier);
  94. void resolveCurrentLocation();
  95. void resolveAddressByTimer();
  96. void resolveAddress(Core::GeoLocation location);
  97. void mapReady();
  98. bool venuesFromCache(Core::GeoLocation location, QString query = {});
  99. void venuesRequest(Core::GeoLocation location, QString query = {});
  100. void venuesSendRequest();
  101. void venuesApplyResults(PickerVenueList venues);
  102. void venuesSearchEnableAt(Core::GeoLocation location);
  103. void venuesSearchChanged(const std::optional<QString> &query);
  104. LocationPickerConfig _config;
  105. Fn<void(Data::InputVenue)> _callback;
  106. Fn<void()> _quit;
  107. std::unique_ptr<SeparatePanel> _window;
  108. not_null<RpWidget*> _body;
  109. RpWidget *_container = nullptr;
  110. RpWidget *_mapPlaceholder = nullptr;
  111. RpWidget *_mapLoading = nullptr;
  112. AbstractButton *_mapButton = nullptr;
  113. SlideWrap<VerticalLayout> *_mapControlsWrap = nullptr;
  114. rpl::variable<QString> _chooseButtonLabel;
  115. ScrollArea *_scroll = nullptr;
  116. Webview::StorageId _webviewStorageId;
  117. std::unique_ptr<Webview::Window> _webview;
  118. SingleQueuedInvokation _updateStyles;
  119. Core::GeoLocation _initialProvided;
  120. int _mapPlaceholderAdded = 0;
  121. bool _subscribedToColors = false;
  122. base::Timer _geocoderResolveTimer;
  123. Core::GeoLocation _geocoderResolvePostponed;
  124. Core::GeoLocation _geocoderResolvingFor;
  125. QString _geocoderSavedAddress;
  126. rpl::variable<QString> _geocoderAddress;
  127. rpl::variable<PickerVenueState> _venueState;
  128. const not_null<Main::Session*> _session;
  129. std::optional<Core::GeoLocation> _venuesSearchLocation;
  130. std::optional<QString> _venuesSearchQuery;
  131. base::Timer _venuesSearchDebounceTimer;
  132. MTP::Sender _api;
  133. PeerData *_venueRecipient = nullptr;
  134. UserData *_venuesBot = nullptr;
  135. mtpRequestId _venuesBotRequestId = 0;
  136. mtpRequestId _venuesRequestId = 0;
  137. Core::GeoLocation _venuesRequestLocation;
  138. QString _venuesRequestQuery;
  139. QString _venuesInitialQuery;
  140. base::flat_map<QString, std::vector<VenuesCacheEntry>> _venuesCache;
  141. Core::GeoLocation _venuesNoSearchLocation;
  142. rpl::variable<bool> _venuesSearchShown = false;
  143. rpl::lifetime _lifetime;
  144. };
  145. } // namespace Ui