mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-03 21:54:05 +02:00
Support business working hours API.
This commit is contained in:
parent
4d12f1c0ef
commit
dd0bdd62fb
9 changed files with 177 additions and 65 deletions
|
@ -18,7 +18,7 @@ constexpr auto kInNextDayMax = WorkingInterval::kInNextDayMax;
|
|||
auto &list = intervals.list;
|
||||
ranges::sort(list, ranges::less(), &WorkingInterval::start);
|
||||
for (auto i = 0, count = int(list.size()); i != count; ++i) {
|
||||
if (i && list[i].intersected(list[i - 1])) {
|
||||
if (i && list[i] && list[i -1] && list[i].start <= list[i - 1].end) {
|
||||
list[i - 1] = list[i - 1].united(list[i]);
|
||||
list[i] = {};
|
||||
}
|
||||
|
@ -54,12 +54,12 @@ WorkingIntervals WorkingIntervals::normalized() const {
|
|||
return SortAndMerge(MoveTailToFront(SortAndMerge(*this)));
|
||||
}
|
||||
|
||||
Data::WorkingIntervals ExtractDayIntervals(
|
||||
const Data::WorkingIntervals &intervals,
|
||||
WorkingIntervals ExtractDayIntervals(
|
||||
const WorkingIntervals &intervals,
|
||||
int dayIndex) {
|
||||
Expects(dayIndex >= 0 && dayIndex < 7);
|
||||
|
||||
auto result = Data::WorkingIntervals();
|
||||
auto result = WorkingIntervals();
|
||||
auto &list = result.list;
|
||||
for (const auto &interval : intervals.list) {
|
||||
const auto now = interval.intersected(
|
||||
|
@ -80,7 +80,7 @@ Data::WorkingIntervals ExtractDayIntervals(
|
|||
}
|
||||
result = result.normalized();
|
||||
|
||||
const auto outside = [&](Data::WorkingInterval interval) {
|
||||
const auto outside = [&](WorkingInterval interval) {
|
||||
return (interval.end <= 0) || (interval.start >= kDay);
|
||||
};
|
||||
list.erase(ranges::remove_if(list, outside), end(list));
|
||||
|
@ -106,15 +106,15 @@ Data::WorkingIntervals ExtractDayIntervals(
|
|||
return result;
|
||||
}
|
||||
|
||||
Data::WorkingIntervals RemoveDayIntervals(
|
||||
const Data::WorkingIntervals &intervals,
|
||||
WorkingIntervals RemoveDayIntervals(
|
||||
const WorkingIntervals &intervals,
|
||||
int dayIndex) {
|
||||
auto result = intervals.normalized();
|
||||
auto &list = result.list;
|
||||
const auto day = Data::WorkingInterval{ 0, kDay };
|
||||
const auto day = WorkingInterval{ 0, kDay };
|
||||
const auto shifted = day.shifted(dayIndex * kDay);
|
||||
auto before = Data::WorkingInterval{ 0, shifted.start };
|
||||
auto after = Data::WorkingInterval{ shifted.end, kWeek };
|
||||
auto before = WorkingInterval{ 0, shifted.start };
|
||||
auto after = WorkingInterval{ shifted.end, kWeek };
|
||||
for (auto i = 0, count = int(list.size()); i != count; ++i) {
|
||||
if (list[i].end <= shifted.start || list[i].start >= shifted.end) {
|
||||
continue;
|
||||
|
@ -140,10 +140,10 @@ Data::WorkingIntervals RemoveDayIntervals(
|
|||
return result.normalized();
|
||||
}
|
||||
|
||||
Data::WorkingIntervals ReplaceDayIntervals(
|
||||
const Data::WorkingIntervals &intervals,
|
||||
WorkingIntervals ReplaceDayIntervals(
|
||||
const WorkingIntervals &intervals,
|
||||
int dayIndex,
|
||||
Data::WorkingIntervals replacement) {
|
||||
WorkingIntervals replacement) {
|
||||
auto result = RemoveDayIntervals(intervals, dayIndex);
|
||||
const auto first = result.list.insert(
|
||||
end(result.list),
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "base/flags.h"
|
||||
#include "data/data_location.h"
|
||||
|
||||
class UserData;
|
||||
|
||||
|
@ -125,20 +126,50 @@ struct WorkingHours {
|
|||
return { intervals.normalized(), timezoneId };
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return !timezoneId.isEmpty();
|
||||
}
|
||||
|
||||
friend inline bool operator==(
|
||||
const WorkingHours &a,
|
||||
const WorkingHours &b) = default;
|
||||
};
|
||||
|
||||
[[nodiscard]] Data::WorkingIntervals ExtractDayIntervals(
|
||||
const Data::WorkingIntervals &intervals,
|
||||
[[nodiscard]] WorkingIntervals ExtractDayIntervals(
|
||||
const WorkingIntervals &intervals,
|
||||
int dayIndex);
|
||||
[[nodiscard]] Data::WorkingIntervals RemoveDayIntervals(
|
||||
const Data::WorkingIntervals &intervals,
|
||||
[[nodiscard]] WorkingIntervals RemoveDayIntervals(
|
||||
const WorkingIntervals &intervals,
|
||||
int dayIndex);
|
||||
[[nodiscard]] Data::WorkingIntervals ReplaceDayIntervals(
|
||||
const Data::WorkingIntervals &intervals,
|
||||
[[nodiscard]] WorkingIntervals ReplaceDayIntervals(
|
||||
const WorkingIntervals &intervals,
|
||||
int dayIndex,
|
||||
Data::WorkingIntervals replacement);
|
||||
WorkingIntervals replacement);
|
||||
|
||||
struct BusinessLocation {
|
||||
QString address;
|
||||
LocationPoint point;
|
||||
|
||||
explicit operator bool() const {
|
||||
return !address.isEmpty();
|
||||
}
|
||||
|
||||
friend inline bool operator==(
|
||||
const BusinessLocation &a,
|
||||
const BusinessLocation &b) = default;
|
||||
};
|
||||
|
||||
struct BusinessDetails {
|
||||
WorkingHours hours;
|
||||
BusinessLocation location;
|
||||
|
||||
explicit operator bool() const {
|
||||
return hours || location;
|
||||
}
|
||||
|
||||
friend inline bool operator==(
|
||||
const BusinessDetails &a,
|
||||
const BusinessDetails &b) = default;
|
||||
};
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -8,10 +8,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/business/data_business_info.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "data/business/data_business_common.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "main/main_session.h"
|
||||
|
||||
namespace Data {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] MTPBusinessWorkHours ToMTP(const WorkingHours &data) {
|
||||
const auto list = data.intervals.normalized().list;
|
||||
const auto proj = [](const WorkingInterval &data) {
|
||||
return MTPBusinessWeeklyOpen(MTP_businessWeeklyOpen(
|
||||
MTP_int(data.start / 60),
|
||||
MTP_int(data.end / 60)));
|
||||
};
|
||||
return MTP_businessWorkHours(
|
||||
MTP_flags(0),
|
||||
MTP_string(data.timezoneId),
|
||||
MTP_vector_from_range(list | ranges::views::transform(proj)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
BusinessInfo::BusinessInfo(not_null<Session*> owner)
|
||||
: _owner(owner) {
|
||||
|
@ -19,16 +37,20 @@ BusinessInfo::BusinessInfo(not_null<Session*> owner)
|
|||
|
||||
BusinessInfo::~BusinessInfo() = default;
|
||||
|
||||
const WorkingHours &BusinessInfo::workingHours() const {
|
||||
return _workingHours.current();
|
||||
}
|
||||
|
||||
rpl::producer<WorkingHours> BusinessInfo::workingHoursValue() const {
|
||||
return _workingHours.value();
|
||||
}
|
||||
|
||||
void BusinessInfo::saveWorkingHours(WorkingHours data) {
|
||||
_workingHours = std::move(data);
|
||||
auto details = _owner->session().user()->businessDetails();
|
||||
if (details.hours == data) {
|
||||
return;
|
||||
}
|
||||
details.hours = std::move(data);
|
||||
|
||||
using Flag = MTPaccount_UpdateBusinessWorkHours::Flag;
|
||||
_owner->session().api().request(MTPaccount_UpdateBusinessWorkHours(
|
||||
MTP_flags(details.hours ? Flag::f_business_work_hours : Flag()),
|
||||
ToMTP(details.hours)
|
||||
)).send();
|
||||
|
||||
_owner->session().user()->setBusinessDetails(std::move(details));
|
||||
}
|
||||
|
||||
void BusinessInfo::preload() {
|
||||
|
|
|
@ -18,8 +18,6 @@ public:
|
|||
explicit BusinessInfo(not_null<Session*> owner);
|
||||
~BusinessInfo();
|
||||
|
||||
[[nodiscard]] const WorkingHours &workingHours() const;
|
||||
[[nodiscard]] rpl::producer<WorkingHours> workingHoursValue() const;
|
||||
void saveWorkingHours(WorkingHours data);
|
||||
|
||||
void preload();
|
||||
|
@ -29,8 +27,6 @@ public:
|
|||
private:
|
||||
const not_null<Session*> _owner;
|
||||
|
||||
rpl::variable<WorkingHours> _workingHours;
|
||||
|
||||
rpl::variable<Timezones> _timezones;
|
||||
|
||||
mtpRequestId _timezonesRequestId = 0;
|
||||
|
|
|
@ -73,42 +73,43 @@ struct PeerUpdate {
|
|||
TranslationDisabled = (1ULL << 13),
|
||||
Color = (1ULL << 14),
|
||||
BackgroundEmoji = (1ULL << 15),
|
||||
StoriesState = (1ULL << 16),
|
||||
|
||||
// For users
|
||||
CanShareContact = (1ULL << 16),
|
||||
IsContact = (1ULL << 17),
|
||||
PhoneNumber = (1ULL << 18),
|
||||
OnlineStatus = (1ULL << 19),
|
||||
BotCommands = (1ULL << 20),
|
||||
BotCanBeInvited = (1ULL << 21),
|
||||
BotStartToken = (1ULL << 22),
|
||||
CommonChats = (1ULL << 23),
|
||||
HasCalls = (1ULL << 24),
|
||||
SupportInfo = (1ULL << 25),
|
||||
IsBot = (1ULL << 26),
|
||||
EmojiStatus = (1ULL << 27),
|
||||
StoriesState = (1ULL << 28),
|
||||
CanShareContact = (1ULL << 17),
|
||||
IsContact = (1ULL << 18),
|
||||
PhoneNumber = (1ULL << 19),
|
||||
OnlineStatus = (1ULL << 20),
|
||||
BotCommands = (1ULL << 21),
|
||||
BotCanBeInvited = (1ULL << 22),
|
||||
BotStartToken = (1ULL << 23),
|
||||
CommonChats = (1ULL << 24),
|
||||
HasCalls = (1ULL << 25),
|
||||
SupportInfo = (1ULL << 26),
|
||||
IsBot = (1ULL << 27),
|
||||
EmojiStatus = (1ULL << 28),
|
||||
BusinessDetails = (1ULL << 29),
|
||||
|
||||
// For chats and channels
|
||||
InviteLinks = (1ULL << 29),
|
||||
Members = (1ULL << 30),
|
||||
Admins = (1ULL << 31),
|
||||
BannedUsers = (1ULL << 32),
|
||||
Rights = (1ULL << 33),
|
||||
PendingRequests = (1ULL << 34),
|
||||
Reactions = (1ULL << 35),
|
||||
InviteLinks = (1ULL << 30),
|
||||
Members = (1ULL << 31),
|
||||
Admins = (1ULL << 32),
|
||||
BannedUsers = (1ULL << 33),
|
||||
Rights = (1ULL << 34),
|
||||
PendingRequests = (1ULL << 35),
|
||||
Reactions = (1ULL << 36),
|
||||
|
||||
// For channels
|
||||
ChannelAmIn = (1ULL << 36),
|
||||
StickersSet = (1ULL << 37),
|
||||
EmojiSet = (1ULL << 38),
|
||||
ChannelLinkedChat = (1ULL << 39),
|
||||
ChannelLocation = (1ULL << 40),
|
||||
Slowmode = (1ULL << 41),
|
||||
GroupCall = (1ULL << 42),
|
||||
ChannelAmIn = (1ULL << 37),
|
||||
StickersSet = (1ULL << 38),
|
||||
EmojiSet = (1ULL << 39),
|
||||
ChannelLinkedChat = (1ULL << 40),
|
||||
ChannelLocation = (1ULL << 41),
|
||||
Slowmode = (1ULL << 42),
|
||||
GroupCall = (1ULL << 43),
|
||||
|
||||
// For iteration
|
||||
LastUsedBit = (1ULL << 42),
|
||||
LastUsedBit = (1ULL << 43),
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
||||
|
|
|
@ -26,7 +26,6 @@ public:
|
|||
|
||||
[[nodiscard]] size_t hash() const;
|
||||
|
||||
private:
|
||||
friend inline bool operator==(
|
||||
const LocationPoint &a,
|
||||
const LocationPoint &b) {
|
||||
|
@ -39,6 +38,7 @@ private:
|
|||
return (a._lat < b._lat) || ((a._lat == b._lat) && (a._lon < b._lon));
|
||||
}
|
||||
|
||||
private:
|
||||
float64 _lat = 0;
|
||||
float64 _lon = 0;
|
||||
uint64 _access = 0;
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "storage/localstorage.h"
|
||||
#include "storage/storage_user_photos.h"
|
||||
#include "main/main_session.h"
|
||||
#include "data/business/data_business_common.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_peer_bot_command.h"
|
||||
|
@ -30,6 +31,34 @@ constexpr auto kSetOnlineAfterActivity = TimeId(30);
|
|||
|
||||
using UpdateFlag = Data::PeerUpdate::Flag;
|
||||
|
||||
[[nodiscard]] Data::BusinessDetails FromMTP(
|
||||
const tl::conditional<MTPBusinessWorkHours> &hours,
|
||||
const tl::conditional<MTPBusinessLocation> &location) {
|
||||
auto result = Data::BusinessDetails();
|
||||
if (hours) {
|
||||
const auto &data = hours->data();
|
||||
result.hours.timezoneId = qs(data.vtimezone_id());
|
||||
result.hours.intervals.list = ranges::views::all(
|
||||
data.vweekly_open().v
|
||||
) | ranges::views::transform([](const MTPBusinessWeeklyOpen &open) {
|
||||
const auto &data = open.data();
|
||||
return Data::WorkingInterval{
|
||||
data.vstart_minute().v * 60,
|
||||
data.vend_minute().v * 60,
|
||||
};
|
||||
}) | ranges::to_vector;
|
||||
}
|
||||
if (location) {
|
||||
const auto &data = location->data();
|
||||
result.location.address = qs(data.vaddress());
|
||||
data.vgeo_point().match([&](const MTPDgeoPoint &data) {
|
||||
result.location.point = Data::LocationPoint(data);
|
||||
}, [&](const MTPDgeoPointEmpty &) {
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
BotInfo::BotInfo() = default;
|
||||
|
@ -62,6 +91,8 @@ UserData::UserData(not_null<Data::Session*> owner, PeerId id)
|
|||
, _flags((id == owner->session().userPeerId()) ? Flag::Self : Flag(0)) {
|
||||
}
|
||||
|
||||
UserData::~UserData() = default;
|
||||
|
||||
bool UserData::canShareThisContact() const {
|
||||
return canShareThisContactFast()
|
||||
|| !owner().findContactPhone(peerToUser(id)).isEmpty();
|
||||
|
@ -174,6 +205,22 @@ void UserData::setStoriesState(StoriesState state) {
|
|||
}
|
||||
}
|
||||
|
||||
const Data::BusinessDetails &UserData::businessDetails() const {
|
||||
static const auto empty = Data::BusinessDetails();
|
||||
return _businessDetails ? *_businessDetails : empty;
|
||||
}
|
||||
|
||||
void UserData::setBusinessDetails(Data::BusinessDetails details) {
|
||||
if ((!details && !_businessDetails)
|
||||
|| (details && _businessDetails && details == *_businessDetails)) {
|
||||
return;
|
||||
}
|
||||
_businessDetails = details
|
||||
? std::make_unique<Data::BusinessDetails>(std::move(details))
|
||||
: nullptr;
|
||||
session().changes().peerUpdated(this, UpdateFlag::BusinessDetails);
|
||||
}
|
||||
|
||||
void UserData::setName(const QString &newFirstName, const QString &newLastName, const QString &newPhoneName, const QString &newUsername) {
|
||||
bool changeName = !newFirstName.isEmpty() || !newLastName.isEmpty();
|
||||
|
||||
|
@ -572,6 +619,10 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
|
|||
user->setWallPaper({});
|
||||
}
|
||||
|
||||
user->setBusinessDetails(FromMTP(
|
||||
update.vbusiness_work_hours(),
|
||||
update.vbusiness_location()));
|
||||
|
||||
user->owner().stories().apply(user, update.vstories());
|
||||
|
||||
user->fullUpdated();
|
||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Data {
|
||||
struct BotCommand;
|
||||
struct BusinessDetails;
|
||||
} // namespace Data
|
||||
|
||||
struct BotInfo {
|
||||
|
@ -84,6 +85,8 @@ public:
|
|||
using Flags = Data::Flags<UserDataFlags>;
|
||||
|
||||
UserData(not_null<Data::Session*> owner, PeerId id);
|
||||
~UserData();
|
||||
|
||||
void setPhoto(const MTPUserProfilePhoto &photo);
|
||||
|
||||
void setName(
|
||||
|
@ -192,6 +195,9 @@ public:
|
|||
[[nodiscard]] bool hasUnreadStories() const;
|
||||
void setStoriesState(StoriesState state);
|
||||
|
||||
[[nodiscard]] const Data::BusinessDetails &businessDetails() const;
|
||||
void setBusinessDetails(Data::BusinessDetails details);
|
||||
|
||||
private:
|
||||
auto unavailableReasons() const
|
||||
-> const std::vector<Data::UnavailableReason> & override;
|
||||
|
@ -201,6 +207,7 @@ private:
|
|||
|
||||
Data::UsernamesInfo _username;
|
||||
|
||||
std::unique_ptr<Data::BusinessDetails> _businessDetails;
|
||||
std::vector<Data::UnavailableReason> _unavailableReasons;
|
||||
QString _phone;
|
||||
QString _privateForwardName;
|
||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "core/application.h"
|
||||
#include "data/business/data_business_info.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "settings/business/settings_recipients_helper.h"
|
||||
|
@ -50,6 +51,7 @@ private:
|
|||
void save();
|
||||
|
||||
rpl::variable<Data::WorkingHours> _hours;
|
||||
rpl::variable<bool> _enabled;
|
||||
|
||||
};
|
||||
|
||||
|
@ -566,7 +568,7 @@ void WorkingHours::setupContent(
|
|||
const auto state = content->lifetime().make_state<State>(State{
|
||||
.timezones = info->timezonesValue(),
|
||||
});
|
||||
_hours = info->workingHours();
|
||||
_hours = controller->session().user()->businessDetails().hours;
|
||||
|
||||
AddDividerTextWithLottie(content, {
|
||||
.lottie = u"hours"_q,
|
||||
|
@ -582,7 +584,9 @@ void WorkingHours::setupContent(
|
|||
content,
|
||||
tr::lng_hours_show(),
|
||||
st::settingsButtonNoIcon
|
||||
))->toggleOn(rpl::single(false));
|
||||
))->toggleOn(rpl::single(bool(_hours.current())));
|
||||
|
||||
_enabled = enabled->toggledValue();
|
||||
|
||||
const auto wrap = content->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
|
@ -670,7 +674,7 @@ void WorkingHours::setupContent(
|
|||
|
||||
void WorkingHours::save() {
|
||||
controller()->session().data().businessInfo().saveWorkingHours(
|
||||
_hours.current());
|
||||
_enabled.current() ? _hours.current() : Data::WorkingHours());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Add table
Reference in a new issue