mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-25 23:13:11 +02:00
Check premium for todo lists actions.
This commit is contained in:
parent
e5de8e22b7
commit
bf217bf7aa
12 changed files with 155 additions and 8 deletions
|
@ -2636,6 +2636,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_premium_summary_about_effects" = "Add over 500 animated effects to private messages.";
|
||||
"lng_premium_summary_subtitle_filter_tags" = "Tag Your Chats";
|
||||
"lng_premium_summary_about_filter_tags" = "Display folder names for each chat in the chat list.";
|
||||
"lng_premium_summary_subtitle_todo_lists" = "To-Do Lists";
|
||||
"lng_premium_summary_about_todo_lists" = "Create To-Do Lists, I guess..";
|
||||
"lng_premium_summary_bottom_subtitle" = "About Telegram Premium";
|
||||
"lng_premium_summary_bottom_about" = "While the free version of Telegram already gives its users more than any other messaging application, **Telegram Premium** pushes its capabilities even further.\n\n**Telegram Premium** is a paid option, because most Premium Features require additional expenses from Telegram to third parties such as data center providers and server manufacturers. Contributions from **Telegram Premium** users allow us to cover such costs and also help Telegram stay free for everyone.";
|
||||
"lng_premium_summary_button" = "Subscribe for {cost} per month";
|
||||
|
@ -5860,6 +5862,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_todo_completed#one" = "{count} of {total} completed";
|
||||
"lng_todo_completed#other" = "{count} of {total} completed";
|
||||
"lng_todo_completed_none" = "None of {total} completed";
|
||||
"lng_todo_menu_item" = "To-Do List";
|
||||
"lng_todo_create" = "Create To-Do List";
|
||||
"lng_todo_create_title" = "New To-Do List";
|
||||
"lng_todo_create_title_placeholder" = "Title";
|
||||
|
@ -5875,6 +5878,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_todo_choose_title" = "Please enter a title.";
|
||||
"lng_todo_choose_tasks" = "Please enter at least one task.";
|
||||
|
||||
"lng_todo_add_title" = "Add Tasks";
|
||||
"lng_todo_create_premium" = "Only subscribers of {link} can create To-Do Lists.";
|
||||
"lng_todo_add_premium" = "Only subscribers of {link} can add tasks.";
|
||||
"lng_todo_mark_premium" = "Only subscribers of {link} can mark tasks as done.";
|
||||
"lng_todo_premium_link" = "Telegram Premium";
|
||||
"lng_todo_mark_restricted" = "{user} has restricted others from marking tasks as done.";
|
||||
|
||||
"lng_outdated_title" = "PLEASE UPDATE YOUR OPERATING SYSTEM.";
|
||||
"lng_outdated_title_bits" = "PLEASE SWITCH TO A 64-BIT OPERATING SYSTEM.";
|
||||
"lng_outdated_soon" = "Otherwise, Telegram Desktop will stop updating on {date}.";
|
||||
|
|
|
@ -133,6 +133,8 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
|
|||
return tr::lng_premium_summary_subtitle_business();
|
||||
case PremiumFeature::Effects:
|
||||
return tr::lng_premium_summary_subtitle_effects();
|
||||
case PremiumFeature::TodoLists:
|
||||
return tr::lng_premium_summary_subtitle_todo_lists();
|
||||
|
||||
case PremiumFeature::BusinessLocation:
|
||||
return tr::lng_business_subtitle_location();
|
||||
|
@ -198,6 +200,8 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
|
|||
return tr::lng_premium_summary_about_business();
|
||||
case PremiumFeature::Effects:
|
||||
return tr::lng_premium_summary_about_effects();
|
||||
case PremiumFeature::TodoLists:
|
||||
return tr::lng_premium_summary_about_todo_lists();
|
||||
|
||||
case PremiumFeature::BusinessLocation:
|
||||
return tr::lng_business_about_location();
|
||||
|
@ -538,6 +542,7 @@ struct VideoPreviewDocument {
|
|||
case PremiumFeature::LastSeen: return "last_seen";
|
||||
case PremiumFeature::MessagePrivacy: return "message_privacy";
|
||||
case PremiumFeature::Effects: return "effects";
|
||||
case PremiumFeature::TodoLists: return "todo_lists"; AssertIsDebug()
|
||||
|
||||
case PremiumFeature::BusinessLocation: return "business_location";
|
||||
case PremiumFeature::BusinessHours: return "business_hours";
|
||||
|
|
|
@ -72,6 +72,7 @@ enum class PremiumFeature {
|
|||
Business,
|
||||
Effects,
|
||||
FilterTags,
|
||||
TodoLists,
|
||||
|
||||
// Business features.
|
||||
BusinessLocation,
|
||||
|
|
|
@ -2332,7 +2332,10 @@ MediaTodoList::~MediaTodoList() {
|
|||
}
|
||||
|
||||
std::unique_ptr<Media> MediaTodoList::clone(not_null<HistoryItem*> parent) {
|
||||
return std::make_unique<MediaTodoList>(parent, _todolist);
|
||||
const auto id = parent->fullId();
|
||||
return std::make_unique<MediaTodoList>(
|
||||
parent,
|
||||
parent->history()->owner().duplicateTodoList(id, _todolist));
|
||||
}
|
||||
|
||||
TodoListData *MediaTodoList::todolist() const {
|
||||
|
|
|
@ -4142,6 +4142,19 @@ not_null<TodoListData*> Session::processTodoList(
|
|||
return result;
|
||||
}
|
||||
|
||||
not_null<TodoListData*> Session::duplicateTodoList(
|
||||
TodoListId id,
|
||||
not_null<TodoListData*> existing) {
|
||||
const auto result = todoList(id);
|
||||
result->title = existing->title;
|
||||
result->items = existing->items;
|
||||
for (auto &item : result->items) {
|
||||
item.completedBy = nullptr;
|
||||
item.completionDate = TimeId();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Session::checkPollsClosings() {
|
||||
const auto now = base::unixtime::now();
|
||||
auto closest = 0;
|
||||
|
|
|
@ -698,6 +698,9 @@ public:
|
|||
not_null<TodoListData*> processTodoList(
|
||||
TodoListId id,
|
||||
const MTPDmessageMediaToDo &data);
|
||||
[[nodiscard]] not_null<TodoListData*> duplicateTodoList(
|
||||
TodoListId id,
|
||||
not_null<TodoListData*> existing);
|
||||
|
||||
[[nodiscard]] not_null<CloudImage*> location(
|
||||
const LocationPoint &point);
|
||||
|
|
|
@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/view/media/history_view_todo_list.h"
|
||||
|
||||
#include "base/unixtime.h"
|
||||
#include "core/application.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "core/ui_integration.h" // TextContext
|
||||
#include "lang/lang_keys.h"
|
||||
#include "history/history.h"
|
||||
|
@ -35,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "main/main_session.h"
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_todo_lists.h"
|
||||
#include "window/window_peer_menu.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_window.h"
|
||||
|
@ -324,6 +327,18 @@ void TodoList::startToggleAnimation(Task &task) {
|
|||
}
|
||||
|
||||
void TodoList::toggleCompletion(int id) {
|
||||
if (!canComplete()) {
|
||||
_parent->delegate()->elementShowTooltip(
|
||||
tr::lng_todo_mark_restricted(
|
||||
tr::now,
|
||||
lt_user,
|
||||
Ui::Text::Bold(_parent->data()->from()->shortName()),
|
||||
Ui::Text::RichLangValue), [] {});
|
||||
return;
|
||||
} else if (!_parent->history()->session().premium()) {
|
||||
Window::PeerMenuTodoWantsPremium(Window::TodoWantsPremium::Mark);
|
||||
return;
|
||||
}
|
||||
const auto i = ranges::find(
|
||||
_tasks,
|
||||
id,
|
||||
|
@ -477,7 +492,11 @@ int TodoList::paintTask(
|
|||
p.setOpacity(1.);
|
||||
}
|
||||
|
||||
paintRadio(p, task, left, top, context);
|
||||
if (canComplete()) {
|
||||
paintRadio(p, task, left, top, context);
|
||||
} else {
|
||||
paintStatus(p, task, left, top, context);
|
||||
}
|
||||
|
||||
top += st::historyPollAnswerPadding.top();
|
||||
p.setPen(stm->historyTextFg);
|
||||
|
@ -584,6 +603,39 @@ void TodoList::paintRadio(
|
|||
p.setOpacity(o);
|
||||
}
|
||||
|
||||
void TodoList::paintStatus(
|
||||
Painter &p,
|
||||
const Task &task,
|
||||
int left,
|
||||
int top,
|
||||
const PaintContext &context) const {
|
||||
top += st::historyPollAnswerPadding.top();
|
||||
|
||||
const auto stm = context.messageStyle();
|
||||
|
||||
const auto &radio = st::historyPollRadio;
|
||||
const auto completed = (task.completionDate != 0);
|
||||
|
||||
const auto rect = QRect(left, top, radio.diameter, radio.diameter);
|
||||
if (completed) {
|
||||
const auto &icon = stm->historyPollChosen;
|
||||
icon.paint(
|
||||
p,
|
||||
left + (radio.diameter - icon.width()) / 2,
|
||||
top + (radio.diameter - icon.height()) / 2,
|
||||
width(),
|
||||
stm->msgFileBg->c);
|
||||
} else {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(stm->msgFileBg);
|
||||
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.drawEllipse(style::centerrect(
|
||||
rect,
|
||||
QRect(0, 0, st::mediaUnreadSize, st::mediaUnreadSize)));
|
||||
}
|
||||
}
|
||||
|
||||
TextSelection TodoList::adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const {
|
||||
|
@ -600,7 +652,6 @@ TextForMimeData TodoList::selectedText(TextSelection selection) const {
|
|||
|
||||
TextState TodoList::textState(QPoint point, StateRequest request) const {
|
||||
auto result = TextState(_parent);
|
||||
const auto can = canComplete();
|
||||
const auto padding = st::msgPadding;
|
||||
auto paintw = width();
|
||||
auto tshift = st::historyPollQuestionTop;
|
||||
|
@ -622,10 +673,9 @@ TextState TodoList::textState(QPoint point, StateRequest request) const {
|
|||
for (const auto &task : _tasks) {
|
||||
const auto height = countTaskHeight(task, paintw);
|
||||
if (point.y() >= tshift && point.y() < tshift + height) {
|
||||
if (can) {
|
||||
_lastLinkPoint = point;
|
||||
result.link = task.handler;
|
||||
} else if (task.completionDate) {
|
||||
_lastLinkPoint = point;
|
||||
result.link = task.handler;
|
||||
if (task.completionDate) {
|
||||
result.customTooltip = true;
|
||||
using Flag = Ui::Text::StateRequest::Flag;
|
||||
if (request.flags & Flag::LookupCustomTooltip) {
|
||||
|
|
|
@ -103,6 +103,12 @@ private:
|
|||
int left,
|
||||
int top,
|
||||
const PaintContext &context) const;
|
||||
void paintStatus(
|
||||
Painter &p,
|
||||
const Task &task,
|
||||
int left,
|
||||
int top,
|
||||
const PaintContext &context) const;
|
||||
void paintBottom(
|
||||
Painter &p,
|
||||
int left,
|
||||
|
|
|
@ -2628,7 +2628,7 @@ std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
|
|||
}
|
||||
if (peer->canCreateTodoLists()) {
|
||||
++minimal;
|
||||
raw->addAction(tr::lng_todo_create(tr::now), [=] {
|
||||
raw->addAction(tr::lng_todo_menu_item(tr::now), [=] {
|
||||
const auto action = actionFactory();
|
||||
const auto source = action.options.scheduled
|
||||
? Api::SendType::Scheduled
|
||||
|
|
|
@ -386,6 +386,15 @@ using Order = std::vector<QString>;
|
|||
PremiumFeature::Effects,
|
||||
},
|
||||
},
|
||||
{
|
||||
u"todo_lists"_q,AssertIsDebug()
|
||||
Entry{
|
||||
&st::settingsPremiumIconTranslations,
|
||||
tr::lng_premium_summary_subtitle_todo_lists(),
|
||||
tr::lng_premium_summary_about_todo_lists(),
|
||||
PremiumFeature::TodoLists,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1608,6 +1617,8 @@ std::vector<PremiumFeature> PremiumFeaturesOrder(
|
|||
return PremiumFeature::Wallpapers;
|
||||
} else if (s == u"effects"_q) {
|
||||
return PremiumFeature::Effects;
|
||||
} else if (s == u"todo_lists"_q) {AssertIsDebug()
|
||||
return PremiumFeature::TodoLists;
|
||||
}
|
||||
return PremiumFeature::kCount;
|
||||
}) | ranges::views::filter([](PremiumFeature type) {
|
||||
|
|
|
@ -98,6 +98,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "core/application.h"
|
||||
#include "export/export_manager.h"
|
||||
#include "boxes/peers/edit_peer_info_box.h"
|
||||
#include "boxes/premium_preview_box.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
@ -1920,12 +1921,50 @@ void PeerMenuCreatePoll(
|
|||
controller->show(std::move(box), Ui::LayerOption::CloseOther);
|
||||
}
|
||||
|
||||
void PeerMenuTodoWantsPremium(TodoWantsPremium type) {
|
||||
const auto window = Core::App().activeWindow();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
const auto filter = [=](const auto &...) {
|
||||
if (const auto controller = window->sessionController()) {
|
||||
ShowPremiumPreviewBox(controller, PremiumFeature::TodoLists);
|
||||
window->activate();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const auto link = Ui::Text::Link(
|
||||
Ui::Text::Semibold(tr::lng_todo_premium_link(tr::now)));
|
||||
const auto text = [&] {
|
||||
switch (type) {
|
||||
case TodoWantsPremium::Create: return tr::lng_todo_create_premium;
|
||||
case TodoWantsPremium::Add: return tr::lng_todo_add_premium;
|
||||
case TodoWantsPremium::Mark: return tr::lng_todo_mark_premium;
|
||||
}
|
||||
Unexpected("Type in PeerMenuTodoWantsPremium.");
|
||||
}();
|
||||
constexpr auto kToastDuration = crl::time(4000);
|
||||
window->uiShow()->showToast(Ui::Toast::Config{
|
||||
.text = text(
|
||||
tr::now,
|
||||
lt_link,
|
||||
link,
|
||||
Ui::Text::WithEntities),
|
||||
.filter = filter,
|
||||
.duration = kToastDuration,
|
||||
});
|
||||
}
|
||||
|
||||
void PeerMenuCreateTodoList(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<PeerData*> peer,
|
||||
FullReplyTo replyTo,
|
||||
Api::SendType sendType,
|
||||
SendMenu::Details sendMenuDetails) {
|
||||
if (!peer->session().premium()) {
|
||||
PeerMenuTodoWantsPremium(TodoWantsPremium::Create);
|
||||
return;
|
||||
}
|
||||
auto starsRequired = peer->session().changes().peerFlagsValue(
|
||||
peer,
|
||||
Data::PeerUpdate::Flag::FullInfo
|
||||
|
|
|
@ -111,6 +111,12 @@ void PeerMenuCreatePoll(
|
|||
PollData::Flags disabled = PollData::Flags(),
|
||||
Api::SendType sendType = Api::SendType::Normal,
|
||||
SendMenu::Details sendMenuDetails = SendMenu::Details());
|
||||
enum class TodoWantsPremium {
|
||||
Create,
|
||||
Add,
|
||||
Mark,
|
||||
};
|
||||
void PeerMenuTodoWantsPremium(TodoWantsPremium type);
|
||||
void PeerMenuCreateTodoList(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<PeerData*> peer,
|
||||
|
|
Loading…
Add table
Reference in a new issue