Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7958f5235 | ||
|
|
2ae5fc0fac |
@@ -1,105 +0,0 @@
|
||||
---
|
||||
description: For tasks requiring sending Telegram server API requests or working with generated API types.
|
||||
globs:
|
||||
alwaysApply: false
|
||||
---
|
||||
# Telegram Desktop API Usage
|
||||
|
||||
## API Schema
|
||||
|
||||
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`**
|
||||
* Defines the core MTProto protocol types and methods used for basic communication, encryption, authorization, service messages, etc.
|
||||
* Some fundamental types and methods from this schema (like basic types, RPC calls, containers) are often implemented directly in the C++ MTProto core (`SourceFiles/mtproto/`) and may be skipped during the C++ code generation phase.
|
||||
* Other parts of `mtproto.tl` might still be processed by the code generator.
|
||||
|
||||
2. **`Telegram/SourceFiles/mtproto/scheme/api.tl`**
|
||||
* Defines the higher-level Telegram API layer, including all the methods and types related to chat functionality, user profiles, messages, channels, stickers, etc.
|
||||
* This is the primary schema used when making functional API requests within the application.
|
||||
|
||||
Both files use the same TL syntax to describe API methods (functions) and types (constructors).
|
||||
|
||||
## Code Generation
|
||||
|
||||
A custom code generation tool processes `api.tl` (and parts of `mtproto.tl`) to create corresponding C++ classes and types. These generated headers are typically included via the Precompiled Header (PCH) for the main `Telegram` project.
|
||||
|
||||
Generated types often follow the pattern `MTP[Type]` (e.g., `MTPUser`, `MTPMessage`) and methods correspond to functions within the `MTP` namespace or related classes (e.g., `MTPmessages_SendMessage`).
|
||||
|
||||
## Making API Requests
|
||||
|
||||
API requests are made using a standard pattern involving the `api()` object (providing access to the `MTP::Instance`), the generated `MTP...` request object, callback handlers for success (`.done()`) and failure (`.fail()`), and the `.send()` method.
|
||||
|
||||
Here's the general structure:
|
||||
|
||||
```cpp
|
||||
// Include necessary headers if not already in PCH
|
||||
|
||||
// Obtain the API instance (usually via api() or MTP::Instance::Get())
|
||||
api().request(MTPnamespace_MethodName(
|
||||
// Constructor arguments based on the api.tl definition for the method
|
||||
MTP_flags(flags_value), // Use MTP_flags if the method has flags
|
||||
MTP_inputPeer(peer), // Use MTP_... types for parameters
|
||||
MTP_string(messageText),
|
||||
MTP_long(randomId),
|
||||
// ... other arguments matching the TL definition
|
||||
MTP_vector<MTPMessageEntity>() // Example for a vector argument
|
||||
)).done([=]\(const MTPResponseType &result) {
|
||||
// Handle the successful response (result).
|
||||
// 'result' will be of the C++ type corresponding to the TL type
|
||||
// specified after the '=' in the api.tl method definition.
|
||||
// How to access data depends on whether the TL type has one or multiple constructors:
|
||||
|
||||
// 1. Multiple Constructors (e.g., User = User | UserEmpty):
|
||||
// Use .match() with lambdas for each constructor:
|
||||
result.match([&]\(const MTPDuser &data) {
|
||||
/* use data.vfirst_name().v, etc. */
|
||||
}, [&]\(const MTPDuserEmpty &data) {
|
||||
/* handle empty user */
|
||||
});
|
||||
|
||||
// Alternatively, check the type explicitly and use the constructor getter:
|
||||
if (result.type() == mtpc_user) {
|
||||
const auto &data = result.c_user(); // Asserts if type is not mtpc_user!
|
||||
// use data.vfirst_name().v
|
||||
} else if (result.type() == mtpc_userEmpty) {
|
||||
const auto &data = result.c_userEmpty();
|
||||
// handle empty user
|
||||
}
|
||||
|
||||
// 2. Single Constructor (e.g., Messages = messages { msgs: vector<Message> }):
|
||||
// Use .match() with a single lambda:
|
||||
result.match([&]\(const MTPDmessages &data) { /* use data.vmessages().v */ });
|
||||
|
||||
// Or check the type explicitly and use the constructor getter:
|
||||
if (result.type() == mtpc_messages) {
|
||||
const auto &data = result.c_messages(); // Asserts if type is not mtpc_messages!
|
||||
// use data.vmessages().v
|
||||
}
|
||||
|
||||
// Or use the shortcut .data() for single-constructor types:
|
||||
const auto &data = result.data(); // Only works for single-constructor types!
|
||||
// use data.vmessages().v
|
||||
|
||||
}).fail([=]\(const MTP::Error &error) {
|
||||
// Handle the API error (error).
|
||||
// 'error' is an MTP::Error object containing the error code (error.type())
|
||||
// and description (error.description()). Check for specific error strings.
|
||||
if (error.type() == u"FLOOD_WAIT_X"_q) {
|
||||
// Handle flood wait
|
||||
} else {
|
||||
Ui::show(Box<InformBox>(Lang::Hard::ServerError())); // Example generic error handling
|
||||
}
|
||||
}).handleFloodErrors().send(); // handleFloodErrors() is common, then send()
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
|
||||
* 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.
|
||||
* 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 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).
|
||||
* Directly construct the `MTPnamespace_MethodName(...)` object inside `request()`.
|
||||
* Include `.handleFloodErrors()` before `.send()` for standard flood wait handling.
|
||||
@@ -1,164 +0,0 @@
|
||||
---
|
||||
description: For tasks requiring changing or adding user facing phrases and text parts.
|
||||
globs:
|
||||
alwaysApply: false
|
||||
---
|
||||
# Telegram Desktop Localization
|
||||
|
||||
## Coding Style Note
|
||||
|
||||
**Use `auto`:** In the actual codebase, variable types are almost always deduced using `auto` (or `const auto`, `const auto &`) rather than being written out explicitly. Examples in this guide may use explicit types for clarity, but prefer `auto` in practice.
|
||||
|
||||
```cpp
|
||||
// Prefer this:
|
||||
auto currentTitle = tr::lng_settings_title(tr::now);
|
||||
auto nameProducer = GetNameProducer(); // Returns rpl::producer<...>
|
||||
|
||||
// Instead of this:
|
||||
QString currentTitle = tr::lng_settings_title(tr::now);
|
||||
rpl::producer<QString> nameProducer = GetNameProducer();
|
||||
```
|
||||
|
||||
## String Resource File
|
||||
|
||||
Base user-facing English strings are defined in the `lang.strings` file:
|
||||
|
||||
`Telegram/Resources/langs/lang.strings`
|
||||
|
||||
This file uses a key-value format with named placeholders:
|
||||
|
||||
```
|
||||
"lng_settings_title" = "Settings";
|
||||
"lng_confirm_delete_item" = "Are you sure you want to delete {item_name}?";
|
||||
"lng_files_selected" = "{count} files selected"; // Simple count example (see Pluralization)
|
||||
```
|
||||
|
||||
Placeholders are enclosed in curly braces, e.g., `{name}`, `{user}`. A special placeholder `{count}` is used for pluralization rules.
|
||||
|
||||
### Pluralization
|
||||
|
||||
For keys that depend on a number (using the `{count}` placeholder), English typically requires two forms: singular and plural. These are defined in `lang.strings` using `#one` and `#other` suffixes:
|
||||
|
||||
```
|
||||
"lng_files_selected#one" = "{count} file selected";
|
||||
"lng_files_selected#other" = "{count} files selected";
|
||||
```
|
||||
|
||||
While only `#one` and `#other` are defined in the base `lang.strings`, the code generation process creates C++ accessors for all six CLDR plural categories (`#zero`, `#one`, `#two`, `#few`, `#many`, `#other`) to support languages with more complex pluralization rules.
|
||||
|
||||
## Translation Process
|
||||
|
||||
While `lang.strings` provides the base English text and the keys, the actual translations are managed via Telegram's translations platform (translations.telegram.org) and loaded dynamically at runtime from the API. The keys from `lang.strings` (including the `#one`/`#other` variants) are used on the platform.
|
||||
|
||||
## Code Generation
|
||||
|
||||
A code generation tool processes `lang.strings` to create C++ structures and accessors within the `tr` namespace. These allow type-safe access to strings and handling of placeholders and pluralization. Generated keys typically follow the pattern `tr::lng_key_name`.
|
||||
|
||||
## String Usage in Code
|
||||
|
||||
Strings are accessed in C++ code using the generated objects within the `tr::` namespace. There are two main ways to use them: reactively (returning an `rpl::producer`) or immediately (returning the current value).
|
||||
|
||||
### 1. Reactive Usage (rpl::producer)
|
||||
|
||||
Calling a generated string function directly returns a reactive producer, typically `rpl::producer<QString>`. This producer automatically updates its value whenever the application language changes.
|
||||
|
||||
```cpp
|
||||
// Key: "settings_title" = "Settings";
|
||||
auto titleProducer = tr::lng_settings_title(); // Type: rpl::producer<QString>
|
||||
|
||||
// Key: "confirm_delete_item" = "Are you sure you want to delete {item_name}?";
|
||||
auto itemNameProducer = /* ... */; // Type: rpl::producer<QString>
|
||||
auto confirmationProducer = tr::lng_confirm_delete_item( // Type: rpl::producer<QString>
|
||||
tr::now, // NOTE: tr::now is NOT passed here for reactive result
|
||||
lt_item_name,
|
||||
std::move(itemNameProducer)); // Placeholder producers should be moved
|
||||
```
|
||||
|
||||
### 2. Immediate Usage (Current Value)
|
||||
|
||||
Passing `tr::now` as the first argument retrieves the string's current value in the active language (typically as a `QString`).
|
||||
|
||||
```cpp
|
||||
// Key: "settings_title" = "Settings";
|
||||
auto currentTitle = tr::lng_settings_title(tr::now); // Type: QString
|
||||
|
||||
// Key: "confirm_delete_item" = "Are you sure you want to delete {item_name}?";
|
||||
const auto currentItemName = QString("My Document"); // Type: QString
|
||||
auto currentConfirmation = tr::lng_confirm_delete_item( // Type: QString
|
||||
tr::now, // Pass tr::now for immediate value
|
||||
lt_item_name, currentItemName); // Placeholder value is a direct QString (or convertible)
|
||||
```
|
||||
|
||||
### 3. Placeholders (`{tag}`)
|
||||
|
||||
Placeholders like `{item_name}` are replaced by providing arguments after `tr::now` (for immediate) or as the initial arguments (for reactive). A corresponding `lt_tag_name` constant is passed before the value.
|
||||
|
||||
* **Immediate:** Pass the direct value (e.g., `QString`, `int`).
|
||||
* **Reactive:** Pass an `rpl::producer` of the corresponding type (e.g., `rpl::producer<QString>`). Remember to `std::move` the producer or use `rpl::duplicate` if you need to reuse the original producer afterwards.
|
||||
|
||||
### 4. Pluralization (`{count}`)
|
||||
|
||||
Keys using `{count}` require a numeric value for the `lt_count` placeholder. The correct plural form (`#zero`, `#one`, ..., `#other`) is automatically selected based on this value and the current language rules.
|
||||
|
||||
* **Immediate (`tr::now`):** Pass a `float64` or `int` (which is auto-converted to `float64`).
|
||||
```cpp
|
||||
int count = 1;
|
||||
auto filesText = tr::lng_files_selected(tr::now, lt_count, count); // Type: QString
|
||||
count = 5;
|
||||
filesText = tr::lng_files_selected(tr::now, lt_count, count); // Uses "files_selected#other"
|
||||
```
|
||||
|
||||
* **Reactive:** Pass an `rpl::producer<float64>`. Use the `tr::to_count()` helper to convert an `rpl::producer<int>` or wrap a single value.
|
||||
```cpp
|
||||
// From an existing int producer:
|
||||
auto countProducer = /* ... */; // Type: rpl::producer<int>
|
||||
auto filesTextProducer = tr::lng_files_selected( // Type: rpl::producer<QString>
|
||||
lt_count,
|
||||
countProducer | tr::to_count()); // Use tr::to_count() for conversion
|
||||
|
||||
// From a single int value wrapped reactively:
|
||||
int currentCount = 5;
|
||||
auto filesTextProducerSingle = tr::lng_files_selected( // Type: rpl::producer<QString>
|
||||
lt_count,
|
||||
rpl::single(currentCount) | tr::to_count());
|
||||
// Alternative for single values (less common): rpl::single(currentCount * 1.)
|
||||
```
|
||||
|
||||
### 5. Custom Projectors
|
||||
|
||||
An optional final argument can be a projector function (like `Ui::Text::Upper` or `Ui::Text::WithEntities`) to transform the output.
|
||||
|
||||
* If the projector returns `OutputType`, the string function returns `OutputType` (immediate) or `rpl::producer<OutputType>` (reactive).
|
||||
* Placeholder values must match the projector's *input* requirements. For `Ui::Text::WithEntities`, placeholders expect `TextWithEntities` (immediate) or `rpl::producer<TextWithEntities>` (reactive).
|
||||
|
||||
```cpp
|
||||
// Immediate with Ui::Text::WithEntities projector
|
||||
// Key: "user_posted_photo" = "{user} posted a photo";
|
||||
const auto userName = TextWithEntities{ /* ... */ }; // Type: TextWithEntities
|
||||
auto message = tr::lng_user_posted_photo( // Type: TextWithEntities
|
||||
tr::now,
|
||||
lt_user,
|
||||
userName, // Must be TextWithEntities
|
||||
Ui::Text::WithEntities); // Projector
|
||||
|
||||
// Reactive with Ui::Text::WithEntities projector
|
||||
auto userNameProducer = /* ... */; // Type: rpl::producer<TextWithEntities>
|
||||
auto messageProducer = tr::lng_user_posted_photo( // Type: rpl::producer<TextWithEntities>
|
||||
lt_user,
|
||||
std::move(userNameProducer), // Move placeholder producers
|
||||
Ui::Text::WithEntities); // Projector
|
||||
```
|
||||
|
||||
## Key Summary
|
||||
|
||||
* Keys are defined in `Resources/langs/lang.strings` using `{tag}` placeholders.
|
||||
* Plural keys use `{count}` and have `#one`/`#other` variants in `lang.strings`.
|
||||
* Access keys via `tr::lng_key_name(...)` in C++.
|
||||
* Call with `tr::now` as the first argument for the immediate `QString` (or projected type).
|
||||
* Call without `tr::now` for the reactive `rpl::producer<QString>` (or projected type).
|
||||
* Provide placeholder values (`lt_tag_name, value`) matching the usage (direct value for immediate, `rpl::producer` for reactive). Producers should typically be moved via `std::move`.
|
||||
* For `{count}`:
|
||||
* Immediate: Pass `int` or `float64`.
|
||||
* 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.
|
||||
* Actual translations are loaded at runtime from the API.
|
||||
@@ -1,216 +0,0 @@
|
||||
---
|
||||
description:
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
# RPL (Reactive Programming Library) Guide
|
||||
|
||||
## Coding Style Note
|
||||
|
||||
**Use `auto`:** In the actual codebase, variable types are almost always deduced using `auto` (or `const auto`, `const auto &`) rather than being written out explicitly. Examples in this guide may use explicit types for clarity, but prefer `auto` in practice.
|
||||
|
||||
```cpp
|
||||
// Prefer this:
|
||||
auto intProducer = rpl::single(123);
|
||||
const auto &lifetime = existingLifetime;
|
||||
|
||||
// Instead of this:
|
||||
rpl::producer<int> intProducer = rpl::single(123);
|
||||
const rpl::lifetime &lifetime = existingLifetime;
|
||||
|
||||
// Sometimes needed if deduction is ambiguous or needs help:
|
||||
auto user = std::make_shared<UserData>();
|
||||
auto data = QByteArray::fromHex("...");
|
||||
```
|
||||
|
||||
## Introduction
|
||||
|
||||
RPL is the reactive programming library used in this project, residing in the `rpl::` namespace. It allows handling asynchronous streams of data over time.
|
||||
|
||||
The core concept is the `rpl::producer`, which represents a stream of values that can be generated over a certain lifetime.
|
||||
|
||||
## Producers: `rpl::producer<Type, Error = no_error>`
|
||||
|
||||
The fundamental building block is `rpl::producer<Type, Error>`. It produces values of `Type` and can optionally signal an error of type `Error`. By default, `Error` is `rpl::no_error`, indicating that the producer does not explicitly handle error signaling through this mechanism.
|
||||
|
||||
```cpp
|
||||
// A producer that emits integers.
|
||||
auto intProducer = /* ... */; // Type: rpl::producer<int>
|
||||
|
||||
// A producer that emits strings and can potentially emit a CustomError.
|
||||
auto stringProducerWithError = /* ... */; // Type: rpl::producer<QString, CustomError>
|
||||
```
|
||||
|
||||
Producers are typically lazy; they don't start emitting values until someone subscribes to them.
|
||||
|
||||
## Lifetime Management: `rpl::lifetime`
|
||||
|
||||
Reactive pipelines have a limited duration, managed by `rpl::lifetime`. An `rpl::lifetime` object essentially holds a collection of cleanup callbacks. When the lifetime ends (either explicitly destroyed or goes out of scope), these callbacks are executed, tearing down the associated pipeline and freeing resources.
|
||||
|
||||
```cpp
|
||||
rpl::lifetime myLifetime;
|
||||
// ... later ...
|
||||
// myLifetime is destroyed, cleanup happens.
|
||||
|
||||
// Or, pass a lifetime instance to manage a pipeline's duration.
|
||||
rpl::lifetime &parentLifetime = /* ... get lifetime from context ... */;
|
||||
```
|
||||
|
||||
## Starting a Pipeline: `rpl::start_...`
|
||||
|
||||
To consume values from a producer, you start a pipeline using one of the `rpl::start_...` methods. These methods subscribe to the producer and execute callbacks for the events they handle.
|
||||
|
||||
The most common method is `rpl::start_with_next`:
|
||||
|
||||
```cpp
|
||||
auto counter = /* ... */; // Type: rpl::producer<int>
|
||||
rpl::lifetime lifetime;
|
||||
|
||||
// Counter is consumed here, use std::move if it's an l-value.
|
||||
std::move(
|
||||
counter
|
||||
) | rpl::start_with_next([=]\(int nextValue) {
|
||||
// Process the next integer value emitted by the producer.
|
||||
qDebug() << "Received: " << nextValue;
|
||||
}, lifetime); // Pass the lifetime to manage the subscription.
|
||||
// Note: `counter` is now in a moved-from state and likely invalid.
|
||||
|
||||
// If you need to start the same producer multiple times, duplicate it:
|
||||
// rpl::duplicate(counter) | rpl::start_with_next(...);
|
||||
|
||||
// If you DON'T pass a lifetime to a start_... method:
|
||||
auto counter2 = /* ... */; // Type: rpl::producer<int>
|
||||
rpl::lifetime subscriptionLifetime = std::move(
|
||||
counter2
|
||||
) | rpl::start_with_next([=]\(int nextValue) { /* ... */ });
|
||||
// The returned lifetime MUST be stored. If it's discarded immediately,
|
||||
// the subscription stops instantly.
|
||||
// `counter2` is also moved-from here.
|
||||
```
|
||||
|
||||
Other variants allow handling errors (`_error`) and completion (`_done`):
|
||||
|
||||
```cpp
|
||||
auto dataStream = /* ... */; // Type: rpl::producer<QString, Error>
|
||||
rpl::lifetime lifetime;
|
||||
|
||||
// Assuming dataStream might be used again, we duplicate it for the first start.
|
||||
// If it's the only use, std::move(dataStream) would be preferred.
|
||||
rpl::duplicate(
|
||||
dataStream
|
||||
) | rpl::start_with_error([=]\(Error &&error) {
|
||||
// Handle the error signaled by the producer.
|
||||
qDebug() << "Error: " << error.text();
|
||||
}, lifetime);
|
||||
|
||||
// Using dataStream again, perhaps duplicated again or moved if last use.
|
||||
rpl::duplicate(
|
||||
dataStream
|
||||
) | rpl::start_with_done([=] {
|
||||
// Execute when the producer signals it's finished emitting values.
|
||||
qDebug() << "Stream finished.";
|
||||
}, lifetime);
|
||||
|
||||
// Last use of dataStream, so we move it.
|
||||
std::move(
|
||||
dataStream
|
||||
) | rpl::start_with_next_error_done(
|
||||
[=]\(QString &&value) { /* handle next value */ },
|
||||
[=]\(Error &&error) { /* handle error */ },
|
||||
[=] { /* handle done */ },
|
||||
lifetime);
|
||||
```
|
||||
|
||||
## Transforming Producers
|
||||
|
||||
RPL provides functions to create new producers by transforming existing ones:
|
||||
|
||||
* `rpl::map`: Transforms each value emitted by a producer.
|
||||
```cpp
|
||||
auto ints = /* ... */; // Type: rpl::producer<int>
|
||||
// The pipe operator often handles the move implicitly for chained transformations.
|
||||
auto strings = std::move(
|
||||
ints // Explicit move is safer
|
||||
) | rpl::map([](int value) {
|
||||
return QString::number(value * 2);
|
||||
}); // Emits strings like "0", "2", "4", ...
|
||||
```
|
||||
|
||||
* `rpl::filter`: Emits only the values from a producer that satisfy a condition.
|
||||
```cpp
|
||||
auto ints = /* ... */; // Type: rpl::producer<int>
|
||||
auto evenInts = std::move(
|
||||
ints // Explicit move is safer
|
||||
) | rpl::filter([](int value) {
|
||||
return (value % 2 == 0);
|
||||
}); // Emits only even numbers.
|
||||
```
|
||||
|
||||
## Combining Producers
|
||||
|
||||
You can combine multiple producers into one:
|
||||
|
||||
* `rpl::combine`: Combines the latest values from multiple producers whenever *any* of them emits a new value. Requires all producers to have emitted at least one value initially.
|
||||
While it produces a `std::tuple`, subsequent operators like `map`, `filter`, and `start_with_next` can automatically unpack this tuple into separate lambda arguments.
|
||||
```cpp
|
||||
auto countProducer = rpl::single(1); // Type: rpl::producer<int>
|
||||
auto textProducer = rpl::single(u"hello"_q); // Type: rpl::producer<QString>
|
||||
rpl::lifetime lifetime;
|
||||
|
||||
// rpl::combine takes producers by const-ref internally and duplicates,
|
||||
// so move/duplicate is usually not strictly needed here unless you
|
||||
// want to signal intent or manage the lifetime of p1/p2 explicitly.
|
||||
auto combined = rpl::combine(
|
||||
countProducer, // or rpl::duplicate(countProducer)
|
||||
textProducer // or rpl::duplicate(textProducer)
|
||||
);
|
||||
|
||||
// Starting the combined producer consumes it.
|
||||
// The lambda receives unpacked arguments, not the tuple itself.
|
||||
std::move(
|
||||
combined
|
||||
) | rpl::start_with_next([=]\(int count, const QString &text) {
|
||||
// No need for std::get<0>(latest), etc.
|
||||
qDebug() << "Combined: Count=" << count << ", Text=" << text;
|
||||
}, lifetime);
|
||||
|
||||
// This also works with map, filter, etc.
|
||||
std::move(
|
||||
combined
|
||||
) | rpl::filter([=]\(int count, const QString &text) {
|
||||
return count > 0 && !text.isEmpty();
|
||||
}) | rpl::map([=]\(int count, const QString &text) {
|
||||
return text.repeated(count);
|
||||
}) | rpl::start_with_next([=]\(const QString &result) {
|
||||
qDebug() << "Mapped & Filtered: " << result;
|
||||
}, lifetime);
|
||||
```
|
||||
|
||||
* `rpl::merge`: Merges the output of multiple producers of the *same type* into a single producer. It emits a value whenever *any* of the source producers emits a value.
|
||||
```cpp
|
||||
auto sourceA = /* ... */; // Type: rpl::producer<QString>
|
||||
auto sourceB = /* ... */; // Type: rpl::producer<QString>
|
||||
|
||||
// rpl::merge also duplicates internally.
|
||||
auto merged = rpl::merge(sourceA, sourceB);
|
||||
|
||||
// Starting the merged producer consumes it.
|
||||
std::move(
|
||||
merged
|
||||
) | rpl::start_with_next([=]\(QString &&value) {
|
||||
// Receives values from either sourceA or sourceB as they arrive.
|
||||
qDebug() << "Merged value: " << value;
|
||||
}, lifetime);
|
||||
```
|
||||
|
||||
## Key Concepts Summary
|
||||
|
||||
* Use `rpl::producer<Type, Error>` to represent streams of values.
|
||||
* Manage subscription duration using `rpl::lifetime`.
|
||||
* Pass `rpl::lifetime` to `rpl::start_...` methods.
|
||||
* If `rpl::lifetime` is not passed, **store the returned lifetime** to keep the subscription active.
|
||||
* Use operators like `| rpl::map`, `| rpl::filter` to transform streams.
|
||||
* Use `rpl::combine` or `rpl::merge` to combine streams.
|
||||
* When starting a chain (`std::move(producer) | rpl::map(...)`), explicitly move the initial producer.
|
||||
* These functions typically duplicate their input producers internally.
|
||||
* Starting a pipeline consumes the producer; use `
|
||||
@@ -1,154 +0,0 @@
|
||||
---
|
||||
description: For tasks requiring working with user facing UI components.
|
||||
globs:
|
||||
alwaysApply: false
|
||||
---
|
||||
# Telegram Desktop UI Styling
|
||||
|
||||
## Style Definition Files
|
||||
|
||||
UI element styles (colors, fonts, paddings, margins, icons, etc.) are defined in `.style` files using a custom syntax. These files are located alongside the C++ source files they correspond to within specific UI component directories (e.g., `Telegram/SourceFiles/ui/chat/chat.style`).
|
||||
|
||||
Definitions from other `.style` files can be included using the `using` directive at the top of the file:
|
||||
```style
|
||||
using "ui/basic.style";
|
||||
using "ui/widgets/widgets.style";
|
||||
```
|
||||
|
||||
The central definition of named colors happens in `Telegram/SourceFiles/ui/colors.palette`. This file allows for theme generation and loading colors from various sources.
|
||||
|
||||
### Syntax Overview
|
||||
|
||||
1. **Built-in Types:** The syntax recognizes several base types inferred from the value assigned:
|
||||
* `int`: Integer numbers (e.g., `lineHeight: 20;`)
|
||||
* `bool`: Boolean values (e.g., `useShadow: true;`)
|
||||
* `pixels`: Pixel values, ending with `px` (e.g., `borderWidth: 1px;`). Generated as `int` in C++.
|
||||
* `color`: Named colors defined in `colors.palette` (e.g., `background: windowBg;`)
|
||||
* `icon`: Defined inline using a specific syntax (see below). Generates `style::icon`.
|
||||
* `margins`: Four pixel values for margins or padding. Requires `margins(top, right, bottom, left)` syntax (e.g., `margin: margins(10px, 5px, 10px, 5px);` or `padding: margins(8px, 8px, 8px, 8px);`). Generates `style::margins` (an alias for `QMargins`).
|
||||
* `size`: Two pixel values for width and height (e.g., `iconSize: size(16px, 16px);`). Generates `style::size`.
|
||||
* `point`: Two pixel values for x and y coordinates (e.g., `textPos: point(5px, 2px);`). Generates `style::point`.
|
||||
* `align`: Alignment keywords (e.g., `textAlign: align(center);` or `iconAlign: align(left);`). Generates `style::align`.
|
||||
* `font`: Font definitions (e.g., `font: font(14px semibold);`). Generates `style::font`.
|
||||
* `double`: Floating point numbers (e.g., `disabledOpacity: 0.5;`)
|
||||
|
||||
*Note on Borders:* Borders are typically defined using multiple fields like `border: pixels;` (for width) and `borderFg: color;` (for color), rather than a single CSS-like property.
|
||||
|
||||
2. **Structure Definition:** You can define complex data structures directly within the `.style` file:
|
||||
```style
|
||||
MyButtonStyle { // Defines a structure named 'MyButtonStyle'
|
||||
textPadding: margins; // Field 'textPadding' expects margins type
|
||||
icon: icon; // Field 'icon' of type icon
|
||||
height: pixels; // Field 'height' of type pixels
|
||||
}
|
||||
```
|
||||
This generates a `struct MyButtonStyle { ... };` inside the `namespace style`. Fields will have corresponding C++ types (`style::margins`, `style::icon`, `int`).
|
||||
|
||||
3. **Variable Definition & Inheritance:** Variables are defined using `name: value;` or `groupName { ... }`. They can be of built-in types or custom structures. Structures can be initialized inline or inherit from existing variables.
|
||||
|
||||
**Icon Definition Syntax:** Icons are defined inline using the `icon{...}` syntax. The generator probes for `.svg` files or `.png` files (including `@2x`, `@3x` variants) based on the provided path stem.
|
||||
```style
|
||||
// Single-part icon definition:
|
||||
myIconSearch: icon{{ "gui/icons/search", iconColor }};
|
||||
// Multi-part icon definition (layers drawn bottom-up):
|
||||
myComplexIcon: icon{
|
||||
{ "gui/icons/background", iconBgColor },
|
||||
{ "gui/icons/foreground", iconFgColor }
|
||||
};
|
||||
// Icon with path modifiers (PNG only for flips, SVG only for size):
|
||||
myFlippedIcon: icon{{ "gui/icons/arrow-flip_horizontal", arrowColor }};
|
||||
myResizedIcon: icon{{ "gui/icons/logo-128x128", logoColor }}; // Forces 128x128 for SVG
|
||||
```
|
||||
|
||||
**Other Variable Examples:**
|
||||
```style
|
||||
// Simple variables
|
||||
buttonHeight: 30px;
|
||||
activeButtonColor: buttonBgActive; // Named color from colors.palette
|
||||
|
||||
// Variable of a custom structure type, initialized inline
|
||||
defaultButton: MyButtonStyle {
|
||||
textPadding: margins(10px, 15px, 10px, 15px); // Use margins(...) syntax
|
||||
icon: myIconSearch; // Assign the previously defined icon variable
|
||||
height: buttonHeight; // Reference another variable
|
||||
}
|
||||
|
||||
// Another variable inheriting from 'defaultButton' and overriding/adding fields
|
||||
primaryButton: MyButtonStyle(defaultButton) {
|
||||
icon: myComplexIcon; // Override icon with the multi-part one
|
||||
backgroundColor: activeButtonColor; // Add a field not in MyButtonStyle definition
|
||||
}
|
||||
|
||||
// Style group (often used for specific UI elements)
|
||||
chatInput { // Example using separate border properties and explicit padding
|
||||
border: 1px; // Border width
|
||||
borderFg: defaultInputFieldBorder; // Border color (named color)
|
||||
padding: margins(5px, 10px, 5px, 10px); // Use margins(...) syntax for padding field
|
||||
backgroundColor: defaultChatBg; // Background color
|
||||
}
|
||||
```
|
||||
|
||||
## Code Generation
|
||||
|
||||
A code generation tool processes these `.style` files and `colors.palette` to create C++ objects.
|
||||
- The `using` directives resolve dependencies between `.style` files.
|
||||
- Custom structure definitions (like `MyButtonStyle`) generate corresponding `struct MyButtonStyle { ... };` within the `namespace style`.
|
||||
- Style variables/groups (like `defaultButton`, `primaryButton`, `chatInput`) are generated as objects/structs within the `st` namespace (e.g., `st::defaultButton`, `st::primaryButton`, `st::chatInput`). These generated structs contain members corresponding to the fields defined in the `.style` file.
|
||||
- Color objects are generated into the `st` namespace as well, based on their names in `colors.palette` (e.g., `st::windowBg`, `st::buttonBgActive`).
|
||||
- The generated header files for styles are placed in the `Telegram/SourceFiles/styles/` directory with a `style_` prefix (e.g., `styles/style_widgets.h` for `ui/widgets/widgets.style`). You include them like `#include "styles/style_widgets.h"`.
|
||||
|
||||
Generated C++ types correspond to the `.style` types: `style::color`, `style::font`, `style::margins` (used for both `margin:` and `padding:` fields), `style::icon`, `style::size`, `style::point`, `style::align`, and `int` or `bool` for simple types.
|
||||
|
||||
## Style Usage in Code
|
||||
|
||||
Styles are applied in C++ code by referencing the generated `st::...` objects and their members.
|
||||
|
||||
```cpp
|
||||
// Example: Including the generated style header
|
||||
#include "styles/style_widgets.h" // For styles defined in ui/widgets/widgets.style
|
||||
|
||||
// ... inside some UI class code ...
|
||||
|
||||
// Accessing members of a generated style struct
|
||||
int height = st::primaryButton.height; // Accessing the 'height' field (pixels -> int)
|
||||
const style::icon &icon = st::primaryButton.icon; // Accessing the 'icon' field (st::myComplexIcon)
|
||||
style::margins padding = st::primaryButton.textPadding; // Accessing 'textPadding'
|
||||
style::color bgColor = st::primaryButton.backgroundColor; // Accessing the color (st::activeButtonColor)
|
||||
|
||||
// Applying styles (conceptual examples)
|
||||
myButton->setIcon(st::primaryButton.icon);
|
||||
myButton->setHeight(st::primaryButton.height);
|
||||
myButton->setPadding(st::primaryButton.textPadding);
|
||||
myButton->setBackgroundColor(st::primaryButton.backgroundColor);
|
||||
|
||||
// Using styles directly in painting
|
||||
void MyWidget::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
p.fillRect(rect(), st::chatInput.backgroundColor); // Use color from chatInput style
|
||||
|
||||
// Border painting requires width and color
|
||||
int borderWidth = st::chatInput.border; // Access border width (pixels -> int)
|
||||
style::color borderColor = st::chatInput.borderFg; // Access border color
|
||||
if (borderWidth > 0) {
|
||||
p.setPen(QPen(borderColor, borderWidth));
|
||||
// Adjust rect for pen width if needed before drawing
|
||||
p.drawRect(rect().adjusted(borderWidth / 2, borderWidth / 2, -borderWidth / 2, -borderWidth / 2));
|
||||
}
|
||||
|
||||
// Access padding (style::margins)
|
||||
style::margins inputPadding = st::chatInput.padding;
|
||||
// ... use inputPadding.top(), inputPadding.left() etc. for content layout ...
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
|
||||
* Styles are defined in `.style` files next to their corresponding C++ source files.
|
||||
* `using "path/to/other.style";` includes definitions from other style files.
|
||||
* Named colors are defined centrally in `ui/colors.palette`.
|
||||
* `.style` syntax supports built-in types (like `pixels`, `color`, `margins`, `point`, `size`, `align`, `font`, `double`), custom structure definitions (`Name { field: type; ... }`), variable definitions (`name: value;`), and inheritance (`child: Name(parent) { ... }`).
|
||||
* Values must match the expected type (e.g., fields declared as `margins` type, like `margin:` or `padding:`, require `margins(...)` syntax). Borders are typically set via separate `border: pixels;` and `borderFg: color;` fields.
|
||||
* 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.
|
||||
* 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`).
|
||||
@@ -1,2 +0,0 @@
|
||||
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
|
||||
Telegram/ThirdParty/
|
||||
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"name": "CentOS",
|
||||
"image": "tdesktop:centos_env",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {
|
||||
"C_Cpp.intelliSenseEngine": "disabled",
|
||||
"clangd.arguments": [
|
||||
"--compile-commands-dir=${workspaceFolder}/out"
|
||||
],
|
||||
"cmake.generator": "Ninja Multi-Config",
|
||||
"cmake.buildDirectory": "${workspaceFolder}/out"
|
||||
},
|
||||
"extensions": [
|
||||
"ms-vscode.cpptools-extension-pack",
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"TheQtCompany.qt",
|
||||
"ms-python.python",
|
||||
"ms-azuretools.vscode-docker",
|
||||
"eamodio.gitlens"
|
||||
]
|
||||
}
|
||||
},
|
||||
"capAdd": [
|
||||
"SYS_PTRACE"
|
||||
],
|
||||
"securityOpt": [
|
||||
"seccomp=unconfined"
|
||||
],
|
||||
"workspaceMount": "source=${localWorkspaceFolder},target=/usr/src/tdesktop,type=bind,consistency=cached",
|
||||
"workspaceFolder": "/usr/src/tdesktop"
|
||||
}
|
||||
17
.github/ISSUE_TEMPLATE/BUG_REPORT.yml
vendored
@@ -34,7 +34,7 @@ body:
|
||||
label: Operating system
|
||||
description: >
|
||||
Your operating system name, version and desktop environment.
|
||||
**Don't use kernel version (uname), it's useless.**
|
||||
Please don't use kernel version (uname), it's useless.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
@@ -42,9 +42,9 @@ body:
|
||||
label: Version of Telegram Desktop
|
||||
description: >
|
||||
Please note we don't support versions from Linux distro repositories.
|
||||
If you need support for these versions, **please contact your distro maintainer**
|
||||
If you need support for these versions, please contact your distro maintainer
|
||||
or your distro bugtracker.
|
||||
**Don't use 'latest'**, specify actual version, **that's a reason to close your issue**.
|
||||
Don't use 'latest', specify actual version, that's a reason to close your issue.
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
@@ -60,19 +60,8 @@ body:
|
||||
- Other (unofficial) source
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Crash ID
|
||||
description: >
|
||||
If you're reporting a crash, please enter the crash ID from the crash reporter
|
||||
opening on the next launch after crash. **You have to enable beta versions
|
||||
installation in Settings -> Advanced for the reporter to appear.**
|
||||
You don't have to wait for a beta version to arrive.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Logs
|
||||
description: >
|
||||
You can find log.txt using the `viewlogs`
|
||||
[cheat code](https://github.com/telegramdesktop/tdesktop/wiki/Cheat-Codes).
|
||||
placeholder: Insert log.txt here (if necessary)
|
||||
render: shell
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml
vendored
@@ -2,6 +2,7 @@
|
||||
name: Feature request
|
||||
description: Suggest an idea.
|
||||
labels: [enhancement]
|
||||
title: "[Feature Request] "
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
||||
8
.github/ISSUE_TEMPLATE/QUESTION.md
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
name: Question
|
||||
about: Ask a question.
|
||||
title: "[Question] "
|
||||
labels: 'question'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
11
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,11 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Platform-wide issue
|
||||
url: https://bugs.telegram.org
|
||||
about: Any bug report or feature request affecting more than only Telegram Desktop.
|
||||
- name: Issue of other client
|
||||
url: https://bugs.telegram.org
|
||||
about: Any bug report or feature request not about Telegram Desktop.
|
||||
- name: Question
|
||||
url: https://t.me/TelegramDesktopTalk
|
||||
about: Ask a question.
|
||||
6
.github/dependabot.yml
vendored
@@ -1,6 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
21
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 180
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 30
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels: [ "enhancement" ]
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: |
|
||||
Hey there!
|
||||
|
||||
This issue was inactive for a long time and will be automatically closed in 30 days if there isn't any further activity. We therefore assume that the user has lost interest or resolved the problem on their own.
|
||||
|
||||
Don't worry though; if this is an error, let us know with a comment and we'll be happy to reopen the issue.
|
||||
|
||||
Thanks!
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
# Process only issues
|
||||
only: issues
|
||||
25
.github/workflows/cant-reproduce.yml
vendored
@@ -1,25 +0,0 @@
|
||||
name: Can't reproduce.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 3 * * *'
|
||||
|
||||
jobs:
|
||||
cant-reproduce:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: lee-dohm/no-response@v0.5.0
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
responseRequiredLabel: cant reproduce
|
||||
closeComment: >
|
||||
This issue has been automatically closed because no developer succeeded to
|
||||
reproduce the issue with the given reproduction steps. With only the
|
||||
information that is currently in the issue, we don't have enough
|
||||
information to take action. Please reach out if you find what's missing to
|
||||
reproduce the issue so that we can investigate further.
|
||||
|
||||
|
||||
Note that GitHub is a developer communication platform. If you're an ordinary
|
||||
user seeking for help, get to support crew via `Settings -> Ask question` in
|
||||
the application.
|
||||
25
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Docker.
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/docker.yml'
|
||||
- 'Telegram/build/docker/centos_env/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/docker.yml'
|
||||
- 'Telegram/build/docker/centos_env/**'
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
name: Ubuntu
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Docker image build.
|
||||
run: docker build -t telegram_desktop Telegram/build/docker/centos_env
|
||||
80
.github/workflows/linux.yml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-linux.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
@@ -12,7 +13,6 @@ on:
|
||||
- '!.github/workflows/linux.yml'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- '!Telegram/build/docker/centos_env/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
@@ -24,6 +24,7 @@ on:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-linux.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
@@ -31,7 +32,6 @@ on:
|
||||
- '!.github/workflows/linux.yml'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- '!Telegram/build/docker/centos_env/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
@@ -43,55 +43,48 @@ on:
|
||||
jobs:
|
||||
|
||||
linux:
|
||||
name: Rocky Linux 8
|
||||
name: CentOS 7
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: docker.pkg.github.com/telegramdesktop/tdesktop/centos_env
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: scl enable llvm-toolset-7.0 -- scl enable devtoolset-10 -- bash --noprofile --norc -eo pipefail {0}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
defines:
|
||||
- ""
|
||||
- "DESKTOP_APP_DISABLE_DBUS_INTEGRATION"
|
||||
- "DESKTOP_APP_DISABLE_X11_INTEGRATION"
|
||||
- "DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION"
|
||||
|
||||
env:
|
||||
UPLOAD_ARTIFACT: "true"
|
||||
ONLY_CACHE: "false"
|
||||
IMAGE_TAG: tdesktop:centos_env
|
||||
UPLOAD_ARTIFACT: "false"
|
||||
|
||||
steps:
|
||||
- name: Get repository name.
|
||||
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
path: ${{ env.REPO_NAME }}
|
||||
|
||||
- name: First set up.
|
||||
run: |
|
||||
sudo apt update
|
||||
curl -sSL https://install.python-poetry.org | python3 -
|
||||
cd Telegram/build/docker/centos_env
|
||||
poetry install
|
||||
DOCKERFILE=$(DEBUG= LTO= poetry run gen_dockerfile)
|
||||
echo "$DOCKERFILE" > Dockerfile
|
||||
|
||||
- name: Free up some disk space.
|
||||
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
|
||||
with:
|
||||
tool-cache: true
|
||||
|
||||
- name: Set up Docker Buildx.
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Libraries.
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: Telegram/build/docker/centos_env
|
||||
load: ${{ env.ONLY_CACHE == 'false' }}
|
||||
tags: ${{ env.IMAGE_TAG }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
gcc --version
|
||||
ln -s $LibrariesPath Libraries
|
||||
|
||||
- name: Telegram Desktop build.
|
||||
if: env.ONLY_CACHE == 'false'
|
||||
run: |
|
||||
cd $REPO_NAME/Telegram
|
||||
|
||||
DEFINE=""
|
||||
if [ -n "${{ matrix.defines }}" ]; then
|
||||
DEFINE="-D ${{ matrix.defines }}=ON"
|
||||
@@ -101,27 +94,20 @@ jobs:
|
||||
echo "ARTIFACT_NAME=Telegram" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
docker run --rm \
|
||||
-u $(id -u) \
|
||||
-v $PWD:/usr/src/tdesktop \
|
||||
-e CONFIG=Debug \
|
||||
$IMAGE_TAG \
|
||||
/usr/src/tdesktop/Telegram/build/docker/centos_env/build.sh \
|
||||
-D CMAKE_CONFIGURATION_TYPES=Debug \
|
||||
-D CMAKE_C_FLAGS_DEBUG="" \
|
||||
-D CMAKE_CXX_FLAGS_DEBUG="" \
|
||||
./configure.sh \
|
||||
-D CMAKE_C_FLAGS="-Werror" \
|
||||
-D CMAKE_CXX_FLAGS="-Werror" \
|
||||
-D CMAKE_EXE_LINKER_FLAGS="-s" \
|
||||
-D TDESKTOP_API_TEST=ON \
|
||||
-D DESKTOP_APP_DISABLE_AUTOUPDATE=OFF \
|
||||
-D DESKTOP_APP_USE_PACKAGED=OFF \
|
||||
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF \
|
||||
$DEFINE
|
||||
|
||||
cmake --build ../out --config Debug --parallel
|
||||
|
||||
- name: Check.
|
||||
if: env.ONLY_CACHE == 'false'
|
||||
run: |
|
||||
filePath="out/Debug/Telegram"
|
||||
filePath="$REPO_NAME/out/Debug/Telegram"
|
||||
if test -f "$filePath"; then
|
||||
echo "Build successfully done! :)"
|
||||
|
||||
@@ -135,12 +121,12 @@ jobs:
|
||||
- name: Move artifact.
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
run: |
|
||||
cd out/Debug
|
||||
cd $REPO_NAME/out/Debug
|
||||
mkdir artifact
|
||||
mv {Telegram,Updater} artifact/
|
||||
- uses: actions/upload-artifact@v4
|
||||
mv Telegram artifact/
|
||||
- uses: actions/upload-artifact@master
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
name: Upload artifact.
|
||||
with:
|
||||
name: ${{ env.ARTIFACT_NAME }}
|
||||
path: out/Debug/artifact/
|
||||
path: ${{ env.REPO_NAME }}/out/Debug/artifact/
|
||||
|
||||
2
.github/workflows/lock.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v5
|
||||
- uses: dessant/lock-threads@v3
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
issue-inactive-days: 45
|
||||
|
||||
36
.github/workflows/mac.yml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-mac.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
@@ -22,6 +23,7 @@ on:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-mac.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
@@ -40,23 +42,22 @@ jobs:
|
||||
|
||||
macos:
|
||||
name: MacOS
|
||||
runs-on: macos-13
|
||||
runs-on: macos-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
defines:
|
||||
- ""
|
||||
env:
|
||||
UPLOAD_ARTIFACT: "true"
|
||||
UPLOAD_ARTIFACT: "false"
|
||||
ONLY_CACHE: "false"
|
||||
PREPARE_PATH: "Telegram/build/prepare/prepare.py"
|
||||
|
||||
steps:
|
||||
- name: Get repository name.
|
||||
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
path: ${{ env.REPO_NAME }}
|
||||
@@ -64,10 +65,8 @@ jobs:
|
||||
- name: First set up.
|
||||
run: |
|
||||
sudo chown -R `whoami`:admin /usr/local/share
|
||||
|
||||
brew update
|
||||
brew upgrade || true
|
||||
brew install automake meson nasm ninja pkg-config
|
||||
brew install automake fdk-aac lame libass libtool libvorbis libvpx \
|
||||
ninja opus sdl shtool texi2html theora x264 xvid yasm pkg-config
|
||||
|
||||
# Disable spotlight.
|
||||
sudo mdutil -a -i off
|
||||
@@ -76,19 +75,17 @@ jobs:
|
||||
|
||||
- name: ThirdParty cache.
|
||||
id: cache-third-party
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ThirdParty
|
||||
key: ${{ runner.OS }}-third-party-${{ hashFiles(format('{0}/{1}', env.REPO_NAME, env.PREPARE_PATH)) }}
|
||||
restore-keys: ${{ runner.OS }}-third-party-
|
||||
key: ${{ runner.OS }}-third-party
|
||||
|
||||
- name: Libraries cache.
|
||||
id: cache-libs
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: Libraries
|
||||
key: ${{ runner.OS }}-libs-${{ hashFiles(format('{0}/{1}', env.REPO_NAME, env.PREPARE_PATH)) }}
|
||||
restore-keys: ${{ runner.OS }}-libs-
|
||||
key: ${{ runner.OS }}-libs
|
||||
|
||||
- name: Libraries.
|
||||
run: |
|
||||
@@ -114,16 +111,17 @@ jobs:
|
||||
fi
|
||||
|
||||
./configure.sh \
|
||||
-D CMAKE_CONFIGURATION_TYPES=Debug \
|
||||
-D CMAKE_C_FLAGS="-Werror" \
|
||||
-D CMAKE_CXX_FLAGS="-Werror" \
|
||||
-D CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=NO \
|
||||
-D TDESKTOP_API_TEST=ON \
|
||||
-D DESKTOP_APP_DISABLE_AUTOUPDATE=OFF \
|
||||
-D DESKTOP_APP_USE_PACKAGED=OFF \
|
||||
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF \
|
||||
$DEFINE
|
||||
|
||||
cmake --build ../out --config Debug --parallel
|
||||
cd ../out
|
||||
|
||||
xcoderun='xcodebuild build -project Telegram.xcodeproj -scheme Telegram -destination "platform=macOS,arch=x86_64" -configuration Debug'
|
||||
bash -c "$xcoderun" || bash -c "$xcoderun" || bash -c "$xcoderun"
|
||||
|
||||
- name: Move artifact.
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
@@ -132,7 +130,7 @@ jobs:
|
||||
mkdir artifact
|
||||
mv Telegram.app artifact/
|
||||
mv Updater artifact/
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@master
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
name: Upload artifact.
|
||||
with:
|
||||
|
||||
167
.github/workflows/mac_packaged.yml
vendored
@@ -1,167 +0,0 @@
|
||||
name: MacOS Packaged.
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/mac_packaged.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/configure.bat'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/mac_packaged.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/configure.bat'
|
||||
|
||||
jobs:
|
||||
|
||||
macos:
|
||||
name: MacOS
|
||||
runs-on: macos-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
defines:
|
||||
- ""
|
||||
|
||||
env:
|
||||
GIT: "https://github.com"
|
||||
CMAKE_PREFIX_PATH: "/opt/homebrew/opt/ffmpeg@6:/opt/homebrew/opt/openal-soft"
|
||||
UPLOAD_ARTIFACT: "true"
|
||||
ONLY_CACHE: "false"
|
||||
MANUAL_CACHING: "1"
|
||||
AUTO_CACHING: "1"
|
||||
|
||||
steps:
|
||||
- name: Get repository name.
|
||||
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
path: ${{ env.REPO_NAME }}
|
||||
|
||||
- name: First set up.
|
||||
run: |
|
||||
brew update
|
||||
brew upgrade || true
|
||||
brew install ada-url autoconf automake boost cmake ffmpeg libtool openal-soft openh264 openssl opus ninja pkg-config python qt yasm xz
|
||||
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
|
||||
|
||||
xcodebuild -version > CACHE_KEY.txt
|
||||
brew list --versions >> CACHE_KEY.txt
|
||||
echo $MANUAL_CACHING >> CACHE_KEY.txt
|
||||
echo "$GITHUB_WORKSPACE" >> CACHE_KEY.txt
|
||||
if [ "$AUTO_CACHING" = "1" ]; then
|
||||
thisFile=$REPO_NAME/.github/workflows/mac_packaged.yml
|
||||
echo `md5 -q $thisFile` >> CACHE_KEY.txt
|
||||
fi
|
||||
echo "CACHE_KEY=`md5 -q CACHE_KEY.txt`" >> $GITHUB_ENV
|
||||
|
||||
echo "LibrariesPath=`pwd`" >> $GITHUB_ENV
|
||||
|
||||
curl -o tg_owt-version.json https://api.github.com/repos/desktop-app/tg_owt/git/refs/heads/master
|
||||
|
||||
- name: RNNoise.
|
||||
run: |
|
||||
cd $LibrariesPath
|
||||
|
||||
git clone --depth=1 https://gitlab.xiph.org/xiph/rnnoise.git
|
||||
cd rnnoise
|
||||
./autogen.sh
|
||||
./configure --disable-examples --disable-doc
|
||||
make -j$(sysctl -n hw.logicalcpu)
|
||||
sudo make install
|
||||
|
||||
- name: WebRTC cache.
|
||||
id: cache-webrtc
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/tg_owt
|
||||
key: ${{ runner.OS }}-webrtc-${{ env.CACHE_KEY }}-${{ hashFiles('**/tg_owt-version.json') }}
|
||||
- name: WebRTC.
|
||||
if: steps.cache-webrtc.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
cd $LibrariesPath
|
||||
|
||||
git clone --depth=1 --recursive --shallow-submodules $GIT/desktop-app/tg_owt.git
|
||||
cd tg_owt
|
||||
|
||||
cmake -Bbuild -GNinja . \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_C_FLAGS_DEBUG="" \
|
||||
-DCMAKE_CXX_FLAGS_DEBUG=""
|
||||
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Telegram Desktop build.
|
||||
if: env.ONLY_CACHE == 'false'
|
||||
env:
|
||||
tg_owt_DIR: ${{ env.LibrariesPath }}/tg_owt/build
|
||||
run: |
|
||||
cd $REPO_NAME
|
||||
|
||||
DEFINE=""
|
||||
if [ -n "${{ matrix.defines }}" ]; then
|
||||
DEFINE="-D ${{ matrix.defines }}=ON"
|
||||
echo Define from matrix: $DEFINE
|
||||
echo "ARTIFACT_NAME=Telegram_${{ matrix.defines }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "ARTIFACT_NAME=Telegram" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
cmake -Bbuild -GNinja . \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_C_FLAGS_DEBUG="" \
|
||||
-DCMAKE_CXX_FLAGS_DEBUG="" \
|
||||
-DCMAKE_EXE_LINKER_FLAGS="-s" \
|
||||
-DTDESKTOP_API_TEST=ON \
|
||||
-DDESKTOP_APP_USE_PACKAGED_LAZY=ON \
|
||||
$DEFINE
|
||||
|
||||
cmake --build build --parallel
|
||||
|
||||
cd build
|
||||
macdeployqt Telegram.app
|
||||
codesign --remove-signature Telegram.app
|
||||
|
||||
mkdir dmgsrc
|
||||
mv Telegram.app dmgsrc
|
||||
hdiutil create -volname Telegram -srcfolder dmgsrc -ov -format UDZO Telegram.dmg
|
||||
|
||||
- name: Move artifact.
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
run: |
|
||||
cd $REPO_NAME/build
|
||||
mkdir artifact
|
||||
mv Telegram.dmg artifact/
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
name: Upload artifact.
|
||||
with:
|
||||
name: ${{ env.ARTIFACT_NAME }}
|
||||
path: ${{ env.REPO_NAME }}/build/artifact/
|
||||
4
.github/workflows/master_updater.yml
vendored
@@ -11,9 +11,7 @@ jobs:
|
||||
SKIP: "0"
|
||||
to_branch: "master"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@v1
|
||||
if: env.SKIP == '0'
|
||||
- name: Push the code to the master branch.
|
||||
if: env.SKIP == '0'
|
||||
|
||||
16
.github/workflows/needs-user-action.yml
vendored
@@ -1,16 +0,0 @@
|
||||
name: Needs user action.
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
schedule:
|
||||
- cron: '0 2 * * *'
|
||||
|
||||
jobs:
|
||||
needs-user-action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: lee-dohm/no-response@v0.5.0
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
responseRequiredLabel: needs user action
|
||||
19
.github/workflows/no-response.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: No Response
|
||||
|
||||
# Both `issue_comment` and `scheduled` event types are required for this Action
|
||||
# to work properly.
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
noResponse:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: lee-dohm/no-response@v0.5.0
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
# Label requiring a response
|
||||
responseRequiredLabel: waiting for answer
|
||||
29
.github/workflows/snap.yml
vendored
@@ -38,33 +38,38 @@ on:
|
||||
|
||||
jobs:
|
||||
|
||||
snap:
|
||||
linux:
|
||||
name: Ubuntu
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
UPLOAD_ARTIFACT: "true"
|
||||
UPLOAD_ARTIFACT: "false"
|
||||
|
||||
steps:
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: First set up.
|
||||
run: |
|
||||
sudo iptables -P FORWARD ACCEPT
|
||||
sudo snap install --classic snapcraft
|
||||
sudo usermod -aG lxd $USER
|
||||
sudo lxd init --auto
|
||||
sudo lxd waitready
|
||||
sudo apt-get purge --autoremove lxd
|
||||
|
||||
- name: Free up some disk space.
|
||||
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
|
||||
sudo snap install --classic snapcraft
|
||||
sudo snap install lxd
|
||||
|
||||
# Workaround for snapcraft
|
||||
# See https://forum.snapcraft.io/t/13258
|
||||
sudo chown root:root /
|
||||
|
||||
sudo usermod -aG lxd $USER
|
||||
|
||||
sudo snap run lxd init --auto
|
||||
sudo snap run lxd waitready
|
||||
|
||||
- name: Telegram Desktop snap build.
|
||||
run: sudo -u $USER snap run snapcraft --verbosity=debug
|
||||
run: sg lxd -c 'snap run snapcraft --use-lxd'
|
||||
|
||||
- name: Move artifact.
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
@@ -75,7 +80,7 @@ jobs:
|
||||
mkdir artifact
|
||||
mv $artifact_name artifact
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@master
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
name: Upload artifact.
|
||||
with:
|
||||
|
||||
25
.github/workflows/stale.yml
vendored
@@ -1,25 +0,0 @@
|
||||
name: 'Close stale issues and PRs'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
stale-issue-message: |
|
||||
Hey there!
|
||||
|
||||
This issue was inactive for a long time and will be automatically closed in 30 days if there isn't any further activity. We therefore assume that the user has lost interest or resolved the problem on their own.
|
||||
|
||||
Don't worry though; if this is an error, let us know with a comment and we'll be happy to reopen the issue.
|
||||
|
||||
Thanks!
|
||||
stale-issue-label: 'stale'
|
||||
exempt-issue-labels: 'enhancement'
|
||||
days-before-stale: 180
|
||||
days-before-close: 30
|
||||
days-before-pr-stale: -1
|
||||
operations-per-run: 1000
|
||||
16
.github/workflows/waiting-for-answer.yml
vendored
@@ -1,16 +0,0 @@
|
||||
name: Waiting for answer.
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
schedule:
|
||||
- cron: '30 0 * * *'
|
||||
|
||||
jobs:
|
||||
waiting-for-answer:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: lee-dohm/no-response@v0.5.0
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
responseRequiredLabel: waiting for answer
|
||||
119
.github/workflows/win.yml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-win.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
@@ -12,7 +13,7 @@ on:
|
||||
- '!.github/workflows/win.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/docker/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/SourceFiles/platform/mac/**'
|
||||
@@ -23,6 +24,7 @@ on:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-win.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
@@ -30,7 +32,7 @@ on:
|
||||
- '!.github/workflows/win.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/docker/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/SourceFiles/platform/mac/**'
|
||||
@@ -42,48 +44,59 @@ jobs:
|
||||
|
||||
windows:
|
||||
name: Windows
|
||||
runs-on: windows-latest
|
||||
runs-on: windows-2022
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [Win32, x64]
|
||||
generator: ["", "Ninja Multi-Config"]
|
||||
|
||||
env:
|
||||
UPLOAD_ARTIFACT: "true"
|
||||
UPLOAD_ARTIFACT: "false"
|
||||
ONLY_CACHE: "false"
|
||||
PREPARE_PATH: "Telegram/build/prepare/prepare.py"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: cmd
|
||||
working-directory: ${{ github.workspace }}
|
||||
|
||||
steps:
|
||||
- name: Prepare directories.
|
||||
run: |
|
||||
mkdir %userprofile%\TBuild\Libraries
|
||||
mklink /d %GITHUB_WORKSPACE%\TBuild %userprofile%\TBuild
|
||||
echo TBUILD=%GITHUB_WORKSPACE%\TBuild>>%GITHUB_ENV%
|
||||
echo TBUILD=%userprofile%\TBuild>>%GITHUB_ENV%
|
||||
|
||||
- name: Get repository name.
|
||||
shell: bash
|
||||
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
|
||||
- uses: ilammy/msvc-dev-cmd@v1.13.0
|
||||
- uses: ilammy/msvc-dev-cmd@v1.10.0
|
||||
name: Native Tools Command Prompt.
|
||||
with:
|
||||
arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v4
|
||||
uses: LebedevRI/checkout@issue197
|
||||
with:
|
||||
submodules: recursive
|
||||
path: ${{ env.TBUILD }}\${{ env.REPO_NAME }}
|
||||
|
||||
- name: Choco installs.
|
||||
run: |
|
||||
choco install --no-progress -y nasm strawberryperl yasm jom ninja
|
||||
py -m pip install pywin32
|
||||
|
||||
- name: Install msys64.
|
||||
run: |
|
||||
mkdir %TBUILD%\ThirdParty
|
||||
xcopy /E /I C:\msys64 %TBUILD%\ThirdParty\msys64
|
||||
|
||||
- name: Set up environment paths.
|
||||
shell: bash
|
||||
run: |
|
||||
echo "CACHE_KEY=$(sha256sum $TBUILD/$REPO_NAME/$PREPARE_PATH | awk '{ print $1 }')" >> $GITHUB_ENV
|
||||
echo "C:\\Strawberry\\perl\\bin\\" >> $GITHUB_PATH
|
||||
echo "C:\\Program Files\\NASM\\" >> $GITHUB_PATH
|
||||
echo "C:\\ProgramData\\chocolatey\\lib\\ninja\\tools\\" >> $GITHUB_PATH
|
||||
|
||||
echo "Configurate git for cherry-picks."
|
||||
git config --global user.email "you@example.com"
|
||||
@@ -94,75 +107,38 @@ jobs:
|
||||
nuget sources Disable -Name "Microsoft Visual Studio Offline Packages"
|
||||
nuget sources Add -Source https://api.nuget.org/v3/index.json & exit 0
|
||||
|
||||
- name: ThirdParty cache.
|
||||
id: cache-third-party
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.TBUILD }}\ThirdParty
|
||||
key: ${{ runner.OS }}-${{ matrix.arch }}-third-party-${{ env.CACHE_KEY }}
|
||||
restore-keys: ${{ runner.OS }}-${{ matrix.arch }}-third-party-
|
||||
|
||||
- name: Libraries cache.
|
||||
id: cache-libs
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.TBUILD }}\Libraries
|
||||
key: ${{ runner.OS }}-${{ matrix.arch }}-libs-${{ env.CACHE_KEY }}
|
||||
restore-keys: ${{ runner.OS }}-${{ matrix.arch }}-libs-
|
||||
path: ${{ env.TBUILD }}/Libraries
|
||||
key: ${{ runner.OS }}-libs
|
||||
|
||||
- name: Libraries.
|
||||
env:
|
||||
GYP_MSVS_OVERRIDE_PATH: 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\'
|
||||
GYP_MSVS_VERSION: 2022
|
||||
run: |
|
||||
C:
|
||||
cd %TBUILD%
|
||||
%REPO_NAME%\Telegram\build\prepare\win.bat skip-release silent
|
||||
%REPO_NAME%/Telegram/build/prepare/win.bat skip-release silent
|
||||
|
||||
- name: Read configuration matrix.
|
||||
- name: Read defines.
|
||||
shell: bash
|
||||
run: |
|
||||
ARTIFACT_NAME="Telegram"
|
||||
|
||||
ARCH=""
|
||||
if [ -n "${{ matrix.arch }}" ]; then
|
||||
case "${{ matrix.arch }}" in
|
||||
Win32) ARCH="x86";;
|
||||
*) ARCH="${{ matrix.arch }}";;
|
||||
esac
|
||||
echo "Architecture from matrix: $ARCH"
|
||||
ARTIFACT_NAME="${ARTIFACT_NAME}_${{ matrix.arch }}"
|
||||
fi
|
||||
|
||||
GENERATOR=""
|
||||
if [ -n "${{ matrix.generator }}" ]; then
|
||||
GENERATOR="-G \"${{ matrix.generator }}\""
|
||||
echo "Generator from matrix: $GENERATOR"
|
||||
ARTIFACT_NAME="${ARTIFACT_NAME}_${{ matrix.generator }}"
|
||||
fi
|
||||
echo "TDESKTOP_BUILD_GENERATOR=$GENERATOR" >> $GITHUB_ENV
|
||||
|
||||
[ -n "$GENERATOR" ] && ARCH=""
|
||||
echo "TDESKTOP_BUILD_ARCH=$ARCH" >> $GITHUB_ENV
|
||||
|
||||
DEFINE=""
|
||||
if [ -n "${{ matrix.defines }}" ]; then
|
||||
DEFINE="-D ${{ matrix.defines }}=ON"
|
||||
echo "Define from matrix: $DEFINE"
|
||||
ARTIFACT_NAME="${ARTIFACT_NAME}_${{ matrix.defines }}"
|
||||
echo Define from matrix: $DEFINE
|
||||
echo "ARTIFACT_NAME=Telegram_${{ matrix.defines }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "ARTIFACT_NAME=Telegram" >> $GITHUB_ENV
|
||||
fi
|
||||
echo "TDESKTOP_BUILD_DEFINE=$DEFINE" >> $GITHUB_ENV
|
||||
|
||||
echo "ARTIFACT_NAME=$ARTIFACT_NAME" >> $GITHUB_ENV
|
||||
|
||||
API="-D TDESKTOP_API_TEST=ON"
|
||||
if [ $GITHUB_REF == 'refs/heads/nightly' ]; then
|
||||
echo "Use the open credentials."
|
||||
API="-D TDESKTOP_API_ID=611335 -D TDESKTOP_API_HASH=d524b414d21f4d37f08684c1df41ac9c"
|
||||
fi
|
||||
echo "TDESKTOP_BUILD_API=$API" >> $GITHUB_ENV
|
||||
|
||||
- name: Free up some disk space.
|
||||
run: |
|
||||
C:
|
||||
cd %TBUILD%
|
||||
del /S Libraries\*.pdb
|
||||
del /S Libraries\*.pch
|
||||
@@ -171,32 +147,29 @@ jobs:
|
||||
- name: Telegram Desktop build.
|
||||
if: env.ONLY_CACHE == 'false'
|
||||
run: |
|
||||
C:
|
||||
cd %TBUILD%\%REPO_NAME%\Telegram
|
||||
|
||||
call configure.bat ^
|
||||
%TDESKTOP_BUILD_GENERATOR% ^
|
||||
%TDESKTOP_BUILD_ARCH% ^
|
||||
%TDESKTOP_BUILD_API% ^
|
||||
-D CMAKE_CONFIGURATION_TYPES=Debug ^
|
||||
-D CMAKE_C_FLAGS="/WX" ^
|
||||
-D CMAKE_CXX_FLAGS="/WX" ^
|
||||
-D DESKTOP_APP_DISABLE_AUTOUPDATE=OFF ^
|
||||
${{ matrix.arch }} ^
|
||||
-D TDESKTOP_API_TEST=ON ^
|
||||
-D DESKTOP_APP_USE_PACKAGED=OFF ^
|
||||
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF ^
|
||||
-D DESKTOP_APP_NO_PDB=ON ^
|
||||
%TDESKTOP_BUILD_DEFINE%
|
||||
%TDESKTOP_BUILD_DEFINE% ^
|
||||
-DCMAKE_SYSTEM_VERSION=%SDK%
|
||||
|
||||
cmake --build ..\out --config Debug --parallel
|
||||
cd ..\out
|
||||
msbuild -m Telegram.sln /p:Configuration=Debug,Platform=${{ matrix.arch }},DebugSymbols=false,DebugType=none
|
||||
|
||||
- name: Move artifact.
|
||||
if: (env.UPLOAD_ARTIFACT == 'true') || (github.ref == 'refs/heads/nightly')
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
run: |
|
||||
set OUT=%TBUILD%\%REPO_NAME%\out\Debug
|
||||
mkdir artifact
|
||||
move %OUT%\Telegram.exe artifact/
|
||||
move %OUT%\Updater.exe artifact/
|
||||
- uses: actions/upload-artifact@v4
|
||||
move %TBUILD%\%REPO_NAME%\out\Debug\Telegram.exe artifact/
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload artifact.
|
||||
if: (env.UPLOAD_ARTIFACT == 'true') || (github.ref == 'refs/heads/nightly')
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
with:
|
||||
name: ${{ env.ARTIFACT_NAME }}
|
||||
path: artifact\
|
||||
|
||||
20
.github/workflows/winget.yml
vendored
@@ -1,20 +0,0 @@
|
||||
name: Publish to WinGet
|
||||
on:
|
||||
release:
|
||||
types: [released, prereleased]
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: windows-latest # action can only be run on windows
|
||||
steps:
|
||||
- if: github.event.action == 'released'
|
||||
uses: telegramdesktop/winget-releaser@main
|
||||
with:
|
||||
identifier: Telegram.TelegramDesktop
|
||||
installers-regex: 't(setup|portable).*(exe|zip)$'
|
||||
token: ${{ secrets.WINGET_TOKEN }}
|
||||
- if: github.event.action == 'prereleased'
|
||||
uses: telegramdesktop/winget-releaser@main
|
||||
with:
|
||||
identifier: Telegram.TelegramDesktop.Beta
|
||||
installers-regex: 't(setup|portable).*(exe|zip)$'
|
||||
token: ${{ secrets.WINGET_TOKEN }}
|
||||
2
.gitignore
vendored
@@ -18,8 +18,6 @@ Release/
|
||||
*.xcodeproj
|
||||
ipch/
|
||||
.vs/
|
||||
.vscode/
|
||||
.cache/
|
||||
|
||||
/Telegram/log.txt
|
||||
/Telegram/data
|
||||
|
||||
33
.gitmodules
vendored
@@ -58,6 +58,9 @@
|
||||
[submodule "Telegram/ThirdParty/range-v3"]
|
||||
path = Telegram/ThirdParty/range-v3
|
||||
url = https://github.com/ericniebler/range-v3.git
|
||||
[submodule "Telegram/ThirdParty/fcitx-qt5"]
|
||||
path = Telegram/ThirdParty/fcitx-qt5
|
||||
url = https://github.com/fcitx/fcitx-qt5.git
|
||||
[submodule "Telegram/ThirdParty/nimf"]
|
||||
path = Telegram/ThirdParty/nimf
|
||||
url = https://github.com/hamonikr/nimf.git
|
||||
@@ -76,24 +79,24 @@
|
||||
[submodule "Telegram/lib_webview"]
|
||||
path = Telegram/lib_webview
|
||||
url = https://github.com/desktop-app/lib_webview.git
|
||||
[submodule "Telegram/lib_waylandshells"]
|
||||
path = Telegram/lib_waylandshells
|
||||
url = https://github.com/desktop-app/lib_waylandshells.git
|
||||
[submodule "Telegram/ThirdParty/jemalloc"]
|
||||
path = Telegram/ThirdParty/jemalloc
|
||||
url = https://github.com/jemalloc/jemalloc
|
||||
[submodule "Telegram/ThirdParty/kwayland"]
|
||||
path = Telegram/ThirdParty/kwayland
|
||||
url = https://github.com/KDE/kwayland.git
|
||||
[submodule "Telegram/ThirdParty/dispatch"]
|
||||
path = Telegram/ThirdParty/dispatch
|
||||
url = https://github.com/apple/swift-corelibs-libdispatch
|
||||
[submodule "Telegram/ThirdParty/kimageformats"]
|
||||
path = Telegram/ThirdParty/kimageformats
|
||||
url = https://github.com/KDE/kimageformats.git
|
||||
[submodule "Telegram/ThirdParty/kcoreaddons"]
|
||||
path = Telegram/ThirdParty/kcoreaddons
|
||||
url = https://github.com/KDE/kcoreaddons.git
|
||||
[submodule "Telegram/ThirdParty/cld3"]
|
||||
path = Telegram/ThirdParty/cld3
|
||||
url = https://github.com/google/cld3.git
|
||||
[submodule "Telegram/ThirdParty/libprisma"]
|
||||
path = Telegram/ThirdParty/libprisma
|
||||
url = https://github.com/desktop-app/libprisma.git
|
||||
[submodule "Telegram/ThirdParty/xdg-desktop-portal"]
|
||||
path = Telegram/ThirdParty/xdg-desktop-portal
|
||||
url = https://github.com/flatpak/xdg-desktop-portal.git
|
||||
[submodule "Telegram/ThirdParty/extra-cmake-modules"]
|
||||
path = Telegram/ThirdParty/extra-cmake-modules
|
||||
url = https://github.com/KDE/extra-cmake-modules.git
|
||||
[submodule "Telegram/ThirdParty/plasma-wayland-protocols"]
|
||||
path = Telegram/ThirdParty/plasma-wayland-protocols
|
||||
url = https://github.com/KDE/plasma-wayland-protocols.git
|
||||
[submodule "Telegram/ThirdParty/wayland-protocols"]
|
||||
path = Telegram/ThirdParty/wayland-protocols
|
||||
url = https://github.com/gitlab-freedesktop-mirrors/wayland-protocols.git
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
# For license and copyright information please follow this link:
|
||||
# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
cmake_minimum_required(VERSION 3.25...3.31)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
cmake_policy(SET CMP0076 NEW)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
@@ -14,9 +16,7 @@ desktop_app_parse_version(Telegram/build/version)
|
||||
|
||||
set(project_langs C CXX)
|
||||
if (APPLE)
|
||||
list(APPEND project_langs OBJC OBJCXX)
|
||||
elseif (LINUX)
|
||||
list(APPEND project_langs ASM)
|
||||
set(project_langs C CXX OBJC OBJCXX)
|
||||
endif()
|
||||
|
||||
project(Telegram
|
||||
@@ -31,17 +31,10 @@ get_filename_component(third_party_loc "Telegram/ThirdParty" REALPATH)
|
||||
get_filename_component(submodules_loc "Telegram" REALPATH)
|
||||
get_filename_component(cmake_helpers_loc "cmake" REALPATH)
|
||||
|
||||
if (NOT DESKTOP_APP_USE_PACKAGED AND WIN32)
|
||||
set(Python3_EXECUTABLE ${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/python/Scripts/python)
|
||||
endif()
|
||||
|
||||
include(cmake/variables.cmake)
|
||||
include(cmake/nice_target_sources.cmake)
|
||||
include(cmake/target_compile_options_if_exists.cmake)
|
||||
include(cmake/target_link_frameworks.cmake)
|
||||
include(cmake/target_link_optional_libraries.cmake)
|
||||
include(cmake/target_link_options_if_exists.cmake)
|
||||
include(cmake/target_link_static_libraries.cmake)
|
||||
include(cmake/target_link_frameworks.cmake)
|
||||
include(cmake/init_target.cmake)
|
||||
include(cmake/generate_target.cmake)
|
||||
include(cmake/nuget.cmake)
|
||||
@@ -49,10 +42,10 @@ include(cmake/validate_d3d_compiler.cmake)
|
||||
include(cmake/target_prepare_qrc.cmake)
|
||||
|
||||
include(cmake/options.cmake)
|
||||
|
||||
include(cmake/external/qt/package.cmake)
|
||||
|
||||
set(desktop_app_skip_libs
|
||||
glibmm
|
||||
variant
|
||||
)
|
||||
|
||||
|
||||
2
LEGAL
@@ -1,7 +1,7 @@
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
Copyright (c) 2014-2025 The Telegram Desktop Authors.
|
||||
Copyright (c) 2014-2022 The Telegram Desktop Authors.
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
17
README.md
@@ -1,6 +1,6 @@
|
||||
# [Telegram Desktop][telegram_desktop] – Official Messenger
|
||||
|
||||
This is the complete source code and the build instructions for the official [Telegram][telegram] messenger desktop client, based on the [Telegram API][telegram_api] and the [MTProto][telegram_proto] secure protocol.
|
||||
This is the complete source code and the build instructions for the alpha version of the official desktop client for the [Telegram][telegram] messenger, based on the [Telegram API][telegram_api] and the [MTProto][telegram_proto] secure protocol.
|
||||
|
||||
[](https://github.com/telegramdesktop/tdesktop/releases)
|
||||
[](https://github.com/telegramdesktop/tdesktop/actions)
|
||||
@@ -17,18 +17,13 @@ The latest version is available for
|
||||
|
||||
* [Windows 7 and above (64 bit)](https://telegram.org/dl/desktop/win64) ([portable](https://telegram.org/dl/desktop/win64_portable))
|
||||
* [Windows 7 and above (32 bit)](https://telegram.org/dl/desktop/win) ([portable](https://telegram.org/dl/desktop/win_portable))
|
||||
* [macOS 10.13 and above](https://telegram.org/dl/desktop/mac)
|
||||
* [macOS 10.12 and above](https://telegram.org/dl/desktop/mac)
|
||||
* [Linux static build for 64 bit](https://telegram.org/dl/desktop/linux)
|
||||
* [Snap](https://snapcraft.io/telegram-desktop)
|
||||
* [Flatpak](https://flathub.org/apps/details/org.telegram.desktop)
|
||||
|
||||
## Old system versions
|
||||
|
||||
Version **4.9.9** was the last that supports older systems
|
||||
|
||||
* [macOS 10.12](https://updates.tdesktop.com/tmac/tsetup.4.9.9.dmg)
|
||||
* [Linux with glibc < 2.28 static build](https://updates.tdesktop.com/tlinux/tsetup.4.9.9.tar.xz)
|
||||
|
||||
Version **2.4.4** was the last that supports older systems
|
||||
|
||||
* [OS X 10.10 and 10.11](https://updates.tdesktop.com/tosx/tsetup-osx.2.4.4.dmg)
|
||||
@@ -42,8 +37,8 @@ Version **1.8.15** was the last that supports older systems
|
||||
|
||||
## Third-party
|
||||
|
||||
* Qt 6 ([LGPL](http://doc.qt.io/qt-6/lgpl.html)) and Qt 5.15 ([LGPL](http://doc.qt.io/qt-5/lgpl.html)) slightly patched
|
||||
* OpenSSL 3.2.1 ([Apache License 2.0](https://www.openssl.org/source/apache-license-2.0.txt))
|
||||
* Qt 6 ([LGPL](http://doc.qt.io/qt-6/lgpl.html)) and Qt 5.15.2 ([LGPL](http://doc.qt.io/qt-5/lgpl.html)) slightly patched
|
||||
* OpenSSL 1.1.1 and 1.0.1 ([OpenSSL License](https://www.openssl.org/source/license.html))
|
||||
* WebRTC ([New BSD License](https://github.com/desktop-app/tg_owt/blob/master/LICENSE))
|
||||
* zlib 1.2.11 ([zlib License](http://www.zlib.net/zlib_license.html))
|
||||
* LZMA SDK 9.20 ([public domain](http://www.7-zip.org/sdk.html))
|
||||
@@ -58,13 +53,13 @@ Version **1.8.15** was the last that supports older systems
|
||||
* Guideline Support Library ([MIT License](https://github.com/Microsoft/GSL/blob/master/LICENSE))
|
||||
* Range-v3 ([Boost License](https://github.com/ericniebler/range-v3/blob/master/LICENSE.txt))
|
||||
* Open Sans font ([Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html))
|
||||
* Vazirmatn font ([SIL Open Font License 1.1](https://github.com/rastikerdar/vazirmatn/blob/master/OFL.txt))
|
||||
* Vazir font ([SIL Open Font License 1.1](https://github.com/rastikerdar/vazir-font/blob/master/OFL.txt))
|
||||
* Emoji alpha codes ([MIT License](https://github.com/emojione/emojione/blob/master/extras/alpha-codes/LICENSE.md))
|
||||
* Catch test framework ([Boost License](https://github.com/philsquared/Catch/blob/master/LICENSE.txt))
|
||||
* xxHash ([BSD License](https://github.com/Cyan4973/xxHash/blob/dev/LICENSE))
|
||||
* QR Code generator ([MIT License](https://github.com/nayuki/QR-Code-generator#license))
|
||||
* CMake ([New BSD License](https://github.com/Kitware/CMake/blob/master/Copyright.txt))
|
||||
* Hunspell ([LGPL](https://github.com/hunspell/hunspell/blob/master/COPYING.LESSER))
|
||||
* Ada ([Apache License 2.0](https://github.com/ada-url/ada/blob/main/LICENSE-APACHE))
|
||||
|
||||
## Build instructions
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 787 B |
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="84px" height="84px" viewBox="0 0 84 84" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>topic blue</title>
|
||||
<defs>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
|
||||
<stop stop-color="#4BB7FF" offset="0%"></stop>
|
||||
<stop stop-color="#015EC1" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="99.39588%" id="linearGradient-2">
|
||||
<stop stop-color="#0888DF" offset="0%"></stop>
|
||||
<stop stop-color="#0042AC" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="topic-blue" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M42,4.47368421 C52.6535116,4.47368421 62.3029461,8.44172846 69.286057,14.8715044 C76.2233062,21.2590526 80.5263158,30.0798831 80.5263158,39.8304382 C80.5263158,49.5809933 76.2233062,58.4018239 69.286057,64.7893721 C62.3029461,71.219148 52.6535116,75.1871923 42,75.1871923 C37.5267059,75.1871923 33.2308553,74.4877643 29.2348341,73.2001187 C29.0182529,73.1303293 28.8019654,73.0586229 28.5862413,72.9852481 C28.3948519,73.106612 28.2000814,73.2292009 28.0019297,73.3530173 C26.1800899,74.4914063 24.5768234,75.4183854 23.1902273,76.1332316 C19.9632993,77.7968433 15.8838664,78.895322 10.968708,79.4573148 L10.3331597,79.5269374 C10.8475353,78.5381033 11.3155893,77.6262907 11.7364879,76.7897918 L12.0856904,76.0911971 C13.1548056,73.9371347 13.8747553,72.3343394 14.2288664,71.2486595 C14.8154652,69.4501884 15.1095499,67.6701625 15.2363061,66.0328103 C15.2549358,65.7921643 15.2704685,65.5479168 15.2812363,65.2994157 C15.1072303,65.1457013 14.9345381,64.9902431 14.7631844,64.8330639 C7.79678435,58.4429296 3.47368421,49.6037286 3.47368421,39.8304382 C3.47368421,30.0798831 7.77669379,21.2590526 14.713943,14.8715044 C21.6970539,8.44172846 31.3464884,4.47368421 42,4.47368421 Z" id="Combined-Shape-Copy-2" stroke="url(#linearGradient-2)" stroke-width="2.94736842" fill="url(#linearGradient-1)"></path>
|
||||
<path d="M9.68078613,24.6137047 C9.8721537,24.8136848 10.1894036,24.8206666 10.3893837,24.629299 C10.3964827,24.6225057 10.4033805,24.6155051 10.410082,24.6083194 C20.5178445,13.7276637 31.3141669,8.50123177 42.7990494,8.92902374 C54.2584365,9.35586606 64.9235425,15.3681505 74.7943671,26.9658769 C75.0309355,27.243826 75.4426222,27.2904538 75.7353592,27.0724506 C76.0315877,26.8518473 76.1075038,26.440096 75.9094038,26.1283693 C67.7821181,13.3374534 56.7453333,6.69089625 42.7990494,6.18869781 C28.8220513,5.68539338 17.7581791,11.5492352 9.60743269,23.7802233 C9.4336795,24.0409463 9.46416665,24.3873362 9.68078613,24.6137047 Z" id="Path-22" fill="#71D0FF" opacity="0.37491644"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>general</title>
|
||||
<g id="general" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M14.4576257,1.02558449 C15.189053,1.1696007 15.6657078,1.88165413 15.5222641,2.61600035 L14.8818905,5.62412405 L16.6504058,5.62421139 C17.3957661,5.62421139 18,6.23085664 18,6.97919149 C18,7.72752633 17.3957661,8.33417159 16.6504058,8.33417159 L14.3525674,8.33397488 L13.6850637,11.7513347 L15.3008116,11.7515071 C16.0461719,11.7515071 16.6504058,12.3581524 16.6504058,13.1064872 C16.6504058,13.8548221 16.0461719,14.4614673 15.3008116,14.4614673 L13.1557407,14.4614328 L12.4307242,17.9055215 C12.2872804,18.6398677 11.5780573,19.1184247 10.84663,18.9744085 C10.1152028,18.8303923 9.63854794,18.1183389 9.7819917,17.3839927 L10.4051821,14.4614328 L7.75733538,14.4614328 L7.03234733,17.9055215 C6.90989534,18.5324024 6.37514133,18.9728813 5.76623746,18.9987859 L5.71387199,19 C5.62631985,19.0002755 5.53745163,18.9919715 5.44825318,18.9744085 C4.71682589,18.8303923 4.24017107,18.1183389 4.38361482,17.3839927 L5.00702313,14.4614328 L3.34959422,14.4614673 C2.60423391,14.4614673 2,13.8548221 2,13.1064872 C2,12.3581524 2.60423391,11.7515071 3.34959422,11.7515071 L5.53634616,11.7513347 L6.20384986,8.33397488 L4.69918844,8.33417159 C3.95382813,8.33417159 3.34959422,7.72752633 3.34959422,6.97919149 C3.34959422,6.23085664 3.95382813,5.62421139 4.69918844,5.62421139 L6.73317289,5.62412405 L7.4751547,2.09447154 C7.60110532,1.44967974 8.16325465,1.00209364 8.79363004,1 L8.84631136,1.00087004 C8.91674267,1.00340951 8.98789009,1.01153413 9.05924885,1.02558449 C9.79067614,1.1696007 10.267331,1.88165413 10.1238872,2.61600035 L9.48348515,5.62412405 L12.1315782,5.62412405 L12.8735316,2.09447154 C13.0169753,1.36012532 13.7261984,0.881568286 14.4576257,1.02558449 Z M10.9345052,11.7513347 L11.6020089,8.33397488 L8.95416211,8.33397488 L8.28665842,11.7513347 L10.9345052,11.7513347 Z" id="Combined-Shape-Copy-6" fill="#FFFFFF"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="84px" height="84px" viewBox="0 0 84 84" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>topic gray</title>
|
||||
<defs>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
|
||||
<stop stop-color="#A5A5A5" offset="0%"></stop>
|
||||
<stop stop-color="#616161" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="99.39588%" id="linearGradient-2">
|
||||
<stop stop-color="#737373" offset="0%"></stop>
|
||||
<stop stop-color="#565656" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="topic-gray" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M42,4.47368421 C52.6535116,4.47368421 62.3029461,8.44172846 69.286057,14.8715044 C76.2233062,21.2590526 80.5263158,30.0798831 80.5263158,39.8304382 C80.5263158,49.5809933 76.2233062,58.4018239 69.286057,64.7893721 C62.3029461,71.219148 52.6535116,75.1871923 42,75.1871923 C37.5267059,75.1871923 33.2308553,74.4877643 29.2348341,73.2001187 C29.0182529,73.1303293 28.8019654,73.0586229 28.5862413,72.9852481 C28.3948519,73.106612 28.2000814,73.2292009 28.0019297,73.3530173 C26.1800899,74.4914063 24.5768234,75.4183854 23.1902273,76.1332316 C19.9632993,77.7968433 15.8838664,78.895322 10.968708,79.4573148 L10.3331597,79.5269374 C10.8475353,78.5381033 11.3155893,77.6262907 11.7364879,76.7897918 L12.0856904,76.0911971 C13.1548056,73.9371347 13.8747553,72.3343394 14.2288664,71.2486595 C14.8154652,69.4501884 15.1095499,67.6701625 15.2363061,66.0328103 C15.2549358,65.7921643 15.2704685,65.5479168 15.2812363,65.2994157 C15.1072303,65.1457013 14.9345381,64.9902431 14.7631844,64.8330639 C7.79678435,58.4429296 3.47368421,49.6037286 3.47368421,39.8304382 C3.47368421,30.0798831 7.77669379,21.2590526 14.713943,14.8715044 C21.6970539,8.44172846 31.3464884,4.47368421 42,4.47368421 Z" id="Combined-Shape-Copy-2" stroke="url(#linearGradient-2)" stroke-width="2.94736842" fill="url(#linearGradient-1)"></path>
|
||||
<path d="M9.68078613,24.6137047 C9.8721537,24.8136848 10.1894036,24.8206666 10.3893837,24.629299 C10.3964827,24.6225057 10.4033805,24.6155051 10.410082,24.6083194 C20.5178445,13.7276637 31.3141669,8.50123177 42.7990494,8.92902374 C54.2584365,9.35586606 64.9235425,15.3681505 74.7943671,26.9658769 C75.0309355,27.243826 75.4426222,27.2904538 75.7353592,27.0724506 C76.0315877,26.8518473 76.1075038,26.440096 75.9094038,26.1283693 C67.7821181,13.3374534 56.7453333,6.69089625 42.7990494,6.18869781 C28.8220513,5.68539338 17.7581791,11.5492352 9.60743269,23.7802233 C9.4336795,24.0409463 9.46416665,24.3873362 9.68078613,24.6137047 Z" id="Path-22" fill="#B8B8B8" opacity="0.37491644"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="84px" height="84px" viewBox="0 0 84 84" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>topic green</title>
|
||||
<defs>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="99.7635421%" id="linearGradient-1">
|
||||
<stop stop-color="#97E334" offset="0%"></stop>
|
||||
<stop stop-color="#11B411" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="98.9250576%" id="linearGradient-2">
|
||||
<stop stop-color="#48AF18" offset="0%"></stop>
|
||||
<stop stop-color="#05951A" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="topic-green" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M42,4.42105263 C52.6675181,4.42105263 62.3294728,8.39460913 69.3217075,14.8327858 C76.2697184,21.230243 80.5789474,30.0648871 80.5789474,39.8304382 C80.5789474,49.5959894 76.2697184,58.4306335 69.3217075,64.8280906 C62.3294728,71.2662674 52.6675181,75.2398239 42,75.2398239 C37.5210466,75.2398239 33.2197662,74.5394876 29.2186919,73.2502137 C29.0098956,73.1829329 28.8013719,73.1138726 28.5929684,73.0432995 C28.4083865,73.1602808 28.2206704,73.2783974 28.0298198,73.3976517 C26.2065565,74.5369301 24.6020235,75.4646079 23.2143446,76.1800123 C19.9826132,77.8461004 15.8972513,78.9467661 10.9744394,79.5096334 L10.3380323,79.5793501 C12.3422829,75.5502987 13.657562,72.8305079 14.1788292,71.2323391 C14.7640488,69.4380965 15.0573738,67.6622454 15.1838316,66.0287479 C15.2017691,65.7970433 15.21683,65.561992 15.2283048,65.3228731 C15.0601712,65.1741519 14.8932645,65.0238038 14.727607,64.8718496 C7.75040024,58.4718025 3.42105263,49.6187586 3.42105263,39.8304382 C3.42105263,30.0648871 7.7302816,21.230243 14.6782925,14.8327858 C21.6705272,8.39460913 31.3324819,4.42105263 42,4.42105263 Z" id="Combined-Shape-Copy-2" stroke="url(#linearGradient-2)" stroke-width="2.84210526" fill="url(#linearGradient-1)"></path>
|
||||
<path d="M9.68078613,24.6137047 C9.8721537,24.8136848 10.1894036,24.8206666 10.3893837,24.629299 C10.3964827,24.6225057 10.4033805,24.6155051 10.410082,24.6083194 C20.5178445,13.7276637 31.3141669,8.50123177 42.7990494,8.92902374 C54.2584365,9.35586606 64.9235425,15.3681505 74.7943671,26.9658769 C75.0309355,27.243826 75.4426222,27.2904538 75.7353592,27.0724506 C76.0315877,26.8518473 76.1075038,26.440096 75.9094038,26.1283693 C67.7821181,13.3374534 56.7453333,6.69089625 42.7990494,6.18869781 C28.8220513,5.68539338 17.7581791,11.5492352 9.60743269,23.7802233 C9.4336795,24.0409463 9.46416665,24.3873362 9.68078613,24.6137047 Z" id="Path-22" fill="#C2FF71" opacity="0.37491644"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.7 KiB |
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="84px" height="84px" viewBox="0 0 84 84" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>topic red</title>
|
||||
<defs>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
|
||||
<stop stop-color="#FF714C" offset="0%"></stop>
|
||||
<stop stop-color="#C61505" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="98.6056043%" id="linearGradient-2">
|
||||
<stop stop-color="#E12F1F" offset="0%"></stop>
|
||||
<stop stop-color="#B40101" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="topic-red" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M42,4.42105263 C52.6675181,4.42105263 62.3294728,8.39460913 69.3217075,14.8327858 C76.2697184,21.230243 80.5789474,30.0648871 80.5789474,39.8304382 C80.5789474,49.5959894 76.2697184,58.4306335 69.3217075,64.8280906 C62.3294728,71.2662674 52.6675181,75.2398239 42,75.2398239 C37.5210466,75.2398239 33.2197662,74.5394876 29.2186919,73.2502137 C29.0098956,73.1829329 28.8013719,73.1138726 28.5929684,73.0432995 C28.4083865,73.1602808 28.2206704,73.2783974 28.0298198,73.3976517 C26.2065565,74.5369301 24.6020235,75.4646079 23.2143446,76.1800123 C19.9826132,77.8461004 15.8972513,78.9467661 10.9744394,79.5096334 L10.3380323,79.5793501 C12.3422829,75.5502987 13.657562,72.8305079 14.1788292,71.2323391 C14.7640488,69.4380965 15.0573738,67.6622454 15.1838316,66.0287479 C15.2017691,65.7970433 15.21683,65.561992 15.2283048,65.3228731 C15.0601712,65.1741519 14.8932645,65.0238038 14.727607,64.8718496 C7.75040024,58.4718025 3.42105263,49.6187586 3.42105263,39.8304382 C3.42105263,30.0648871 7.7302816,21.230243 14.6782925,14.8327858 C21.6705272,8.39460913 31.3324819,4.42105263 42,4.42105263 Z" id="Combined-Shape-Copy-2" stroke="url(#linearGradient-2)" stroke-width="2.84210526" fill="url(#linearGradient-1)"></path>
|
||||
<path d="M9.68078613,24.6137047 C9.8721537,24.8136848 10.1894036,24.8206666 10.3893837,24.629299 C10.3964827,24.6225057 10.4033805,24.6155051 10.410082,24.6083194 C20.5178445,13.7276637 31.3141669,8.50123177 42.7990494,8.92902374 C54.2584365,9.35586606 64.9235425,15.3681505 74.7943671,26.9658769 C75.0309355,27.243826 75.4426222,27.2904538 75.7353592,27.0724506 C76.0315877,26.8518473 76.1075038,26.440096 75.9094038,26.1283693 C67.7821181,13.3374534 56.7453333,6.69089625 42.7990494,6.18869781 C28.8220513,5.68539338 17.7581791,11.5492352 9.60743269,23.7802233 C9.4336795,24.0409463 9.46416665,24.3873362 9.68078613,24.6137047 Z" id="Path-22" fill="#FFB47D" opacity="0.37491644"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.7 KiB |