Skip to content

Commit

Permalink
Archive manager (Astrabit-ST#80)
Browse files Browse the repository at this point in the history
* feat: start creating the UI for the archive manager

* refactor(filesystem): add `luminol_core::spawn_future` for cross-platform spawning

* chore(filesystem): fix redundant closures

* refactor(project manager): move `frame` into `update_state`

* refactor(filesystem): don't store in IndexedDB unless requested

In web builds, we usually don't need to store folder handles in
IndexedDB, so the old system of storing folder handles in IndexedDB by
default and deleting them from IndexedDB if requested was clunky.

This changes it so that folder handles are not stored by default. You
need to call `.save_to_idb()` to save it and get the key to restore it.

* feat(archive manager): start implementing a filesystem view

* fix(archive manager): fix archive contents not displaying correctly

* fix(archive manager): fix some UI oddities

* fix(archive manager): don't persist collapsing header state

We don't want the state of the collapsing headers in the filesystem view
to be saved because we may be opening a different archive with the same
name, or we may be opening a modified version of the same archive. That
would lead to some errors when opening the view.

* fix(archive manager): depersist the inner subtrees as well

* style(archive manager): future proofing and use generic IDs

This changes the filesystem view to use the indextree node IDs to
generate the egui IDs for the collapsing headers instead of using the
file paths to generate the egui IDs. This is so that we leave less junk
objects in the memory if the user opens a lot of different archives with
different names.

Also, the response tuple for the collapsing headers is now read using
pattern matching instead of by just indexing into the tuple, which makes
it easier to debug errors if egui decides to change the format of the
response tuple.

* fix(archive manager): don't load folder contents until partly open

* feat(archive manager): implement filesystem view file/folder selection

* perf(archive manager): store `depersisted` in nodes, not hashset

I may be stupid.

* feat(archive manager): add stripes to filesystem view rows

* feat(archive manager): implement `SelectedIter`

This iterator allows iterating over the selected entries of a
`FileSystemView` from top to bottom.

* perf(filesystem): `create_dir` now creates missing parents

This prevents us from having to check if a directory exists before
creating it as well as simplifying the web filesystem implementation and
making the `create_dir` function more consistent with `remove_dir`.

* feat(archive manager): implement archive extraction

* perf(archive manager): don't recurse into deselected dirs

* feat(filesystem): implement file picker for saving files

* refactor(filesystem): implement `File` for `&mut impl File`

* refactor(filesystem): use builder pattern to save files

* refactor(filesystem): make saving files less of a hassle

* fix: archiver filesystem `create_dir` is now recursive

I changed all of the other filesystems' `create_dir` implementations to
be recursive, so this one needs to be recursive as well.

* fix(filesystem): fix archiver not being able to create files

* fix(filesystem): fix edge cases in trie.rs

* fix(filesystem): fix archiver file creation using wrong magic value

* feat(archive manager): implement archive creation

* fix(filesystem): fix more edge cases in `get_dir_prefix`

It would appear I need to do more fuzz testing.

* fix(filesystem): fix magic calculation for RGSS3A archives

* perf: improve archive creation speed

The secret sauce is to buffer writes and not flush the archive until
after all files have been written.

* fix(filesystem): fix trie.rs directory merge algorithm

This is the last edge case, I promise!

* feat(archive manager): use better sorting in filesystem view

* fix(archive manager): disable the UI when file/folder picker is active

* fix(archive manager): use correct file extension when creating archives

* fix(archive manager): use better error handling

* feat(archive manager): implement Control and Shift for filesystem view

You can now use the Control and Shift keys like how they normally work
in file managers.

* perf(archive manager): remove redundant stack from previous commit

* feat(archive manager): shift-selection now deselects if pivot is deselected

* feat(archive manager): select "Data" and "Graphics" when creating archives

* feat(archive manager): load from current project by default

* chore: clippy

* fix(archive manager): `is_root` should be set to false for inner calls

* fix(filesystem): fix archiver path separator bug on Windows

* fix(filesystem): fix `FileSystemTrieDirIter` `ExactSizeIterator` implementation

* fix(filesystem): fix trie.rs `create_dir` edge case

I lied. THIS is the last edge case, for real this time!

This fixes a bug where the trie registers the root directory as a child
of itself if the user calls `create_dir` on the trie with any path and
then calls `create_dir` on the trie a second time with the empty path.

* feat(filesystem): implement asynchronous IO for host files

Host files now implement `AsyncRead + AsyncWrite + AsyncSeek + Unpin` so
that we can perform IO asynchronously.

Native files do this by spawning a thread and performing IO there (using
the `async-fs` crate).

Web files do this by just asynchronously waiting for command responses
instead of blocking.

* feat(archive manager): archives are now created asynchronously

* fix(filesystem): web file futures now clear on error

* feat(archive manager): archives are now extracted asynchronously

* feat(archive manager): add progress bars for extraction and creation

* fix(filesystem): fix trie.rs `remove_dir` not removing entry from parent dir

* style(filesystem): remove unnecessary `vec!` from `read_file_xor_async`

* style(filesystem): `get_mut_file` -> `get_file_mut`

* fix: fix app being drawn every frame on native

* fix(archive manager): request repaint when progress bar updates

* style(filesystem): remove poll-promise from filesystem dependencies

* style(filesystem): fix formatting of imports in archiver/filesystem.rs

* feat(archive manager): add tooltip explaining how to select files/folders

* style(filesystem): fix formatting in archiver/filesystem.rs again
  • Loading branch information
white-axe authored Dec 25, 2023
1 parent a7cd8c4 commit 83de3eb
Show file tree
Hide file tree
Showing 27 changed files with 2,494 additions and 251 deletions.
170 changes: 166 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,16 @@ crossbeam = "0.8.2"
dashmap = "5.5.3"
flume = "0.11.0"
oneshot = "0.1.6"
futures-lite = "2.1.0"
async-std = "1.12.0"
pin-project = "1"

poll-promise = { version = "0.3.0" }

camino = "1.1.6"

slab = { version = "0.4.9", features = ["serde"] }
qp-trie = "0.8.2"

itertools = "0.11.0"

Expand Down
10 changes: 7 additions & 3 deletions crates/audio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,18 @@ impl Default for Audio {

impl Audio {
/// Play a sound on a source.
pub fn play(
pub fn play<T>(
&self,
path: impl AsRef<camino::Utf8Path>,
filesystem: &impl luminol_filesystem::FileSystem, // FIXME
filesystem: &T,
volume: u8,
pitch: u8,
source: Source,
) -> Result<()> {
) -> Result<()>
where
T: luminol_filesystem::FileSystem,
T::File: 'static,
{
let path = path.as_ref();
let file = filesystem.open_file(path, luminol_filesystem::OpenFlags::Read)?;

Expand Down
4 changes: 4 additions & 0 deletions crates/components/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,9 @@ serde.workspace = true

once_cell.workspace = true
slab.workspace = true
qp-trie.workspace = true

anyhow.workspace = true

indextree = "4.6.0"
lexical-sort = "0.3.1"
Loading

0 comments on commit 83de3eb

Please sign in to comment.