> ## Documentation Index
> Fetch the complete documentation index at: https://www.mellowtel.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Інтеграція Mellowtel у ваш додаток для Windows

Інтегруйте Mellowtel у ваш додаток для Windows, щоб дозволити користувачам ділитися невикористаною пропускною здатністю інтернету в обмін на винагороди або преміум-функції.

<Warning>
  **Згода користувача є обов’язковою.** SDK викидає `InvalidOperationException`, якщо ви викликаєте `StartAsync()` без того, щоб користувач погодився.
</Warning>

## Попередні вимоги

* Обліковий запис Mellowtel та **Integration ID** з [панелі керування](https://www.mellowtel.com/mellowtel-auth/). Кожен додаток отримує свій унікальний Integration ID.
* .NET 10 SDK
* Windows 10 або Windows 11
* Додаток на .NET (Console, WPF або Windows Forms)

<Note>
  Хочете побачити повну інтеграцію в реальному світі перед тим, як підключити це до свого додатку? Зразок [mellowtel-pomodoro-windows](https://github.com/mellowtel-inc/mellowtel-pomodoro-windows) для WPF показує повний потік від початку до кінця: діалог згоди, перемикач налаштувань та фоновий життєвий цикл.
</Note>

***

## Встановлення

Mellowtel для Windows доступний на NuGet як [`Mellowtel.Win`](https://www.nuget.org/packages/Mellowtel.Win).

### 1. Встановіть пакет

З вашої директорії проекту:

```bash theme={null}
dotnet add package Mellowtel.Win
```

Або додайте `PackageReference` до вашого `.csproj`:

```xml theme={null}
<PackageReference Include="Mellowtel.Win" Version="1.0.0" />
```

### 2. Додайте до вашого коду

```csharp theme={null}
using MellowtelWin;

// Ініціалізуйте Mellowtel з вашим Integration ID
var mellowtel = new Mellowtel("YOUR_INTEGRATION_ID", new MellowtelOptions
{
    PluginId = "your-app-id"
});

// Якщо користувач вже погодився, відновіть роботу без повідомлення.
// Якщо ні, це нічого не робить і повертає false.
await mellowtel.StartIfOptedInAsync();

// Потік для першого запуску: покажіть свій інтерфейс згоди, потім погодьтеся і почніть.
if (!mellowtel.GetOptInStatus() && ShowConsentDialog())
{
    mellowtel.OptIn();
    await mellowtel.StartAsync();
}

// При завершенні роботи додатку
await mellowtel.StopAsync();
mellowtel.Dispose();
```

<Note>
  Замініть `YOUR_INTEGRATION_ID` на Integration ID з вашої панелі керування Mellowtel, і встановіть `PluginId` як стабільний ідентифікатор для вашого додатку. `ShowConsentDialog()` — це ваш власний інтерфейс, який повертає `true` тільки тоді, коли користувач явно погоджується. Дивіться [Згода користувача](#user-consent) нижче.
</Note>

### Опції конфігурації

`MellowtelOptions` дозволяє налаштувати кілька параметрів:

| Властивість    | Тип      | За замовчуванням                    | Опис                                                                          |
| -------------- | -------- | ----------------------------------- | ----------------------------------------------------------------------------- |
| `PluginId`     | `string` | `"mellowtel-win"`                   | Стабільний ідентифікатор для вашого додатку. Встановіть це на щось унікальне. |
| `MaxDailyRate` | `int`    | Вбудоване значення за замовчуванням | Максимальна кількість запитів, які SDK обробляє за день.                      |
| `DisableLogs`  | `bool`   | `true`                              | Встановіть `false`, щоб увімкнути журнали SDK під час розробки.               |

***

## Приклади за типом додатку

<Tabs>
  <Tab title="Консольний додаток">
    ```csharp theme={null}
    using MellowtelWin;

    class Program
    {
        static async Task Main(string[] args)
        {
            using var mellowtel = new Mellowtel("YOUR_INTEGRATION_ID", new MellowtelOptions
            {
                PluginId = "your-app-id"
            });

            if (!mellowtel.GetOptInStatus())
            {
                Console.WriteLine("Користувач повинен погодитися перед використанням цієї служби.");
                return;
            }

            using var cts = new CancellationTokenSource();
            Console.CancelKeyPress += (s, e) => { e.Cancel = true; cts.Cancel(); };

            try
            {
                await mellowtel.StartAsync(cts.Token);
                Console.WriteLine("Mellowtel працює. Натисніть Ctrl+C, щоб зупинити.");
                await Task.Delay(Timeout.Infinite, cts.Token);
            }
            catch (InvalidOperationException ex)
            {
                Console.WriteLine($"Не можна запустити: {ex.Message}");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("Зупинка...");
            }
            finally
            {
                await mellowtel.StopAsync();
            }
        }
    }
    ```
  </Tab>

  <Tab title="WPF Додаток">
    Додайте до вашого `MainWindow.xaml.cs`:

    ```csharp theme={null}
    using MellowtelWin;
    using System.Windows;

    public partial class MainWindow : Window
    {
        private Mellowtel? _mellowtel;

        public MainWindow()
        {
            InitializeComponent();
            Loaded += Window_Loaded;
        }

        private async void Window_Loaded(object sender, RoutedEventArgs e)
        {
            _mellowtel = new Mellowtel("YOUR_INTEGRATION_ID", new MellowtelOptions
            {
                PluginId = "your-app-id"
            });

            _mellowtel.ConnectionStateChanged += (s, connected) =>
            {
                Dispatcher.Invoke(() =>
                {
                    StatusTextBlock.Text = connected ? "Підключено" : "Відключено";
                });
            };

            // Відновіть роботу без повідомлення, якщо вже погоджено. Інакше покажіть свій інтерфейс згоди.
            var started = await _mellowtel.StartIfOptedInAsync();
            if (!started)
            {
                // Покажіть свій діалог згоди тут
            }
        }

        protected override async void OnClosing(CancelEventArgs e)
        {
            if (_mellowtel != null)
            {
                await _mellowtel.StopAsync();
                _mellowtel.Dispose();
            }
            base.OnClosing(e);
        }
    }
    ```
  </Tab>

  <Tab title="Windows Forms">
    Додайте до вашого `MainForm.cs`:

    ```csharp theme={null}
    using MellowtelWin;

    public partial class MainForm : Form
    {
        private Mellowtel? _mellowtel;

        public MainForm()
        {
            InitializeComponent();
            Load += MainForm_Load;
            FormClosing += MainForm_FormClosing;
        }

        private async void MainForm_Load(object sender, EventArgs e)
        {
            _mellowtel = new Mellowtel("YOUR_INTEGRATION_ID", new MellowtelOptions
            {
                PluginId = "your-app-id"
            });

            _mellowtel.ConnectionStateChanged += (s, connected) =>
            {
                if (InvokeRequired)
                    Invoke(() => statusLabel.Text = connected ? "Підключено" : "Відключено");
                else
                    statusLabel.Text = connected ? "Підключено" : "Відключено";
            };

            // Відновіть роботу без повідомлення, якщо вже погоджено. Інакше покажіть свій інтерфейс згоди.
            var started = await _mellowtel.StartIfOptedInAsync();
            if (!started)
            {
                // Покажіть свій діалог згоди тут
            }
        }

        private async void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_mellowtel != null)
            {
                await _mellowtel.StopAsync();
                _mellowtel.Dispose();
            }
        }
    }
    ```
  </Tab>
</Tabs>

### Спостереження за станом підключення

Екземпляр `Mellowtel` надає подію `ConnectionStateChanged`, яка викликається щоразу, коли підключення WebSocket до бекенду Mellowtel підключається або відключається. Приклади для WPF та Windows Forms вище підписуються на цю подію, щоб керувати індикатором стану. Навантаження — це `bool`, де `true` означає підключено, а `false` означає відключено.

Подія викликається у фоновому потоці, тому UI-фреймворки, які забезпечують прив'язку до потоку, повинні передавати оновлення на UI-потік. У WPF використовуйте `Dispatcher.Invoke`, а в Windows Forms використовуйте `Control.Invoke` (обидва показані у прикладах вище).

<Note>
  **Про WPF `async void OnClosing` патерн.** Приклад WPF вище використовує `protected override async void OnClosing`, що є найпростішою формою, але має тонку проблему: `base.OnClosing(e)` викликається синхронно, поки `StopAsync()` ще очікує, тому вікно може закритися до завершення очищення. Для більшості додатків це нормально, оскільки процес завершується відразу після цього. Якщо вам потрібне гарантоване плавне завершення (наприклад, щоб зберегти телеметрію), дотримуйтесь [документованого Microsoft патерну відкладення](https://learn.microsoft.com/en-us/dotnet/api/system.windows.window.closing), де ви встановлюєте `e.Cancel = true`, `await` вашої асинхронної роботи, а потім явно закриваєте вікно.
</Note>

***

## Згода користувача

<Warning>
  Відображення діалогу згоди є **обов’язковим**. SDK це забезпечує: `StartAsync()` викидає `InvalidOperationException`, якщо користувач не погодився.
</Warning>

```csharp theme={null}
var mellowtel = new Mellowtel("YOUR_INTEGRATION_ID", new MellowtelOptions
{
    PluginId = "your-app-id"
});

if (!mellowtel.GetOptInStatus())
{
    var userAgreed = ShowConsentDialog(); // ваш власний діалог

    if (userAgreed)
        mellowtel.OptIn();
    else
        return; // користувач відмовився, не починайте
}

try
{
    await mellowtel.StartAsync();
}
catch (InvalidOperationException ex)
{
    Console.WriteLine($"Помилка: {ex.Message}");
}
```

### Що має включати ваш діалог згоди

<Steps>
  <Step title="Поясніть, що робить Mellowtel">
    Використовуйте просту мову. Приклад: *"Цей додаток використовує Mellowtel для обміну вашою невикористаною пропускною здатністю інтернету. Це дозволяє вам \[користь/функція]. Ви можете відмовитися в будь-який час у налаштуваннях."*
  </Step>

  <Step title="Надайте користувачам чіткий вибір">
    Включіть окремі варіанти Прийняти та Відхилити.
  </Step>

  <Step title="Посилання на політики">
    Включіть посилання на [Умови використання](https://www.mellowtel.com/terms-and-conditions) та [Політику конфіденційності](https://www.mellowtel.com/privacy-policy).
  </Step>
</Steps>

### Дозвольте користувачам змінювати свою згоду в налаштуваннях

```csharp theme={null}
// Перевірте поточний статус
bool isOptedIn = mellowtel.GetOptInStatus();

// Відмова
if (userWantsToOptOut)
{
    mellowtel.OptOut();
    await mellowtel.StopAsync();
}

// Повернення згоди
if (userWantsToOptIn)
{
    mellowtel.OptIn();
    await mellowtel.StartAsync();
}
```

Для більш багатого інтерфейсу (наприклад, показуючи, коли користувач вперше погодився), `GetOptInDetails()` повертає статус згоди разом з датами згоди та відмови:

```csharp theme={null}
var (isOptedIn, optInDate, optOutDate) = mellowtel.GetOptInDetails();
```

***

## Усунення несправностей

<AccordionGroup>
  <Accordion title="Помилка &#x22;Пакет не знайдено&#x22;">
    1. Переконайтеся, що ваш проект націлений на **.NET 10** або пізнішу версію. `Mellowtel.Win` вимагає `net10.0`.
    2. Очистіть кеш NuGet і відновіть:

    ```bash theme={null}
    dotnet nuget locals all --clear
    dotnet restore
    ```
  </Accordion>

  <Accordion title="Помилка &#x22;InvalidOperationException: Користувач не погодився&#x22;">
    `StartAsync()` вимагає явної згоди. Викличте `OptIn()` після того, як ваш діалог згоди поверне позитивний результат, потім викличте `StartAsync()`. Для безмовного відновлення при наступних запусках використовуйте `StartIfOptedInAsync()`, що нічого не робить, коли користувач не погодився.
  </Accordion>
</AccordionGroup>

***

Орієнтовний час завершення: 10-15 хвилин.

Якщо вам потрібна допомога або у вас є відгуки, зв'яжіться з нами за адресою [info@mellowtel.com](mailto:info@mellowtel.com) або приєднуйтесь до нашої [спільноти в Discord](https://discord.com/invite/txAZp4MSDe).
