Fix Cursor rules files.

This commit is contained in:
John Preston 2025-05-05 21:01:23 +04:00
parent 57d24d0fbf
commit 1d2f713673
4 changed files with 44 additions and 24 deletions

View file

@ -1,8 +1,13 @@
---
description: For tasks requiring sending Telegram server API requests or working with generated API types.
globs:
alwaysApply: false
---
# Telegram Desktop API Usage # Telegram Desktop API Usage
## API Schema ## API Schema
The API definitions are described using [TL Language](https://core.telegram.org/mtproto/TL) in two main schema files: The API definitions are described using [TL Language]\(https:/core.telegram.org/mtproto/TL) in two main schema files:
1. **`Telegram/SourceFiles/mtproto/scheme/mtproto.tl`** 1. **`Telegram/SourceFiles/mtproto/scheme/mtproto.tl`**
* Defines the core MTProto protocol types and methods used for basic communication, encryption, authorization, service messages, etc. * Defines the core MTProto protocol types and methods used for basic communication, encryption, authorization, service messages, etc.
@ -39,7 +44,7 @@ api().request(MTPnamespace_MethodName(
MTP_long(randomId), MTP_long(randomId),
// ... other arguments matching the TL definition // ... other arguments matching the TL definition
MTP_vector<MTPMessageEntity>() // Example for a vector argument MTP_vector<MTPMessageEntity>() // Example for a vector argument
)).done([=](const MTPResponseType &result) { )).done([=]\(const MTPResponseType &result) {
// Handle the successful response (result). // Handle the successful response (result).
// 'result' will be of the C++ type corresponding to the TL type // 'result' will be of the C++ type corresponding to the TL type
// specified after the '=' in the api.tl method definition. // specified after the '=' in the api.tl method definition.
@ -47,9 +52,9 @@ api().request(MTPnamespace_MethodName(
// 1. Multiple Constructors (e.g., User = User | UserEmpty): // 1. Multiple Constructors (e.g., User = User | UserEmpty):
// Use .match() with lambdas for each constructor: // Use .match() with lambdas for each constructor:
result.match([&](const MTPDuser &data) { result.match([&]\(const MTPDuser &data) {
/* use data.vfirst_name().v, etc. */ /* use data.vfirst_name().v, etc. */
}, [&](const MTPDuserEmpty &data) { }, [&]\(const MTPDuserEmpty &data) {
/* handle empty user */ /* handle empty user */
}); });
@ -64,7 +69,7 @@ api().request(MTPnamespace_MethodName(
// 2. Single Constructor (e.g., Messages = messages { msgs: vector<Message> }): // 2. Single Constructor (e.g., Messages = messages { msgs: vector<Message> }):
// Use .match() with a single lambda: // Use .match() with a single lambda:
result.match([&](const MTPDmessages &data) { /* use data.vmessages().v */ }); result.match([&]\(const MTPDmessages &data) { /* use data.vmessages().v */ });
// Or check the type explicitly and use the constructor getter: // Or check the type explicitly and use the constructor getter:
if (result.type() == mtpc_messages) { if (result.type() == mtpc_messages) {
@ -76,7 +81,7 @@ api().request(MTPnamespace_MethodName(
const auto &data = result.data(); // Only works for single-constructor types! const auto &data = result.data(); // Only works for single-constructor types!
// use data.vmessages().v // use data.vmessages().v
}).fail([=](const MTP::Error &error) { }).fail([=]\(const MTP::Error &error) {
// Handle the API error (error). // Handle the API error (error).
// 'error' is an MTP::Error object containing the error code (error.type()) // 'error' is an MTP::Error object containing the error code (error.type())
// and description (error.description()). Check for specific error strings. // and description (error.description()). Check for specific error strings.
@ -93,8 +98,8 @@ api().request(MTPnamespace_MethodName(
* Always refer to `Telegram/SourceFiles/mtproto/scheme/api.tl` for the correct method names, parameters (names and types), and response types. * Always refer to `Telegram/SourceFiles/mtproto/scheme/api.tl` for the correct method names, parameters (names and types), and response types.
* Use the generated `MTP...` types/classes for request parameters (e.g., `MTP_int`, `MTP_string`, `MTP_bool`, `MTP_vector`, `MTPInputUser`, etc.) and response handling. * Use the generated `MTP...` types/classes for request parameters (e.g., `MTP_int`, `MTP_string`, `MTP_bool`, `MTP_vector`, `MTPInputUser`, etc.) and response handling.
* The `.done()` lambda receives the specific C++ `MTP...` type corresponding to the TL return type. * The `.done()` lambda receives the specific C++ `MTP...` type corresponding to the TL return type.
* For types with **multiple constructors** (e.g., `User = User | UserEmpty`), use `result.match([&](const MTPDuser &d){ ... }, [&](const MTPDuserEmpty &d){ ... })` to handle each case, or check `result.type() == mtpc_user` / `mtpc_userEmpty` and call the specific `result.c_user()` / `result.c_userEmpty()` getter (which asserts on type mismatch). * For types with **multiple constructors** (e.g., `User = User | UserEmpty`), use `result.match([&]\(const MTPDuser &d){ ... }, [&]\(const MTPDuserEmpty &d){ ... })` to handle each case, or check `result.type() == mtpc_user` / `mtpc_userEmpty` and call the specific `result.c_user()` / `result.c_userEmpty()` getter (which asserts on type mismatch).
* For types with a **single constructor** (e.g., `Messages = messages{...}`), you can use `result.match([&](const MTPDmessages &d){ ... })` with one lambda, or check `type()` and call `c_messages()`, or use the shortcut `result.data()` to access the fields directly. * For types with a **single constructor** (e.g., `Messages = messages{...}`), you can use `result.match([&]\(const MTPDmessages &d){ ... })` with one lambda, or check `type()` and call `c_messages()`, or use the shortcut `result.data()` to access the fields directly.
* The `.fail()` lambda receives an `MTP::Error` object. Check `error.type()` against known error strings (often defined as constants or using `u"..."_q` literals). * The `.fail()` lambda receives an `MTP::Error` object. Check `error.type()` against known error strings (often defined as constants or using `u"..."_q` literals).
* Directly construct the `MTPnamespace_MethodName(...)` object inside `request()`. * Directly construct the `MTPnamespace_MethodName(...)` object inside `request()`.
* Include `.handleFloodErrors()` before `.send()` for standard flood wait handling. * Include `.handleFloodErrors()` before `.send()` for standard flood wait handling.

View file

@ -1,3 +1,8 @@
---
description: For tasks requiring changing or adding user facing phrases and text parts.
globs:
alwaysApply: false
---
# Telegram Desktop Localization # Telegram Desktop Localization
## Coding Style Note ## Coding Style Note
@ -156,4 +161,4 @@ auto messageProducer = tr::lng_user_posted_photo( // Type: rpl::producer<TextWit
* Immediate: Pass `int` or `float64`. * Immediate: Pass `int` or `float64`.
* Reactive: Pass `rpl::producer<float64>`, typically by converting an `int` producer using `| tr::to_count()`. * Reactive: Pass `rpl::producer<float64>`, typically by converting an `int` producer using `| tr::to_count()`.
* Optional projector function as the last argument modifies the output type and required placeholder types. * Optional projector function as the last argument modifies the output type and required placeholder types.
* Actual translations are loaded at runtime from the API. * Actual translations are loaded at runtime from the API.

View file

@ -1,3 +1,8 @@
---
description:
globs:
alwaysApply: true
---
# RPL (Reactive Programming Library) Guide # RPL (Reactive Programming Library) Guide
## Coding Style Note ## Coding Style Note
@ -64,7 +69,7 @@ rpl::lifetime lifetime;
// Counter is consumed here, use std::move if it's an l-value. // Counter is consumed here, use std::move if it's an l-value.
std::move( std::move(
counter counter
) | rpl::start_with_next([=](int nextValue) { ) | rpl::start_with_next([=]\(int nextValue) {
// Process the next integer value emitted by the producer. // Process the next integer value emitted by the producer.
qDebug() << "Received: " << nextValue; qDebug() << "Received: " << nextValue;
}, lifetime); // Pass the lifetime to manage the subscription. }, lifetime); // Pass the lifetime to manage the subscription.
@ -77,7 +82,7 @@ std::move(
auto counter2 = /* ... */; // Type: rpl::producer<int> auto counter2 = /* ... */; // Type: rpl::producer<int>
rpl::lifetime subscriptionLifetime = std::move( rpl::lifetime subscriptionLifetime = std::move(
counter2 counter2
) | rpl::start_with_next([=](int nextValue) { /* ... */ }); ) | rpl::start_with_next([=]\(int nextValue) { /* ... */ });
// The returned lifetime MUST be stored. If it's discarded immediately, // The returned lifetime MUST be stored. If it's discarded immediately,
// the subscription stops instantly. // the subscription stops instantly.
// `counter2` is also moved-from here. // `counter2` is also moved-from here.
@ -93,7 +98,7 @@ rpl::lifetime lifetime;
// If it's the only use, std::move(dataStream) would be preferred. // If it's the only use, std::move(dataStream) would be preferred.
rpl::duplicate( rpl::duplicate(
dataStream dataStream
) | rpl::start_with_error([=](Error &&error) { ) | rpl::start_with_error([=]\(Error &&error) {
// Handle the error signaled by the producer. // Handle the error signaled by the producer.
qDebug() << "Error: " << error.text(); qDebug() << "Error: " << error.text();
}, lifetime); }, lifetime);
@ -101,7 +106,7 @@ rpl::duplicate(
// Using dataStream again, perhaps duplicated again or moved if last use. // Using dataStream again, perhaps duplicated again or moved if last use.
rpl::duplicate( rpl::duplicate(
dataStream dataStream
) | rpl::start_with_done([=]() { ) | rpl::start_with_done([=] {
// Execute when the producer signals it's finished emitting values. // Execute when the producer signals it's finished emitting values.
qDebug() << "Stream finished."; qDebug() << "Stream finished.";
}, lifetime); }, lifetime);
@ -110,9 +115,9 @@ rpl::duplicate(
std::move( std::move(
dataStream dataStream
) | rpl::start_with_next_error_done( ) | rpl::start_with_next_error_done(
[=](QString &&value) { /* handle next value */ }, [=]\(QString &&value) { /* handle next value */ },
[=](Error &&error) { /* handle error */ }, [=]\(Error &&error) { /* handle error */ },
[=]() { /* handle done */ }, [=] { /* handle done */ },
lifetime); lifetime);
``` ```
@ -164,7 +169,7 @@ You can combine multiple producers into one:
// The lambda receives unpacked arguments, not the tuple itself. // The lambda receives unpacked arguments, not the tuple itself.
std::move( std::move(
combined combined
) | rpl::start_with_next([=](int count, const QString &text) { ) | rpl::start_with_next([=]\(int count, const QString &text) {
// No need for std::get<0>(latest), etc. // No need for std::get<0>(latest), etc.
qDebug() << "Combined: Count=" << count << ", Text=" << text; qDebug() << "Combined: Count=" << count << ", Text=" << text;
}, lifetime); }, lifetime);
@ -172,11 +177,11 @@ You can combine multiple producers into one:
// This also works with map, filter, etc. // This also works with map, filter, etc.
std::move( std::move(
combined combined
) | rpl::filter([=](int count, const QString &text) { ) | rpl::filter([=]\(int count, const QString &text) {
return count > 0 && !text.isEmpty(); return count > 0 && !text.isEmpty();
}) | rpl::map([=](int count, const QString &text) { }) | rpl::map([=]\(int count, const QString &text) {
return text.repeated(count); return text.repeated(count);
}) | rpl::start_with_next([=](const QString &result) { }) | rpl::start_with_next([=]\(const QString &result) {
qDebug() << "Mapped & Filtered: " << result; qDebug() << "Mapped & Filtered: " << result;
}, lifetime); }, lifetime);
``` ```
@ -192,7 +197,7 @@ You can combine multiple producers into one:
// Starting the merged producer consumes it. // Starting the merged producer consumes it.
std::move( std::move(
merged merged
) | rpl::start_with_next([=](QString &&value) { ) | rpl::start_with_next([=]\(QString &&value) {
// Receives values from either sourceA or sourceB as they arrive. // Receives values from either sourceA or sourceB as they arrive.
qDebug() << "Merged value: " << value; qDebug() << "Merged value: " << value;
}, lifetime); }, lifetime);
@ -208,4 +213,4 @@ You can combine multiple producers into one:
* Use `rpl::combine` or `rpl::merge` to combine streams. * Use `rpl::combine` or `rpl::merge` to combine streams.
* When starting a chain (`std::move(producer) | rpl::map(...)`), explicitly move the initial producer. * When starting a chain (`std::move(producer) | rpl::map(...)`), explicitly move the initial producer.
* These functions typically duplicate their input producers internally. * These functions typically duplicate their input producers internally.
* Starting a pipeline consumes the producer; use ` * Starting a pipeline consumes the producer; use `

View file

@ -1,3 +1,8 @@
---
description: For tasks requiring working with user facing UI components.
globs:
alwaysApply: false
---
# Telegram Desktop UI Styling # Telegram Desktop UI Styling
## Style Definition Files ## Style Definition Files
@ -146,4 +151,4 @@ void MyWidget::paintEvent(QPaintEvent *e) {
* Icons are defined inline using `name: icon{{ "path_stem", color }};` or `name: icon{ { "path1", c1 }, ... };` syntax, with optional path modifiers. * Icons are defined inline using `name: icon{{ "path_stem", color }};` or `name: icon{ { "path1", c1 }, ... };` syntax, with optional path modifiers.
* Code generation creates `struct` definitions in the `style` namespace for custom types and objects/structs in the `st` namespace for defined variables/groups. * Code generation creates `struct` definitions in the `style` namespace for custom types and objects/structs in the `st` namespace for defined variables/groups.
* Generated headers are in `styles/` with a `style_` prefix and must be included. * Generated headers are in `styles/` with a `style_` prefix and must be included.
* Access style properties via the generated `st::` objects (e.g., `st::primaryButton.height`, `st::chatInput.backgroundColor`). * Access style properties via the generated `st::` objects (e.g., `st::primaryButton.height`, `st::chatInput.backgroundColor`).