diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f6e67bca..b9c926bf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,7 +34,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-20.04, windows-2019, macOS-latest, ubuntu-latest] + os: [ubuntu-20.04, windows-2019] rust: [stable] steps: - uses: actions/checkout@v2 diff --git a/Cargo.lock b/Cargo.lock index ff4dab1b..654e78e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3201,7 +3201,7 @@ dependencies = [ [[package]] name = "oculante" -version = "0.6.68-dev2" +version = "0.6.68-dev3" dependencies = [ "anyhow", "arboard", diff --git a/Cargo.toml b/Cargo.toml index d8df0e2e..c799e550 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" name = "oculante" readme = "README.md" repository = "https://github.com/woelper/oculante/" -version = "0.6.68-dev2" +version = "0.6.68-dev3" [package.metadata.bundle] icon = ["res/oculante.png"] diff --git a/PKGBUILD b/PKGBUILD index 3d10ecd7..c4d997f4 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Johann Woelper pkgname=oculante -pkgver=0.6.68-dev2 +pkgver=0.6.68-dev3 pkgrel=1 depends=('aom' 'libwebp' 'expat' 'freetype2' 'gtk3' 'cairo') makedepends=('rust' 'cargo' 'tar' 'nasm' 'cmake') diff --git a/src/main.rs b/src/main.rs index b9cbb0b2..44b2eeeb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -665,7 +665,7 @@ fn drawe(app: &mut App, gfx: &mut Graphics, plugins: &mut Plugins, state: &mut O // fill image sequence if state.folder_selected.is_none() { if let Some(p) = &state.current_path { - state.scrubber = scrubber::Scrubber::new(p, None, false, false); + state.scrubber = scrubber::Scrubber::new(p, None, false, false, None); state.scrubber.wrap = state.persistent_settings.wrap_folder; // debug!("{:#?} from {}", &state.scrubber, p.display()); @@ -1080,6 +1080,7 @@ fn browse_for_folder_path(state: &mut OculanteState) { Some(FAVOURITES_FILE), true, true, + Some(3), ); let current_path = state.scrubber.next(); diff --git a/src/scrubber.rs b/src/scrubber.rs index 04d43b5d..259a57bf 100644 --- a/src/scrubber.rs +++ b/src/scrubber.rs @@ -15,8 +15,20 @@ pub struct Scrubber { } impl Scrubber { - pub fn new(path: &Path, favourites_file: Option<&str>, randomize: bool, walk_files: bool) -> Self { - let entries = get_image_filenames_for_directory(path, favourites_file, randomize, walk_files) + pub fn new( + path: &Path, + favourites_file: Option<&str>, + randomize: bool, + walk_files: bool, + intersperse_with_favs_every_n: Option, + ) -> Self { + let entries = get_image_filenames_for_directory( + path, + favourites_file, + randomize, + walk_files, + intersperse_with_favs_every_n, + ) .unwrap_or_default(); let index = entries.iter().position(|p| p == path).unwrap_or_default(); Self { @@ -66,7 +78,13 @@ impl Scrubber { // Get sorted list of files in a folder // TODO: Should probably return an Result instead, but am too lazy to figure out + handle a dedicated error type here // TODO: Cache this result, instead of doing it each time we need to fetch another file from the folder -pub fn get_image_filenames_for_directory(folder_path: &Path, favourites_file: Option<&str>, randomize: bool, walk_files: bool) -> Result> { +pub fn get_image_filenames_for_directory( + folder_path: &Path, + favourites_file: Option<&str>, + randomize: bool, + walk_files: bool, + intersperse_with_favs_every_n: Option, +) -> Result> { let mut folder_path = folder_path.to_path_buf(); if folder_path.is_file() { folder_path = folder_path @@ -75,14 +93,14 @@ pub fn get_image_filenames_for_directory(folder_path: &Path, favourites_file: Op .context("Can't get parent")?; } - let mut _favourites: HashSet = Default::default(); + let mut favourites: HashSet = Default::default(); if let Some(favourites_file) = favourites_file { let favourites_path = folder_path.join(Path::new(favourites_file)); if favourites_path.exists() { let file = std::fs::File::open(favourites_path)?; let reader = BufReader::new(file); - _favourites = reader + favourites = reader .lines() .filter_map(|line| line.ok()) .map(|file_str| folder_path.join(join_path_parts(file_str))) @@ -97,8 +115,8 @@ pub fn get_image_filenames_for_directory(folder_path: &Path, favourites_file: Op dir_files = WalkDir::new(folder_path) .into_iter() .filter_map(|v| v.ok()) - .filter(|x| is_ext_compatible(x.path())) - .map(|x| x.into_path()) + .map(|entry| entry.into_path()) + .filter(|x| is_ext_compatible(x)) .collect::>(); } else { let info = std::fs::read_dir(folder_path)?; @@ -109,13 +127,14 @@ pub fn get_image_filenames_for_directory(folder_path: &Path, favourites_file: Op .collect::>(); } - debug!("number of files: {}", dir_files.len()); - // TODO: Are symlinks handled correctly? + let mut favourites: Vec = favourites.into_iter().collect(); + if randomize { let mut rng = rand::thread_rng(); dir_files.shuffle(&mut rng); + favourites.shuffle(&mut rng); } else { dir_files.sort_unstable_by(|a, b| { lexical_sort::natural_lexical_cmp( @@ -129,6 +148,10 @@ pub fn get_image_filenames_for_directory(folder_path: &Path, favourites_file: Op }); } + if let Some(every_n) = intersperse_with_favs_every_n { + dir_files = insert_after_every(dir_files, favourites, every_n); + } + debug!("number of files: {}", dir_files.len()); return Ok(dir_files); } @@ -138,7 +161,14 @@ pub fn find_first_image_in_directory(folder_path: &PathBuf) -> Result { if !folder_path.is_dir() { bail!("This is not a folder"); }; - get_image_filenames_for_directory(folder_path, None, false, false).map(|x| { + get_image_filenames_for_directory( + folder_path, + None, + false, + false, + None, + ) + .map(|x| { x.first() .cloned() .context("Folder does not have any supported images in it") @@ -154,3 +184,28 @@ fn join_path_parts(path_with_tabs: String) -> PathBuf { path } + +fn insert_after_every(main_vector: Vec, other_vector: Vec, after: usize) -> Vec { + let mut result = Vec::with_capacity(main_vector.len() + other_vector.len()); + let mut other_vector_i = 0; + let other_vector_set: HashSet = other_vector.clone().into_iter().collect(); + + for (i, element) in main_vector.into_iter().enumerate() { + if other_vector_set.contains(&element) { + continue + } + + result.push(element); + if other_vector_i < other_vector.len() && (i + 1) % after == 0 { + result.push(other_vector[other_vector_i].clone()); + other_vector_i += 1; + } + } + + while other_vector_i < other_vector.len() { + result.push(other_vector[other_vector_i].clone()); + other_vector_i += 1; + } + + result +}