feat: add optional feature flags for clipboard and url-open (P5.15)

Implemented feature flags to make dependencies optional:
- clipboard feature: controls arboard dependency
- url-open feature: controls open dependency
- Both enabled by default for backward compatibility

Changes:
- Cargo.toml: Added [features] section with optional deps
- src/input/main_input.rs: Conditional compilation for open::that() and copy_to_clipboard()
- tests/copy.rs: Clipboard tests only compile with feature enabled
- Graceful degradation: user-friendly error messages when features disabled

Benefits:
- Smaller binary size when features disabled
- Modular functionality
- Better platform compatibility

Progress: Priority 5: 1/3 tasks, Total: 17/20 (85%)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Kilin
2026-02-01 02:23:17 +03:00
parent 38b18e35ea
commit 56bddabbe1
5 changed files with 63 additions and 22 deletions

View File

@@ -903,16 +903,21 @@ let message = MessageBuilder::new(MessageId::new(123))
- ✅ Priority 1: 3/3 (100%) - ✅ Priority 1: 3/3 (100%)
- ✅ Priority 2: 5/5 (100%) - ✅ Priority 2: 5/5 (100%)
- ✅ Priority 3: 4/4 (100%) 🎉 - ✅ Priority 3: 4/4 (100%) 🎉
- Priority 4: 1/4 (25%, P4.12 частично) - ✅ Priority 4: 4/4 (100%) 🎉
- ⏳ Priority 5: 0/3 - ⏳ Priority 5: 1/3 (33%, P5.15 завершено)
**Общий прогресс: 12/17 задач (71%)** **Общий прогресс: 17/20 задач (85%)**
**Последние изменения (1 февраля 2026)**:
- ✅ **P5.15 — Feature flags для зависимостей** (2026-02-01)
- Добавлены опциональные features `clipboard` и `url-open` в Cargo.toml
- Зависимости `arboard` и `open` теперь опциональные
- Условная компиляция в коде с graceful degradation
- Преимущества: уменьшение размера бинарника, модульность
**Следующие шаги**: **Следующие шаги**:
- Продолжить P4.12: добавить rustdoc для остальных модулей - P5.16: LRU cache обобщение
- P4.11: Добавить юнит-тесты для utils - P5.17: Tracing вместо println!
- P4.13: Улучшить config validation
- P4.14: Проверить async/await консистентность
## Известные проблемы ## Известные проблемы

View File

@@ -9,6 +9,11 @@ repository = "https://github.com/your-username/tele-tui"
keywords = ["telegram", "tui", "terminal", "cli"] keywords = ["telegram", "tui", "terminal", "cli"]
categories = ["command-line-utilities"] categories = ["command-line-utilities"]
[features]
default = ["clipboard", "url-open"]
clipboard = ["dep:arboard"]
url-open = ["dep:open"]
[dependencies] [dependencies]
ratatui = "0.29" ratatui = "0.29"
crossterm = "0.28" crossterm = "0.28"
@@ -18,8 +23,8 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
dotenvy = "0.15" dotenvy = "0.15"
chrono = "0.4" chrono = "0.4"
open = "5.0" open = { version = "5.0", optional = true }
arboard = "3.4" arboard = { version = "3.4", optional = true }
toml = "0.8" toml = "0.8"
dirs = "5.0" dirs = "5.0"
thiserror = "1.0" thiserror = "1.0"

View File

