Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loop to selection list when pressing q while playing #23

Merged
merged 5 commits into from
Aug 12, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ The license is GPLv2
Don't be surprised if these are not implemented in the end hehe (if there is no interest in the project, certainly not)

- [x] ~Audio (mpv) controls when not in verbose mode~
- [ ] Loop to selection list when pressing `q` while playing
- [x] Loop to selection list when pressing `q` while playing
- [x] ~Some kind of online updating of the list of stations~ _(kind of)_
- [x] ~Code optimizations/beautification~
- [x] ~Search international online radios~
Expand Down
59 changes: 35 additions & 24 deletions src/lib/browser.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use std::error::Error;
use std::rc::Rc;

use crate::{station::Station, Config};
use inquire::{error::InquireError, Autocomplete, Text};
use radiobrowser::{blocking::RadioBrowserAPI, ApiCountry, ApiStation, StationOrder};

pub type StationCache = Rc<Vec<ApiStation>>;

#[derive(Debug, Clone)]
pub struct Stations {
stations: Vec<ApiStation>,
stations: StationCache,
}

impl Autocomplete for Stations {
Expand Down Expand Up @@ -39,39 +42,47 @@ impl Autocomplete for Stations {

pub struct Browser {
api: RadioBrowserAPI,
config: Config,
stations: Vec<ApiStation>,
config: Rc<Config>,
stations: StationCache,
}

impl Browser {
pub fn new(config: Config) -> Result<Browser, Box<dyn Error>> {
pub fn new(
config: Rc<Config>,
cached_stations: Option<StationCache>,
) -> Result<(Browser, StationCache), Box<dyn Error>> {
let api = match RadioBrowserAPI::new() {
Ok(r) => r,
Err(e) => return Err(e),
};

let stations = if let Some(code) = &config.country_code {
match api
.get_stations()
.countrycode(code)
.order(StationOrder::Clickcount)
.send()
{
Ok(s) => s,
Err(_e) => Vec::new(),
}
} else {
match api.get_stations().order(StationOrder::Clickcount).send() {
Ok(s) => s,
Err(_e) => Vec::new(),
}
};
let stations = cached_stations.unwrap_or_else(|| {
Rc::new(if let Some(code) = &config.country_code {
match api
.get_stations()
.countrycode(code)
.order(StationOrder::Clickcount)
.send()
{
Ok(s) => s,
Err(_e) => Vec::new(),
}
} else {
match api.get_stations().order(StationOrder::Clickcount).send() {
Ok(s) => s,
Err(_e) => Vec::new(),
}
})
});

Ok(Browser {
api,
config,
Ok((
Browser {
api,
config,
stations: stations.clone(),
},
stations,
})
))
}

pub fn get_countries() -> Result<Vec<ApiCountry>, Box<dyn Error>> {
Expand Down
7 changes: 7 additions & 0 deletions src/lib/cli_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ pub struct Cli {
)]
pub list_countries: bool,

/// Flag: --no-station-cache: Don't cache the station list loaded from the internet.
#[clap(
long = "no-station-cache",
help = "Don't cache the station list loaded from the internet."
)]
pub no_station_cache: bool,

/// Show extra info
#[clap(flatten)]
pub verbose: clap_verbosity_flag::Verbosity,
Expand Down
44 changes: 1 addition & 43 deletions src/lib/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,13 @@ use crate::station::Station;
use crate::version::Version;

use colored::*;
use inquire::{error::InquireError, Select};
use serde::de::{Deserializer, Error as SeError, Visitor};
use serde::Deserialize;
use std::fmt::{Formatter, Result as ResultFmt};
use std::fs::File;
use std::io::{Read, Write};
use std::path::PathBuf;

use crate::browser::Browser;

const _CONFIG_URL: &str = "https://raw.githubusercontent.com/margual56/radio-cli/main/config.json";

#[derive(Deserialize, Debug, Clone)]
Expand Down Expand Up @@ -134,7 +131,7 @@ impl Config {
}
}

pub fn get_url_for(self, station_name: &str) -> Option<String> {
pub fn get_url_for(&self, station_name: &str) -> Option<String> {
for s in self.data.iter() {
if s.station.eq(station_name) {
return Some(s.url.clone());
Expand All @@ -153,45 +150,6 @@ impl Config {

stations
}

/// Prompts the user to select a station.
/// Returns a station and if the station was taken from the internet.
pub fn prompt(self) -> Result<(Station, bool), InquireError> {
let max_lines: usize = match self.max_lines {
Some(x) => x,
None => Select::<Station>::DEFAULT_PAGE_SIZE,
};

let res = Select::new(&"Select a station to play:".bold(), self.data.clone())
.with_page_size(max_lines)
.prompt();

let internet: bool;
let station: Station = match res {
Ok(s) => {
if s.station.eq("Other") {
internet = true;
let result = Browser::new(self);

let brow = match result {
Ok(b) => b,
Err(_e) => return Err(InquireError::OperationInterrupted),
};

match brow.prompt() {
Ok(r) => r,
Err(e) => return Err(e),
}
} else {
internet = false;
s
}
}
Err(e) => return Err(e),
};

Ok((station, internet))
}
}

fn deserialize_version<'de, D>(deserializer: D) -> Result<Version, D::Error>
Expand Down
Loading
Loading