refactor: state

This commit is contained in:
Gabor Körber 2023-10-27 13:13:22 +02:00
parent cb0272b790
commit fa22be6e0e
6 changed files with 64 additions and 32 deletions

11
Justfile Normal file
View File

@ -0,0 +1,11 @@
default:
@just hello
run:
@cargo run main
bin args='':
@cargo run --bin {{args}}
hello:
@echo "Hello, world!"

View File

@ -1,2 +1,3 @@
pub mod soundclips; pub mod soundclips;
pub mod state;
pub mod vbplay; pub mod vbplay;

View File

@ -1,7 +1,8 @@
use axum::extract::{FromRef, State}; use axum::extract::State;
use axum::{routing, Router}; use axum::{routing, Router};
use axum_template::{engine::Engine, Key, RenderHtml}; use axum_template::{engine::Engine, Key, RenderHtml};
use minijinja::{path_loader, Environment}; use minijinja::{path_loader, Environment};
use state::{AppState, TemplateEngine};
use std::net::SocketAddr; use std::net::SocketAddr;
use serde::Serialize; use serde::Serialize;
@ -10,23 +11,9 @@ use std::sync::{Arc, Mutex};
use vbplay::AudioThread; use vbplay::AudioThread;
mod soundclips; mod soundclips;
mod state;
mod vbplay; mod vbplay;
type AppEngine = Engine<Environment<'static>>;
#[derive(Clone)]
pub struct AppState {
pub engine: AppEngine,
pub clips: Vec<soundclips::SoundClip>,
pub player: Arc<Mutex<AudioThread>>,
}
impl FromRef<AppState> for AppEngine {
fn from_ref(state: &AppState) -> Self {
state.engine.clone()
}
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let mut jinja = Environment::new(); let mut jinja = Environment::new();
@ -36,7 +23,7 @@ async fn main() {
let audio = vbplay::audio_thread(); let audio = vbplay::audio_thread();
let audio: Arc<Mutex<AudioThread>> = Arc::new(Mutex::new(audio)); let audio: Arc<Mutex<AudioThread>> = Arc::new(Mutex::new(audio));
let state = AppState { let app_state = AppState {
engine: template_engine, engine: template_engine,
clips: soundclips::scan_directory_for_clips("E:/sounds/soundboard", &["mp3"]) clips: soundclips::scan_directory_for_clips("E:/sounds/soundboard", &["mp3"])
.expect("No Soundclips found."), .expect("No Soundclips found."),
@ -51,7 +38,7 @@ async fn main() {
.route("/", routing::get(home)) .route("/", routing::get(home))
.route("/play/:hash", routing::get(play_handler)) .route("/play/:hash", routing::get(play_handler))
.route("/stop", routing::get(stop_handler)) .route("/stop", routing::get(stop_handler))
.with_state(state); .with_state(app_state);
println!("listening on {}", addr); println!("listening on {}", addr);
@ -67,7 +54,7 @@ struct TemplateContext {
clips: Vec<soundclips::SoundClip>, clips: Vec<soundclips::SoundClip>,
} }
async fn home(engine: AppEngine, state: State<AppState>) -> impl axum::response::IntoResponse { async fn home(engine: TemplateEngine, state: State<AppState>) -> impl axum::response::IntoResponse {
let clips = state.0.clone().clips; // this is not ideal. let clips = state.0.clone().clips; // this is not ideal.
let context = TemplateContext { clips: clips }; let context = TemplateContext { clips: clips };
RenderHtml(Key("index.html".to_owned()), engine, context) RenderHtml(Key("index.html".to_owned()), engine, context)

View File

@ -58,15 +58,17 @@ pub fn scan_directory_for_clips(directory: &str, extensions: &[&str]) -> Option<
if path.is_file() { if path.is_file() {
if let Some(ext) = path.extension() { if let Some(ext) = path.extension() {
if extensions.iter().any(|&e| ext == OsStr::new(e)) { if extensions.iter().any(|&e| ext == OsStr::new(e)) {
let file_name = path.file_name().unwrap().to_str().unwrap().to_string(); if let Some(file_name) = path.file_name().unwrap().to_str() {
/* /*
the calls to unwrap() are more or less "safe" because: the calls to unwrap() are more or less "safe" because:
file_name() only returns None if the path ends in "..", which won't be the case for paths returned by read_dir. file_name() only returns None if the path ends in "..", which won't be the case for paths returned by read_dir.
to_str() only returns None if the file name isn't valid Unicode, which is quite rare on most modern file systems. to_str() only returns None if the file name isn't valid Unicode, which is quite rare on most modern file systems.
*/ */
let sound_clip = SoundClip::new(file_name, directory.to_owned()); let sound_clip =
sound_clips.push(sound_clip); SoundClip::new(file_name.to_string(), directory.to_owned());
sound_clips.push(sound_clip);
}
} }
} }
} }

21
src/state.rs Normal file
View File

@ -0,0 +1,21 @@
use crate::soundclips::SoundClip;
use crate::vbplay::AudioThread;
use axum::extract::FromRef;
use axum_template::engine::Engine;
use minijinja::Environment;
use std::sync::{Arc, Mutex};
pub type TemplateEngine = Engine<Environment<'static>>;
#[derive(Clone)]
pub struct AppState {
pub engine: TemplateEngine,
pub clips: Vec<SoundClip>,
pub player: Arc<Mutex<AudioThread>>,
}
impl FromRef<AppState> for TemplateEngine {
fn from_ref(state: &AppState) -> Self {
state.engine.clone()
}
}

View File

@ -13,10 +13,20 @@
</script> </script>
</head> </head>
<body> <body>
{% for clip in clips %} <div class="container">
<button onclick="play('{{clip.hash}}')">{{clip.file_name}}</button><br /> <div class="categories">
{% endfor %} <span class="category">Category 1</span>
<!-- More categories -->
<button onclick="stop()">Stop.</button> <button class="more">More</button>
</div>
<div class="soundclips">
{% for clip in clips %}
<button onclick="play('{{clip.hash}}')">{{clip.file_name}}</button>
{% endfor %}
</div>
<div class="player">
<button onclick="stop()">Stop.</button>
</div>
</div>
</body> </body>
</html> </html>