Compare commits
8 Commits
c4e8d64710
...
v0.6.3
| Author | SHA1 | Date | |
|---|---|---|---|
| 436b3f85d0 | |||
| 9c1a9cc3c5 | |||
| 9599ac28ca | |||
| e71a699ed8 | |||
| ff4eb8ca98 | |||
| b69973b9af | |||
| 3e133fa147 | |||
| ae506789ab |
@@ -50,8 +50,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Install Commitizen
|
- name: Install Commitizen
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python3 -m pip install --upgrade pip
|
||||||
pip install commitizen
|
pip3 install commitizen==4.8.3
|
||||||
npm install -g conventional-changelog-cli
|
npm install -g conventional-changelog-cli
|
||||||
|
|
||||||
- name: Configure Git user
|
- name: Configure Git user
|
||||||
|
|||||||
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## v0.6.3 (2025-12-13)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- Wrapped all Sonarr use of Language with Option to fix the 'null' array issue in the new Sonarr API
|
||||||
|
|
||||||
|
## v0.6.2 (2025-12-12)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- Fixed breaking Sonarr Episode file API calls after recent Sonarr API update
|
||||||
|
|
||||||
|
### Refactor
|
||||||
|
|
||||||
|
- Replaced all modulo usages of tick_until_poll with is_multiple_of
|
||||||
|
|
||||||
## v0.6.1 (2025-09-02)
|
## v0.6.1 (2025-09-02)
|
||||||
|
|
||||||
### Fix
|
### Fix
|
||||||
|
|||||||
Generated
+645
-483
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "managarr"
|
name = "managarr"
|
||||||
version = "0.6.1"
|
version = "0.6.3"
|
||||||
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
|
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
|
||||||
description = "A TUI and CLI to manage your Servarrs"
|
description = "A TUI and CLI to manage your Servarrs"
|
||||||
keywords = ["managarr", "ratatui", "dashboard", "servarr", "tui"]
|
keywords = ["managarr", "ratatui", "dashboard", "servarr", "tui"]
|
||||||
|
|||||||
+4
-1
@@ -160,7 +160,10 @@ impl App<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_tick(&mut self) {
|
pub async fn on_tick(&mut self) {
|
||||||
if self.tick_count % self.tick_until_poll == 0 || self.is_routing || self.should_refresh {
|
if self.tick_count.is_multiple_of(self.tick_until_poll)
|
||||||
|
|| self.is_routing
|
||||||
|
|| self.should_refresh
|
||||||
|
{
|
||||||
match self.get_current_route() {
|
match self.get_current_route() {
|
||||||
Route::Radarr(active_radarr_block, _) => self.radarr_on_tick(active_radarr_block).await,
|
Route::Radarr(active_radarr_block, _) => self.radarr_on_tick(active_radarr_block).await,
|
||||||
Route::Sonarr(active_sonarr_block, _) => self.sonarr_on_tick(active_sonarr_block).await,
|
Route::Sonarr(active_sonarr_block, _) => self.sonarr_on_tick(active_sonarr_block).await,
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ impl App<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.tick_count % self.tick_until_poll == 0 {
|
if self.tick_count.is_multiple_of(self.tick_until_poll) {
|
||||||
self.refresh_radarr_metadata().await;
|
self.refresh_radarr_metadata().await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ impl App<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.tick_count % self.tick_until_poll == 0 {
|
if self.tick_count.is_multiple_of(self.tick_until_poll) {
|
||||||
self.refresh_sonarr_metadata().await;
|
self.refresh_sonarr_metadata().await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{command, Subcommand};
|
use clap::Subcommand;
|
||||||
use clap_complete::Shell;
|
use clap_complete::Shell;
|
||||||
use radarr::{RadarrCliHandler, RadarrCommand};
|
use radarr::{RadarrCliHandler, RadarrCommand};
|
||||||
use sonarr::{SonarrCliHandler, SonarrCommand};
|
use sonarr::{SonarrCliHandler, SonarrCommand};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{arg, command, ArgAction, Subcommand};
|
use clap::{ArgAction, Subcommand};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
use super::RadarrCommand;
|
use super::RadarrCommand;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{command, Subcommand};
|
use clap::Subcommand;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{command, Subcommand};
|
use clap::Subcommand;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|||||||
@@ -445,13 +445,25 @@ mod tests {
|
|||||||
let a_languages = a
|
let a_languages = a
|
||||||
.languages
|
.languages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|lang| lang.name.to_lowercase())
|
.map(|lang| {
|
||||||
|
lang
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Default::default())
|
||||||
|
.name
|
||||||
|
.to_lowercase()
|
||||||
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
let b_languages = b
|
let b_languages = b
|
||||||
.languages
|
.languages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|lang| lang.name.to_lowercase())
|
.map(|lang| {
|
||||||
|
lang
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Default::default())
|
||||||
|
.name
|
||||||
|
.to_lowercase()
|
||||||
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
@@ -607,10 +619,10 @@ mod tests {
|
|||||||
BlocklistItem {
|
BlocklistItem {
|
||||||
id: 3,
|
id: 3,
|
||||||
source_title: "test 1".to_owned(),
|
source_title: "test 1".to_owned(),
|
||||||
languages: vec![Language {
|
languages: vec![Some(Language {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "telgu".to_owned(),
|
name: "telgu".to_owned(),
|
||||||
}],
|
})],
|
||||||
quality: QualityWrapper {
|
quality: QualityWrapper {
|
||||||
quality: Quality {
|
quality: Quality {
|
||||||
name: "HD - 1080p".to_owned(),
|
name: "HD - 1080p".to_owned(),
|
||||||
@@ -623,10 +635,10 @@ mod tests {
|
|||||||
BlocklistItem {
|
BlocklistItem {
|
||||||
id: 2,
|
id: 2,
|
||||||
source_title: "test 2".to_owned(),
|
source_title: "test 2".to_owned(),
|
||||||
languages: vec![Language {
|
languages: vec![Some(Language {
|
||||||
id: 3,
|
id: 3,
|
||||||
name: "chinese".to_owned(),
|
name: "chinese".to_owned(),
|
||||||
}],
|
})],
|
||||||
quality: QualityWrapper {
|
quality: QualityWrapper {
|
||||||
quality: Quality {
|
quality: Quality {
|
||||||
name: "SD - 720p".to_owned(),
|
name: "SD - 720p".to_owned(),
|
||||||
@@ -639,10 +651,10 @@ mod tests {
|
|||||||
BlocklistItem {
|
BlocklistItem {
|
||||||
id: 1,
|
id: 1,
|
||||||
source_title: "test 3".to_owned(),
|
source_title: "test 3".to_owned(),
|
||||||
languages: vec![Language {
|
languages: vec![Some(Language {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "english".to_owned(),
|
name: "english".to_owned(),
|
||||||
}],
|
})],
|
||||||
quality: QualityWrapper {
|
quality: QualityWrapper {
|
||||||
quality: Quality {
|
quality: Quality {
|
||||||
name: "HD - 1080p".to_owned(),
|
name: "HD - 1080p".to_owned(),
|
||||||
|
|||||||
@@ -210,13 +210,25 @@ fn blocklist_sorting_options() -> Vec<SortOption<BlocklistItem>> {
|
|||||||
let a_languages = a
|
let a_languages = a
|
||||||
.languages
|
.languages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|lang| lang.name.to_lowercase())
|
.map(|lang| {
|
||||||
|
lang
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Default::default())
|
||||||
|
.name
|
||||||
|
.to_lowercase()
|
||||||
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
let b_languages = b
|
let b_languages = b
|
||||||
.languages
|
.languages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|lang| lang.name.to_lowercase())
|
.map(|lang| {
|
||||||
|
lang
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Default::default())
|
||||||
|
.name
|
||||||
|
.to_lowercase()
|
||||||
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
|
|||||||
@@ -245,8 +245,19 @@ mod tests {
|
|||||||
id: 1,
|
id: 1,
|
||||||
name: "_".to_owned(),
|
name: "_".to_owned(),
|
||||||
};
|
};
|
||||||
let language_a = &a.languages.first().unwrap_or(&default_language);
|
let default_language_option = Some(default_language.clone());
|
||||||
let language_b = &b.languages.first().unwrap_or(&default_language);
|
let language_a = &a
|
||||||
|
.languages
|
||||||
|
.first()
|
||||||
|
.unwrap_or(&default_language_option)
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&default_language);
|
||||||
|
let language_b = &b
|
||||||
|
.languages
|
||||||
|
.first()
|
||||||
|
.unwrap_or(&default_language_option)
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&default_language);
|
||||||
|
|
||||||
language_a.cmp(language_b)
|
language_a.cmp(language_b)
|
||||||
};
|
};
|
||||||
@@ -385,10 +396,10 @@ mod tests {
|
|||||||
id: 3,
|
id: 3,
|
||||||
source_title: "test 1".into(),
|
source_title: "test 1".into(),
|
||||||
event_type: SonarrHistoryEventType::Grabbed,
|
event_type: SonarrHistoryEventType::Grabbed,
|
||||||
languages: vec![Language {
|
languages: vec![Some(Language {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "telgu".to_owned(),
|
name: "telgu".to_owned(),
|
||||||
}],
|
})],
|
||||||
quality: QualityWrapper {
|
quality: QualityWrapper {
|
||||||
quality: Quality {
|
quality: Quality {
|
||||||
name: "HD - 1080p".to_owned(),
|
name: "HD - 1080p".to_owned(),
|
||||||
@@ -401,10 +412,10 @@ mod tests {
|
|||||||
id: 2,
|
id: 2,
|
||||||
source_title: "test 2".into(),
|
source_title: "test 2".into(),
|
||||||
event_type: SonarrHistoryEventType::DownloadFolderImported,
|
event_type: SonarrHistoryEventType::DownloadFolderImported,
|
||||||
languages: vec![Language {
|
languages: vec![Some(Language {
|
||||||
id: 3,
|
id: 3,
|
||||||
name: "chinese".to_owned(),
|
name: "chinese".to_owned(),
|
||||||
}],
|
})],
|
||||||
quality: QualityWrapper {
|
quality: QualityWrapper {
|
||||||
quality: Quality {
|
quality: Quality {
|
||||||
name: "SD - 720p".to_owned(),
|
name: "SD - 720p".to_owned(),
|
||||||
@@ -417,10 +428,10 @@ mod tests {
|
|||||||
id: 1,
|
id: 1,
|
||||||
source_title: "test 3".into(),
|
source_title: "test 3".into(),
|
||||||
event_type: SonarrHistoryEventType::EpisodeFileDeleted,
|
event_type: SonarrHistoryEventType::EpisodeFileDeleted,
|
||||||
languages: vec![Language {
|
languages: vec![Some(Language {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "english".to_owned(),
|
name: "english".to_owned(),
|
||||||
}],
|
})],
|
||||||
quality: QualityWrapper {
|
quality: QualityWrapper {
|
||||||
quality: Quality {
|
quality: Quality {
|
||||||
name: "HD - 1080p".to_owned(),
|
name: "HD - 1080p".to_owned(),
|
||||||
|
|||||||
@@ -150,8 +150,19 @@ pub(in crate::handlers::sonarr_handlers) fn history_sorting_options(
|
|||||||
id: 1,
|
id: 1,
|
||||||
name: "_".to_owned(),
|
name: "_".to_owned(),
|
||||||
};
|
};
|
||||||
let language_a = &a.languages.first().unwrap_or(&default_language);
|
let default_language_option = Some(default_language.clone());
|
||||||
let language_b = &b.languages.first().unwrap_or(&default_language);
|
let language_a = &a
|
||||||
|
.languages
|
||||||
|
.first()
|
||||||
|
.unwrap_or(&default_language_option)
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&default_language);
|
||||||
|
let language_b = &b
|
||||||
|
.languages
|
||||||
|
.first()
|
||||||
|
.unwrap_or(&default_language_option)
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&default_language);
|
||||||
|
|
||||||
language_a.cmp(language_b)
|
language_a.cmp(language_b)
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -515,12 +515,17 @@ pub(in crate::handlers::sonarr_handlers::library) fn releases_sorting_options(
|
|||||||
SortOption {
|
SortOption {
|
||||||
name: "Language",
|
name: "Language",
|
||||||
cmp_fn: Some(|a, b| {
|
cmp_fn: Some(|a, b| {
|
||||||
let default_language_vec = vec![Language {
|
let default_language = Language {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "_".to_owned(),
|
name: "_".to_owned(),
|
||||||
}];
|
};
|
||||||
let language_a = &a.languages.as_ref().unwrap_or(&default_language_vec)[0];
|
let default_language_vec = vec![Some(default_language.clone())];
|
||||||
let language_b = &b.languages.as_ref().unwrap_or(&default_language_vec)[0];
|
let language_a = &a.languages.as_ref().unwrap_or(&default_language_vec)[0]
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&default_language);
|
||||||
|
let language_b = &b.languages.as_ref().unwrap_or(&default_language_vec)[0]
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&default_language);
|
||||||
|
|
||||||
language_a.cmp(language_b)
|
language_a.cmp(language_b)
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1116,12 +1116,17 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_releases_sorting_options_language() {
|
fn test_releases_sorting_options_language() {
|
||||||
let expected_cmp_fn: fn(&SonarrRelease, &SonarrRelease) -> Ordering = |a, b| {
|
let expected_cmp_fn: fn(&SonarrRelease, &SonarrRelease) -> Ordering = |a, b| {
|
||||||
let default_language_vec = vec![Language {
|
let default_language = Language {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "_".to_owned(),
|
name: "_".to_owned(),
|
||||||
}];
|
};
|
||||||
let language_a = &a.languages.as_ref().unwrap_or(&default_language_vec)[0];
|
let default_language_vec = vec![Some(default_language.clone())];
|
||||||
let language_b = &b.languages.as_ref().unwrap_or(&default_language_vec)[0];
|
let language_a = a.languages.as_ref().unwrap_or(&default_language_vec)[0]
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&default_language);
|
||||||
|
let language_b = b.languages.as_ref().unwrap_or(&default_language_vec)[0]
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&default_language);
|
||||||
|
|
||||||
language_a.cmp(language_b)
|
language_a.cmp(language_b)
|
||||||
};
|
};
|
||||||
@@ -1160,10 +1165,10 @@ mod tests {
|
|||||||
size: 1,
|
size: 1,
|
||||||
rejected: true,
|
rejected: true,
|
||||||
seeders: Some(Number::from(1)),
|
seeders: Some(Number::from(1)),
|
||||||
languages: Some(vec![Language {
|
languages: Some(vec![Some(Language {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "Language A".to_owned(),
|
name: "Language A".to_owned(),
|
||||||
}]),
|
})]),
|
||||||
quality: QualityWrapper {
|
quality: QualityWrapper {
|
||||||
quality: Quality {
|
quality: Quality {
|
||||||
name: "Quality A".to_owned(),
|
name: "Quality A".to_owned(),
|
||||||
@@ -1179,10 +1184,10 @@ mod tests {
|
|||||||
size: 2,
|
size: 2,
|
||||||
rejected: false,
|
rejected: false,
|
||||||
seeders: Some(Number::from(2)),
|
seeders: Some(Number::from(2)),
|
||||||
languages: Some(vec![Language {
|
languages: Some(vec![Some(Language {
|
||||||
id: 2,
|
id: 2,
|
||||||
name: "Language B".to_owned(),
|
name: "Language B".to_owned(),
|
||||||
}]),
|
})]),
|
||||||
quality: QualityWrapper {
|
quality: QualityWrapper {
|
||||||
quality: Quality {
|
quality: Quality {
|
||||||
name: "Quality B".to_owned(),
|
name: "Quality B".to_owned(),
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ pub(in crate::handlers::sonarr_handlers) mod utils {
|
|||||||
path: "/nfs/tv/series/season 1/episode 1.mkv".to_owned(),
|
path: "/nfs/tv/series/season 1/episode 1.mkv".to_owned(),
|
||||||
size: 3543348019,
|
size: 3543348019,
|
||||||
quality: quality_wrapper(),
|
quality: quality_wrapper(),
|
||||||
languages: vec![language()],
|
languages: vec![Some(language())],
|
||||||
date_added: DateTime::from(DateTime::parse_from_rfc3339("2024-02-10T07:28:45Z").unwrap()),
|
date_added: DateTime::from(DateTime::parse_from_rfc3339("2024-02-10T07:28:45Z").unwrap()),
|
||||||
media_info: Some(media_info()),
|
media_info: Some(media_info()),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ pub struct BlocklistItem {
|
|||||||
pub series_title: Option<String>,
|
pub series_title: Option<String>,
|
||||||
pub episode_ids: Vec<Number>,
|
pub episode_ids: Vec<Number>,
|
||||||
pub source_title: String,
|
pub source_title: String,
|
||||||
pub languages: Vec<Language>,
|
pub languages: Vec<Option<Language>>,
|
||||||
pub quality: QualityWrapper,
|
pub quality: QualityWrapper,
|
||||||
pub date: DateTime<Utc>,
|
pub date: DateTime<Utc>,
|
||||||
pub protocol: String,
|
pub protocol: String,
|
||||||
@@ -215,7 +215,7 @@ pub struct EpisodeFile {
|
|||||||
pub path: String,
|
pub path: String,
|
||||||
#[serde(deserialize_with = "super::from_i64")]
|
#[serde(deserialize_with = "super::from_i64")]
|
||||||
pub size: i64,
|
pub size: i64,
|
||||||
pub languages: Vec<Language>,
|
pub languages: Vec<Option<Language>>,
|
||||||
pub quality: QualityWrapper,
|
pub quality: QualityWrapper,
|
||||||
pub date_added: DateTime<Utc>,
|
pub date_added: DateTime<Utc>,
|
||||||
pub media_info: Option<MediaInfo>,
|
pub media_info: Option<MediaInfo>,
|
||||||
@@ -509,7 +509,7 @@ pub struct SonarrHistoryItem {
|
|||||||
#[serde(deserialize_with = "super::from_i64")]
|
#[serde(deserialize_with = "super::from_i64")]
|
||||||
pub episode_id: i64,
|
pub episode_id: i64,
|
||||||
pub quality: QualityWrapper,
|
pub quality: QualityWrapper,
|
||||||
pub languages: Vec<Language>,
|
pub languages: Vec<Option<Language>>,
|
||||||
pub date: DateTime<Utc>,
|
pub date: DateTime<Utc>,
|
||||||
pub event_type: SonarrHistoryEventType,
|
pub event_type: SonarrHistoryEventType,
|
||||||
pub data: SonarrHistoryData,
|
pub data: SonarrHistoryData,
|
||||||
@@ -545,7 +545,7 @@ pub struct SonarrRelease {
|
|||||||
pub rejections: Option<Vec<String>>,
|
pub rejections: Option<Vec<String>>,
|
||||||
pub seeders: Option<Number>,
|
pub seeders: Option<Number>,
|
||||||
pub leechers: Option<Number>,
|
pub leechers: Option<Number>,
|
||||||
pub languages: Option<Vec<Language>>,
|
pub languages: Option<Vec<Option<Language>>>,
|
||||||
pub quality: QualityWrapper,
|
pub quality: QualityWrapper,
|
||||||
pub full_season: bool,
|
pub full_season: bool,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -297,7 +297,13 @@ impl Network<'_, '_> {
|
|||||||
Date Added: {}",
|
Date Added: {}",
|
||||||
file.relative_path,
|
file.relative_path,
|
||||||
file.path,
|
file.path,
|
||||||
file.languages.first().unwrap_or(&Language::default()).name,
|
file
|
||||||
|
.languages
|
||||||
|
.first()
|
||||||
|
.unwrap_or(&Some(Language::default()))
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Language::default())
|
||||||
|
.name,
|
||||||
file.date_added,
|
file.date_added,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ pub(in crate::network::sonarr_network) mod test_utils {
|
|||||||
series_title: None,
|
series_title: None,
|
||||||
episode_ids: vec![Number::from(1)],
|
episode_ids: vec![Number::from(1)],
|
||||||
source_title: "Test Source Title".to_owned(),
|
source_title: "Test Source Title".to_owned(),
|
||||||
languages: vec![language()],
|
languages: vec![Some(language())],
|
||||||
quality: quality_wrapper(),
|
quality: quality_wrapper(),
|
||||||
date: DateTime::from(DateTime::parse_from_rfc3339("2024-02-10T07:28:45Z").unwrap()),
|
date: DateTime::from(DateTime::parse_from_rfc3339("2024-02-10T07:28:45Z").unwrap()),
|
||||||
protocol: "usenet".to_owned(),
|
protocol: "usenet".to_owned(),
|
||||||
@@ -180,7 +180,7 @@ pub(in crate::network::sonarr_network) mod test_utils {
|
|||||||
path: "/nfs/tv/series/season 1/episode 1.mkv".to_owned(),
|
path: "/nfs/tv/series/season 1/episode 1.mkv".to_owned(),
|
||||||
size: 3543348019,
|
size: 3543348019,
|
||||||
quality: quality_wrapper(),
|
quality: quality_wrapper(),
|
||||||
languages: vec![language()],
|
languages: vec![Some(language())],
|
||||||
date_added: DateTime::from(DateTime::parse_from_rfc3339("2024-02-10T07:28:45Z").unwrap()),
|
date_added: DateTime::from(DateTime::parse_from_rfc3339("2024-02-10T07:28:45Z").unwrap()),
|
||||||
media_info: Some(media_info()),
|
media_info: Some(media_info()),
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ pub(in crate::network::sonarr_network) mod test_utils {
|
|||||||
source_title: "Test source".into(),
|
source_title: "Test source".into(),
|
||||||
episode_id: 1,
|
episode_id: 1,
|
||||||
quality: quality_wrapper(),
|
quality: quality_wrapper(),
|
||||||
languages: vec![language()],
|
languages: vec![Some(language())],
|
||||||
date: DateTime::from(DateTime::parse_from_rfc3339("2024-02-10T07:28:45Z").unwrap()),
|
date: DateTime::from(DateTime::parse_from_rfc3339("2024-02-10T07:28:45Z").unwrap()),
|
||||||
event_type: SonarrHistoryEventType::Grabbed,
|
event_type: SonarrHistoryEventType::Grabbed,
|
||||||
data: history_data(),
|
data: history_data(),
|
||||||
@@ -377,7 +377,7 @@ pub(in crate::network::sonarr_network) mod test_utils {
|
|||||||
rejections: Some(rejections()),
|
rejections: Some(rejections()),
|
||||||
seeders: Some(Number::from(2)),
|
seeders: Some(Number::from(2)),
|
||||||
leechers: Some(Number::from(1)),
|
leechers: Some(Number::from(1)),
|
||||||
languages: Some(vec![language()]),
|
languages: Some(vec![Some(language())]),
|
||||||
quality: quality_wrapper(),
|
quality: quality_wrapper(),
|
||||||
full_season: false,
|
full_season: false,
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -121,7 +121,7 @@ fn draw_error(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
app.error.scroll_left_or_reset(
|
app.error.scroll_left_or_reset(
|
||||||
area.width as usize,
|
area.width as usize,
|
||||||
true,
|
true,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
|
|
||||||
let paragraph = Paragraph::new(Text::from(app.error.to_string().failure()))
|
let paragraph = Paragraph::new(Text::from(app.error.to_string().failure()))
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ fn draw_blocklist_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
movie.title.scroll_left_or_reset(
|
movie.title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 20),
|
get_width_from_percentage(area, 20),
|
||||||
current_selection == *blocklist_item,
|
current_selection == *blocklist_item,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
|
|
||||||
let languages_string = languages
|
let languages_string = languages
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ pub fn draw_collection_details(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect)
|
|||||||
movie.title.scroll_left_or_reset(
|
movie.title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(table_area, 20),
|
get_width_from_percentage(table_area, 20),
|
||||||
current_selection == *movie,
|
current_selection == *movie,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
let (hours, minutes) = convert_runtime(movie.runtime);
|
let (hours, minutes) = convert_runtime(movie.runtime);
|
||||||
let imdb_rating = movie
|
let imdb_rating = movie
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ pub(super) fn draw_collections(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect)
|
|||||||
collection.title.scroll_left_or_reset(
|
collection.title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 25),
|
get_width_from_percentage(area, 25),
|
||||||
*collection == current_selection,
|
*collection == current_selection,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
let monitored = if collection.monitored { "🏷" } else { "" };
|
let monitored = if collection.monitored { "🏷" } else { "" };
|
||||||
let search_on_add = if collection.search_on_add {
|
let search_on_add = if collection.search_on_add {
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ fn draw_downloads(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
output_path.as_ref().unwrap().scroll_left_or_reset(
|
output_path.as_ref().unwrap().scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 18),
|
get_width_from_percentage(area, 18),
|
||||||
current_selection == *download_record,
|
current_selection == *download_record,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ fn draw_test_all_indexers_test_results(f: &mut Frame<'_>, app: &mut App<'_>, are
|
|||||||
result.validation_failures.scroll_left_or_reset(
|
result.validation_failures.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 86),
|
get_width_from_percentage(area, 86),
|
||||||
*result == current_selection,
|
*result == current_selection,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
let pass_fail = if result.is_valid { "✔" } else { "❌" };
|
let pass_fail = if result.is_valid { "✔" } else { "❌" };
|
||||||
let row = Row::new(vec![
|
let row = Row::new(vec![
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ fn draw_add_movie_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
movie.title.scroll_left_or_reset(
|
movie.title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 27),
|
get_width_from_percentage(area, 27),
|
||||||
*movie == current_selection,
|
*movie == current_selection,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
|
|
||||||
Row::new(vec![
|
Row::new(vec![
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ fn draw_library(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
movie.title.scroll_left_or_reset(
|
movie.title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 27),
|
get_width_from_percentage(area, 27),
|
||||||
*movie == current_selection,
|
*movie == current_selection,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
let monitored = if movie.monitored { "🏷" } else { "" };
|
let monitored = if movie.monitored { "🏷" } else { "" };
|
||||||
let studio = movie.studio.clone().unwrap_or_default();
|
let studio = movie.studio.clone().unwrap_or_default();
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ fn draw_movie_history(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
movie_history_item.source_title.scroll_left_or_reset(
|
movie_history_item.source_title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 34),
|
get_width_from_percentage(area, 34),
|
||||||
current_selection == *movie_history_item,
|
current_selection == *movie_history_item,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
|
|
||||||
Row::new(vec![
|
Row::new(vec![
|
||||||
@@ -393,7 +393,7 @@ fn draw_movie_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
get_width_from_percentage(area, 30),
|
get_width_from_percentage(area, 30),
|
||||||
current_selection == *release
|
current_selection == *release
|
||||||
&& current_route != ActiveRadarrBlock::ManualSearchConfirmPrompt.into(),
|
&& current_route != ActiveRadarrBlock::ManualSearchConfirmPrompt.into(),
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
let size = convert_to_gb(*size);
|
let size = convert_to_gb(*size);
|
||||||
let rejected_str = if *rejected { "⛔" } else { "" };
|
let rejected_str = if *rejected { "⛔" } else { "" };
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ fn draw_blocklist_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
let title = series_title.as_ref().unwrap_or(&String::new()).to_owned();
|
let title = series_title.as_ref().unwrap_or(&String::new()).to_owned();
|
||||||
let languages_string = languages
|
let languages_string = languages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|lang| lang.name.to_owned())
|
.map(|lang| lang.as_ref().unwrap_or(&Default::default()).name.to_owned())
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ fn draw_downloads(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
output_path.as_ref().unwrap().scroll_left_or_reset(
|
output_path.as_ref().unwrap().scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 18),
|
get_width_from_percentage(area, 18),
|
||||||
current_selection == *download_record,
|
current_selection == *download_record,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, HISTORY_BLOCKS};
|
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, HISTORY_BLOCKS};
|
||||||
|
use crate::models::servarr_models::Language;
|
||||||
use crate::models::sonarr_models::{SonarrHistoryEventType, SonarrHistoryItem};
|
use crate::models::sonarr_models::{SonarrHistoryEventType, SonarrHistoryItem};
|
||||||
use crate::models::Route;
|
use crate::models::Route;
|
||||||
use crate::ui::styles::ManagarrStyle;
|
use crate::ui::styles::ManagarrStyle;
|
||||||
@@ -68,7 +69,7 @@ fn draw_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
source_title.scroll_left_or_reset(
|
source_title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 40),
|
get_width_from_percentage(area, 40),
|
||||||
current_selection == *history_item,
|
current_selection == *history_item,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
|
|
||||||
Row::new(vec![
|
Row::new(vec![
|
||||||
@@ -77,7 +78,13 @@ fn draw_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
Cell::from(
|
Cell::from(
|
||||||
languages
|
languages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|language| language.name.to_owned())
|
.map(|language| {
|
||||||
|
language
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Language::default())
|
||||||
|
.name
|
||||||
|
.to_owned()
|
||||||
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(","),
|
.join(","),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ fn draw_test_all_indexers_test_results(f: &mut Frame<'_>, app: &mut App<'_>, are
|
|||||||
result.validation_failures.scroll_left_or_reset(
|
result.validation_failures.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 86),
|
get_width_from_percentage(area, 86),
|
||||||
*result == current_selection,
|
*result == current_selection,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
let pass_fail = if result.is_valid { "✔" } else { "❌" };
|
let pass_fail = if result.is_valid { "✔" } else { "❌" };
|
||||||
let row = Row::new(vec![
|
let row = Row::new(vec![
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ fn draw_add_series_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
series.title.scroll_left_or_reset(
|
series.title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 27),
|
get_width_from_percentage(area, 27),
|
||||||
*series == current_selection,
|
*series == current_selection,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
|
|
||||||
Row::new(vec![
|
Row::new(vec![
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EPISODE_DETAILS_BLOCKS};
|
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EPISODE_DETAILS_BLOCKS};
|
||||||
|
use crate::models::servarr_models::Language;
|
||||||
use crate::models::sonarr_models::{
|
use crate::models::sonarr_models::{
|
||||||
DownloadRecord, DownloadStatus, Episode, SonarrHistoryEventType, SonarrHistoryItem, SonarrRelease,
|
DownloadRecord, DownloadStatus, Episode, SonarrHistoryEventType, SonarrHistoryItem, SonarrRelease,
|
||||||
};
|
};
|
||||||
@@ -271,7 +272,7 @@ fn draw_episode_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect)
|
|||||||
source_title.scroll_left_or_reset(
|
source_title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 40),
|
get_width_from_percentage(area, 40),
|
||||||
current_selection == *history_item,
|
current_selection == *history_item,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
|
|
||||||
Row::new(vec![
|
Row::new(vec![
|
||||||
@@ -280,7 +281,13 @@ fn draw_episode_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect)
|
|||||||
Cell::from(
|
Cell::from(
|
||||||
languages
|
languages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|language| language.name.to_owned())
|
.map(|language| {
|
||||||
|
language
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Language::default())
|
||||||
|
.name
|
||||||
|
.to_owned()
|
||||||
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(","),
|
.join(","),
|
||||||
),
|
),
|
||||||
@@ -415,7 +422,7 @@ fn draw_episode_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
get_width_from_percentage(area, 30),
|
get_width_from_percentage(area, 30),
|
||||||
current_selection == *release
|
current_selection == *release
|
||||||
&& active_sonarr_block != ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt,
|
&& active_sonarr_block != ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
let size = convert_to_gb(*size);
|
let size = convert_to_gb(*size);
|
||||||
let rejected_str = if *rejected { "⛔" } else { "" };
|
let rejected_str = if *rejected { "⛔" } else { "" };
|
||||||
@@ -441,7 +448,11 @@ fn draw_episode_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let language = if languages.is_some() {
|
let language = if languages.is_some() {
|
||||||
languages.clone().unwrap()[0].name.clone()
|
languages.clone().unwrap()[0]
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Default::default())
|
||||||
|
.name
|
||||||
|
.clone()
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ fn draw_library(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
series.title.scroll_left_or_reset(
|
series.title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 23),
|
get_width_from_percentage(area, 23),
|
||||||
*series == current_selection,
|
*series == current_selection,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
let monitored = if series.monitored { "🏷" } else { "" };
|
let monitored = if series.monitored { "🏷" } else { "" };
|
||||||
let certification = series.certification.clone().unwrap_or_default();
|
let certification = series.certification.clone().unwrap_or_default();
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ fn draw_season_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
source_title.scroll_left_or_reset(
|
source_title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 40),
|
get_width_from_percentage(area, 40),
|
||||||
current_selection == *history_item,
|
current_selection == *history_item,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
|
|
||||||
Row::new(vec![
|
Row::new(vec![
|
||||||
@@ -276,7 +276,13 @@ fn draw_season_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
Cell::from(
|
Cell::from(
|
||||||
languages
|
languages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|language| language.name.to_owned())
|
.map(|language| {
|
||||||
|
language
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Default::default())
|
||||||
|
.name
|
||||||
|
.to_owned()
|
||||||
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(","),
|
.join(","),
|
||||||
),
|
),
|
||||||
@@ -372,7 +378,7 @@ fn draw_season_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
get_width_from_percentage(area, 30),
|
get_width_from_percentage(area, 30),
|
||||||
current_selection == *release
|
current_selection == *release
|
||||||
&& active_sonarr_block != ActiveSonarrBlock::ManualSeasonSearchConfirmPrompt,
|
&& active_sonarr_block != ActiveSonarrBlock::ManualSeasonSearchConfirmPrompt,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
let size = convert_to_gb(*size);
|
let size = convert_to_gb(*size);
|
||||||
let rejected_str = if *rejected { "⛔" } else { "" };
|
let rejected_str = if *rejected { "⛔" } else { "" };
|
||||||
@@ -398,7 +404,11 @@ fn draw_season_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let language = if languages.is_some() {
|
let language = if languages.is_some() {
|
||||||
languages.clone().unwrap()[0].name.clone()
|
languages.clone().unwrap()[0]
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Default::default())
|
||||||
|
.name
|
||||||
|
.clone()
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ fn draw_series_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
source_title.scroll_left_or_reset(
|
source_title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 40),
|
get_width_from_percentage(area, 40),
|
||||||
current_selection == *history_item,
|
current_selection == *history_item,
|
||||||
app.tick_count % app.ticks_until_scroll == 0,
|
app.tick_count.is_multiple_of(app.ticks_until_scroll),
|
||||||
);
|
);
|
||||||
|
|
||||||
Row::new(vec![
|
Row::new(vec![
|
||||||
@@ -324,7 +324,13 @@ fn draw_series_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
Cell::from(
|
Cell::from(
|
||||||
languages
|
languages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|language| language.name.to_owned())
|
.map(|language| {
|
||||||
|
language
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Default::default())
|
||||||
|
.name
|
||||||
|
.to_owned()
|
||||||
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(","),
|
.join(","),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user