@@ -696,7 +696,7 @@ async fn load_messages() {
## Приоритет 5: Опциональные улучшения ## Приоритет 5: Опциональные улучшения
### 15. Feature flags для зависимостей ### 15. Feature flags для зависимостей ✅ ЗАВЕРШЕНО
**Проблема**: Все зависимости всегда включены. **Проблема**: Все зависимости всегда включены.
@@ -706,11 +706,25 @@ async fn load_messages() {
default = ["clipboard", "url-open"] default = ["clipboard", "url-open"]
clipboard = ["dep:arboard"] clipboard = ["dep:arboard"]
url-open = ["dep:open"] url-open = ["dep:open"]
[dependencies]
arboard = { version = "3.4", optional = true }
open = { version = "5.0", optional = true }
``` ```
**Реализовано**:
- ✅ Добавлены feature flags в Cargo.toml
- ✅ Зависимости `arboard` и `open` сделаны опциональными
- ✅ Условная компиляция в `src/input/main_input.rs`:
- `#[cfg(feature = "url-open")]` для `open::that()`
- `#[cfg(feature = "clipboard")]` / `#[cfg(not(feature = "clipboard"))]` для `copy_to_clipboard()`
- ✅ Условная компиляция в `tests/copy.rs`:
- `#[cfg(all(test, feature = "clipboard"))]` для clipboard тестов
**Преимущества**: **Преимущества**:
- Уменьшение размера бинарника - Уменьшение размера бинарника
- Опциональная функциональность - Опциональная функциональность
- ✅ Graceful degradation при отключении фич
--- ---
@@ -767,9 +781,10 @@ tracing-subscriber = "0.3"
- [x] P4.12 — Rustdoc ✅ - [x] P4.12 — Rustdoc ✅
- [x] P4.13 — Config validation ✅ - [x] P4.13 — Config validation ✅
- [x] P4.14 — Async/await consistency ✅ - [x] P4.14 — Async/await consistency ✅
- [ ] Priority 5: 0/3 задач - [ ] Priority 5: 1/3 задач
- [x] P5.15 — Feature flags ✅
**Всего**: 16/17 задач (94%) **Всего**: 17/20 задач (85%)
--- ---

View File

@@ -138,6 +138,8 @@ pub async fn handle(app: &mut App, key: KeyEvent) {
"https://t.me/{}", "https://t.me/{}",
username.trim_start_matches('@') username.trim_start_matches('@')
); );
#[cfg(feature = "url-open")]
{
match open::that(&url) { match open::that(&url) {
Ok(_) => { Ok(_) => {
app.status_message = Some(format!("Открыто: {}", url)); app.status_message = Some(format!("Открыто: {}", url));
@@ -148,6 +150,13 @@ pub async fn handle(app: &mut App, key: KeyEvent) {
} }
} }
} }
#[cfg(not(feature = "url-open"))]
{
app.error_message = Some(
"Открытие URL недоступно (требуется feature 'url-open')".to_string()
);
}
}
return; return;
} }
current_idx += 1; current_idx += 1;
@@ -1057,6 +1066,7 @@ fn get_available_actions_count(profile: &crate::tdlib::ProfileInfo) -> usize {
} }
/// Копирует текст в системный буфер обмена /// Копирует текст в системный буфер обмена
#[cfg(feature = "clipboard")]
fn copy_to_clipboard(text: &str) -> Result<(), String> { fn copy_to_clipboard(text: &str) -> Result<(), String> {
use arboard::Clipboard; use arboard::Clipboard;
@@ -1069,6 +1079,12 @@ fn copy_to_clipboard(text: &str) -> Result<(), String> {
Ok(()) Ok(())
} }
/// Заглушка для copy_to_clipboard когда feature "clipboard" выключена
#[cfg(not(feature = "clipboard"))]
fn copy_to_clipboard(_text: &str) -> Result<(), String> {
Err("Копирование в буфер обмена недоступно (требуется feature 'clipboard')".to_string())
}
/// Форматирует сообщение для копирования с контекстом /// Форматирует сообщение для копирования с контекстом
fn format_message_for_clipboard(msg: &crate::tdlib::MessageInfo) -> String { fn format_message_for_clipboard(msg: &crate::tdlib::MessageInfo) -> String {
let mut result = String::new(); let mut result = String::new();

View File

@@ -111,7 +111,7 @@ fn format_message_for_test(msg: &tele_tui::tdlib::MessageInfo) -> String {
result result
} }
#[cfg(test)] #[cfg(all(test, feature = "clipboard"))]
mod clipboard_tests { mod clipboard_tests {
use super::*; use super::*;