Compare commits
5
Commits
c3806f49ba
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5aa894912d | ||
|
|
00c24bca94 | ||
|
|
b6ab469616 | ||
|
|
cef96884c6 | ||
|
|
f8f86eeae1 |
@@ -6,7 +6,9 @@ use std::path::Path;
|
||||
use std::io::Read;
|
||||
use lumiere_domain::video::error::VideoError;
|
||||
use lumiere_domain::video::model::library_item::{LibraryItem, LibraryRawItem};
|
||||
use lumiere_domain::video::model::video::Video;
|
||||
use lumiere_domain::video::port::VideoPort;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VideoService {
|
||||
@@ -38,6 +40,11 @@ impl VideoService {
|
||||
let all_items = already_existing_items.into_iter().chain(new_items).collect();
|
||||
Ok(all_items)
|
||||
}
|
||||
|
||||
pub fn get_video_stream(&self, video_id: Uuid) -> Result<Video, VideoError> {
|
||||
self.video_port.get_video_stream(video_id)
|
||||
.map_err(|_| VideoError::VideoDoesNotExists)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#[derive(Debug)]
|
||||
pub enum VideoError {
|
||||
VideoDoesNotExists,
|
||||
FolderDoesNotExists,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::any::Any;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub enum VideoFormat {
|
||||
@@ -8,7 +9,9 @@ pub enum VideoFormat {
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
pub trait VideoFile {}
|
||||
pub trait VideoFile: Any {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
}
|
||||
|
||||
pub struct Video {
|
||||
pub id: Uuid,
|
||||
|
||||
Generated
+457
@@ -641,6 +641,41 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.10"
|
||||
@@ -684,6 +719,52 @@ dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel"
|
||||
version = "2.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e54d1f576cd3a3460f212a4615fd12ce1b6303c095b79a44449ffbe627753dc1"
|
||||
dependencies = [
|
||||
"diesel_derives",
|
||||
"downcast-rs",
|
||||
"libsqlite3-sys",
|
||||
"sqlite-wasm-rs",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel_derives"
|
||||
version = "2.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1817b7f4279b947fc4cafddec12b0e5f8727141706561ce3ac94a60bddd1cf5"
|
||||
dependencies = [
|
||||
"diesel_table_macro_syntax",
|
||||
"dsl_auto_type",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel_migrations"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d0f4a98124ba6d4ca75da535f65984badec16a003b6e2f94a01e31a79490b8"
|
||||
dependencies = [
|
||||
"diesel",
|
||||
"migrations_internals",
|
||||
"migrations_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel_table_macro_syntax"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe2444076b48641147115697648dc743c2c00b61adade0f01ce67133c7babe8c"
|
||||
dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
@@ -707,6 +788,16 @@ dependencies = [
|
||||
"crypto-common 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch2"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.5"
|
||||
@@ -718,6 +809,26 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "downcast-rs"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc"
|
||||
|
||||
[[package]]
|
||||
name = "dsl_auto_type"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd122633e4bef06db27737f21d3738fb89c8f6d5360d6d9d7635dda142a7757e"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"either",
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.16.9"
|
||||
@@ -756,6 +867,12 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.13.8"
|
||||
@@ -802,6 +919,18 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
||||
|
||||
[[package]]
|
||||
name = "fallible-streaming-iterator"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.13.1"
|
||||
@@ -999,12 +1128,30 @@ dependencies = [
|
||||
"foldhash 0.1.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||
dependencies = [
|
||||
"foldhash 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
|
||||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824e001ac4f3012dd16a264bec811403a67ca9deb6c102fc5049b32c4574b35f"
|
||||
dependencies = [
|
||||
"hashbrown 0.16.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
@@ -1241,6 +1388,12 @@ version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "1.1.0"
|
||||
@@ -1378,6 +1531,17 @@ version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
version = "0.8.2"
|
||||
@@ -1453,12 +1617,29 @@ dependencies = [
|
||||
"jsonwebtoken",
|
||||
"lumiere-application",
|
||||
"lumiere-domain",
|
||||
"lumiere-infrastructure",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lumiere-infrastructure"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"diesel",
|
||||
"diesel_migrations",
|
||||
"log",
|
||||
"lumiere-domain",
|
||||
"rand 0.10.2",
|
||||
"rusqlite",
|
||||
"sysinfo",
|
||||
"tokio",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.8.4"
|
||||
@@ -1471,6 +1652,27 @@ version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||
|
||||
[[package]]
|
||||
name = "migrations_internals"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36c791ecdf977c99f45f23280405d7723727470f6689a5e6dbf513ac547ae10d"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "migrations_macros"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36fc5ac76be324cfd2d3f2cf0fdf5d5d3c4f14ed8aaebadb09e304ba42282703"
|
||||
dependencies = [
|
||||
"migrations_internals",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
@@ -1499,6 +1701,15 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
@@ -1561,6 +1772,63 @@ dependencies = [
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
|
||||
dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-open-directory"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb82bed227edf5201dfedf072bba4015a33d3d4a98519837295a90f0a23f676d"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.4"
|
||||
@@ -1880,6 +2148,31 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rsqlite-vfs"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c51c9ae4df8a7fba42103df5c621fa3c37eccf3a3c650879e90fc48b11cc192c"
|
||||
dependencies = [
|
||||
"hashbrown 0.16.1",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusqlite"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0d2b0146dd9661bf67bb107c0bb2a55064d556eeb3fc314151b957f313bcd4e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"fallible-iterator",
|
||||
"fallible-streaming-iterator",
|
||||
"hashlink",
|
||||
"libsqlite3-sys",
|
||||
"smallvec",
|
||||
"sqlite-wasm-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
@@ -2014,6 +2307,15 @@ dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
@@ -2140,12 +2442,30 @@ dependencies = [
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlite-wasm-rs"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc3efc0da82635d7e1ced0053bbbfa8c7ab9645d0bf36ceb4f7127bb85315d75"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"js-sys",
|
||||
"rsqlite-vfs",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
@@ -2180,6 +2500,21 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.39.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2071df9448915b71c4fe6d25deaf1c22f12bd234f01540b77312bb8e41361e6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"memchr",
|
||||
"ntapi",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-kit",
|
||||
"objc2-open-directory",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.18"
|
||||
@@ -2292,6 +2627,37 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.9.12+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_parser",
|
||||
"winnow 0.7.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.7.5+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
|
||||
dependencies = [
|
||||
"winnow 1.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.5.3"
|
||||
@@ -2412,6 +2778,12 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
@@ -2521,6 +2893,49 @@ dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
@@ -2534,6 +2949,17 @@ dependencies = [
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
@@ -2562,6 +2988,16 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
@@ -2614,6 +3050,15 @@ dependencies = [
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
@@ -2662,6 +3107,18 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.51.0"
|
||||
|
||||
@@ -10,6 +10,7 @@ path = "src/lib.rs"
|
||||
[dependencies]
|
||||
lumiere-domain = { path = "../domain" }
|
||||
lumiere-application = { path = "../application" }
|
||||
lumiere-infrastructure = { path = "../infrastructure" }
|
||||
|
||||
actix-web = { version = "4.14.0", features = ["rustls-0_23"] }
|
||||
actix-web-httpauth = "0.8.2"
|
||||
|
||||
@@ -2,7 +2,7 @@ extern crate core;
|
||||
|
||||
use actix_web::web::ServiceConfig;
|
||||
use actix_web::{get, web, HttpResponse, Responder};
|
||||
use crate::video::handler::{download_file, get_root_folder_content};
|
||||
use crate::video::handler::{download_file, get_root_folder_content, get_video_stream};
|
||||
|
||||
pub mod user;
|
||||
pub mod video;
|
||||
@@ -14,6 +14,7 @@ async fn health() -> impl Responder {
|
||||
|
||||
pub fn init(cfg: &mut ServiceConfig) {
|
||||
cfg.service(download_file)
|
||||
.service(get_video_stream)
|
||||
.service(get_root_folder_content);
|
||||
cfg.default_service(web::to(not_found));
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@ use actix_web::{get, web, HttpResponse, Responder};
|
||||
use tokio::fs::File;
|
||||
use tokio_util::codec::{BytesCodec, FramedRead};
|
||||
use futures_util::stream::StreamExt;
|
||||
use uuid::Uuid;
|
||||
use lumiere_application::video::service::VideoService;
|
||||
use lumiere_infrastructure::video::model::TokioVideoFile;
|
||||
use crate::video::model::LibraryItemDto;
|
||||
|
||||
#[get("/download")]
|
||||
#[get("/api/download")]
|
||||
pub async fn download_file() -> impl Responder {
|
||||
HttpResponse::Ok()
|
||||
.content_type("application/octet-stream")
|
||||
@@ -19,7 +21,41 @@ pub async fn download_file() -> impl Responder {
|
||||
})
|
||||
}
|
||||
|
||||
#[get("/library")]
|
||||
#[get("/api/videos/{video_id}/stream")]
|
||||
pub async fn get_video_stream(
|
||||
video_service: web::Data<Arc<VideoService>>,
|
||||
video_id: web::Path<Uuid>
|
||||
) -> impl Responder {
|
||||
let video_result = video_service.get_video_stream(video_id.into_inner());
|
||||
|
||||
match video_result {
|
||||
Ok(video) => {
|
||||
if let Some(tokio_video_file) = video.file.as_any().downcast_ref::<TokioVideoFile>() {
|
||||
// Clone the file to extend its lifetime into the streaming closure
|
||||
let cloned_file = tokio_video_file.file.try_clone();
|
||||
|
||||
match cloned_file {
|
||||
Ok(file) => HttpResponse::Ok()
|
||||
.content_type("application/octet-stream")
|
||||
.streaming(async_stream::stream! {
|
||||
let file = tokio::fs::File::from_std(file);
|
||||
let mut stream = FramedRead::new(file, BytesCodec::new());
|
||||
while let Some(chunk) = stream.next().await {
|
||||
yield chunk.map(|bytes| bytes.freeze());
|
||||
}
|
||||
}),
|
||||
Err(_) => HttpResponse::InternalServerError().body("Failed to clone video file")
|
||||
}
|
||||
|
||||
} else {
|
||||
HttpResponse::InternalServerError().body("Video file format is not handled.")
|
||||
}
|
||||
}
|
||||
Err(error) => HttpResponse::InternalServerError().body(format!("{:?}", error))
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/api/library")]
|
||||
pub async fn get_root_folder_content(
|
||||
video_service: web::Data<Arc<VideoService>>
|
||||
) -> impl Responder {
|
||||
|
||||
@@ -17,5 +17,5 @@ log = "0.4.33"
|
||||
rand = "0.10.2"
|
||||
rusqlite = { version = "0.39.0", features = ["bundled"] }
|
||||
sysinfo = "0.39.6"
|
||||
tokio = { version = "1.52.3", features = ["fs"] }
|
||||
tokio = { version = "1.52.3", features = ["fs", "rt-multi-thread"] }
|
||||
uuid = { version = "1.23.1", features = ["v4"] }
|
||||
@@ -7,8 +7,10 @@ use std::env;
|
||||
use std::fs;
|
||||
use std::fs::DirEntry;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use LibraryItemType::FOLDER;
|
||||
use lumiere_domain::video::model::library_item::LibraryItemType::VIDEO;
|
||||
use lumiere_domain::video::model::video::VideoFormat::{AVI, MKV, MP4, WEBM};
|
||||
use crate::video::model::LibraryItemEntity;
|
||||
use crate::video::model::{LibraryItemEntity, TokioVideoFile};
|
||||
use crate::video::repository::LibraryItemSqliteRepository;
|
||||
use crate::video::video_format_detector::get_content_type;
|
||||
|
||||
@@ -46,7 +48,7 @@ impl LibraryItemAdapter {
|
||||
|
||||
fn map_file_into_library_raw_item(file: DirEntry) -> Result<LibraryRawItem, VideoError> {
|
||||
let item_type = if file.path().is_dir() {
|
||||
LibraryItemType::FOLDER
|
||||
FOLDER
|
||||
} else {
|
||||
LibraryItemType::VIDEO
|
||||
};
|
||||
@@ -74,6 +76,12 @@ impl LibraryItemAdapter {
|
||||
database_items.iter()
|
||||
.any(|database_item| database_item.name == file_system_item.name)
|
||||
}
|
||||
|
||||
fn find_library_item_by_id(&self, library_item_id: Uuid) -> Result<Option<LibraryItem>, VideoError> {
|
||||
self.repository.find_by_id(library_item_id)
|
||||
.map_err(|_| VideoError::FileReadingTechnicalIssue)
|
||||
.map(|entity_opt| entity_opt.map(LibraryItemEntity::to_library_item))
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoPort for LibraryItemAdapter {
|
||||
@@ -102,7 +110,28 @@ impl VideoPort for LibraryItemAdapter {
|
||||
}
|
||||
|
||||
fn get_video_stream(&self, video_id: Uuid) -> Result<Video, VideoError> {
|
||||
todo!()
|
||||
let video_item = self.find_library_item_by_id(video_id)?;
|
||||
|
||||
match video_item {
|
||||
None => Err(VideoError::VideoDoesNotExists),
|
||||
Some(video) => {
|
||||
match video.r#type {
|
||||
VIDEO => {
|
||||
let root_folder = env::var("ROOT_FOLDER").map_err(|_| VideoError::FolderBrowsingTechnicalIssue)?;
|
||||
let video_file_path = String::from(format!("{root_folder}/{}", video.name));
|
||||
let result = Video {
|
||||
id: video.id,
|
||||
name: video.name,
|
||||
format: AVI,
|
||||
file: Box::new(TokioVideoFile::new(&video_file_path))
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
},
|
||||
FOLDER => Err(VideoError::VideoDoesNotExists)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn save(&self, library_item: &LibraryItem) -> Result<(), VideoError> {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use std::any::Any;
|
||||
use std::fs::File;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use uuid::Uuid;
|
||||
use lumiere_domain::video::model::library_item::{LibraryItem, LibraryItemType, LibraryRawItem};
|
||||
use lumiere_domain::video::model::video::VideoFile;
|
||||
|
||||
pub struct TokioVideoFile {
|
||||
pub file: File
|
||||
@@ -15,6 +17,12 @@ impl TokioVideoFile {
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoFile for TokioVideoFile {
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct LibraryItemEntity {
|
||||
pub id: Uuid,
|
||||
@@ -48,7 +56,15 @@ impl LibraryItemEntity {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_library_raw_item(self) -> Result<LibraryRawItem, Error> {
|
||||
pub fn to_library_item(self) -> LibraryItem {
|
||||
LibraryItem {
|
||||
id: self.id.clone(),
|
||||
name: self.name.clone(),
|
||||
r#type: Self::map_type_from_i8(self.r#type).expect(""),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_library_raw_item(self) -> Result<LibraryRawItem, Error> {
|
||||
let library_item = LibraryRawItem {
|
||||
id: Some(self.id.clone()),
|
||||
name: self.name.clone(),
|
||||
|
||||
@@ -53,10 +53,10 @@ impl LibraryItemSqliteRepository {
|
||||
WHERE parent_folder_id IS NULL",
|
||||
)?;
|
||||
let rows = prepared_statement.query([])?;
|
||||
rows.map(Self::map_to_library_item).collect::<Vec<LibraryItemEntity>>()
|
||||
rows.map(Self::map_to_entity).collect::<Vec<LibraryItemEntity>>()
|
||||
}
|
||||
|
||||
fn map_to_library_item(row: &Row) -> Result<LibraryItemEntity, Error> {
|
||||
fn map_to_entity(row: &Row) -> Result<LibraryItemEntity, Error> {
|
||||
let id_text: String = row.get(0)?;
|
||||
let type_as_number: i8 = row.get(2)?;
|
||||
Ok(
|
||||
@@ -185,6 +185,26 @@ impl LibraryItemSqliteRepository {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
pub fn find_by_id(&self, library_item_id: Uuid) -> Result<Option<LibraryItemEntity>, Error> {
|
||||
let database_connection = self.get_connection();
|
||||
|
||||
let mut prepared_statement = database_connection.prepare(
|
||||
"SELECT
|
||||
id,
|
||||
name,
|
||||
type,
|
||||
parent_folder_id
|
||||
FROM library_item
|
||||
WHERE id = ?1;"
|
||||
)?;
|
||||
let mut rows = prepared_statement.query([library_item_id.to_string()])?;
|
||||
|
||||
if let Some(row) = rows.next()? {
|
||||
Ok(Some(Self::map_to_entity(&row)?))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn map_to_raw_entity(row: &Row) -> Result<LibraryItemRawEntity, Error> {
|
||||
let id_text: String = row.get(0)?;
|
||||
@@ -199,4 +219,4 @@ impl LibraryItemSqliteRepository {
|
||||
};
|
||||
Ok(raw_entity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+1
@@ -1883,6 +1883,7 @@ dependencies = [
|
||||
"jsonwebtoken",
|
||||
"lumiere-application",
|
||||
"lumiere-domain",
|
||||
"lumiere-infrastructure",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# Editor configuration, see https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.ts]
|
||||
quote_type = single
|
||||
ij_typescript_use_double_quotes = false
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
@@ -0,0 +1,44 @@
|
||||
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
|
||||
|
||||
# Compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
/bazel-out
|
||||
|
||||
# Node
|
||||
/node_modules
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# IDEs and editors
|
||||
.idea/
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/mcp.json
|
||||
.history/*
|
||||
|
||||
# Miscellaneous
|
||||
/.angular/cache
|
||||
.sass-cache/
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
testem.log
|
||||
/typings
|
||||
__screenshots__/
|
||||
|
||||
# System files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.html",
|
||||
"options": {
|
||||
"parser": "angular"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
|
||||
"recommendations": ["angular.ng-template"]
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "ng serve",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: start",
|
||||
"url": "http://localhost:4200/"
|
||||
},
|
||||
{
|
||||
"name": "ng test",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: test",
|
||||
"url": "http://localhost:9876/debug.html"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
// For more information, visit: https://angular.dev/ai/mcp
|
||||
"servers": {
|
||||
"angular-cli": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@angular/cli", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "start",
|
||||
"isBackground": true,
|
||||
"problemMatcher": {
|
||||
"owner": "typescript",
|
||||
"pattern": "$tsc",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": {
|
||||
"regexp": "Changes detected"
|
||||
},
|
||||
"endsPattern": {
|
||||
"regexp": "bundle generation (complete|failed)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"isBackground": true,
|
||||
"problemMatcher": {
|
||||
"owner": "typescript",
|
||||
"pattern": "$tsc",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": {
|
||||
"regexp": "Changes detected"
|
||||
},
|
||||
"endsPattern": {
|
||||
"regexp": "bundle generation (complete|failed)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
# LumiereFrontend
|
||||
|
||||
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 21.2.19.
|
||||
|
||||
## Development server
|
||||
|
||||
To start a local development server, run:
|
||||
|
||||
```bash
|
||||
ng serve
|
||||
```
|
||||
|
||||
Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
|
||||
|
||||
```bash
|
||||
ng generate component component-name
|
||||
```
|
||||
|
||||
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
|
||||
|
||||
```bash
|
||||
ng generate --help
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To build the project run:
|
||||
|
||||
```bash
|
||||
ng build
|
||||
```
|
||||
|
||||
This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
To execute unit tests with the [Vitest](https://vitest.dev/) test runner, use the following command:
|
||||
|
||||
```bash
|
||||
ng test
|
||||
```
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
For end-to-end (e2e) testing, run:
|
||||
|
||||
```bash
|
||||
ng e2e
|
||||
```
|
||||
|
||||
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
|
||||
|
||||
## Additional Resources
|
||||
|
||||
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
||||
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"cli": {
|
||||
"packageManager": "npm"
|
||||
},
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"lumiere-frontend": {
|
||||
"projectType": "application",
|
||||
"schematics": {},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular/build:application",
|
||||
"options": {
|
||||
"browser": "src/main.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"assets": [
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "public"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "500kB",
|
||||
"maximumError": "1MB"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "4kB",
|
||||
"maximumError": "8kB"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"development": {
|
||||
"optimization": false,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular/build:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "lumiere-frontend:build:production"
|
||||
},
|
||||
"development": {
|
||||
"buildTarget": "lumiere-frontend:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular/build:unit-test"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+8825
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "lumiere-frontend",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --proxy-config proxy.conf.json",
|
||||
"build": "ng build",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test"
|
||||
},
|
||||
"private": true,
|
||||
"packageManager": "npm@10.9.7",
|
||||
"dependencies": {
|
||||
"@angular/common": "^21.2.0",
|
||||
"@angular/compiler": "^21.2.0",
|
||||
"@angular/core": "^21.2.0",
|
||||
"@angular/forms": "^21.2.0",
|
||||
"@angular/platform-browser": "^21.2.0",
|
||||
"@angular/router": "^21.2.0",
|
||||
"@types/video.js": "^7.3.58",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"video.js": "^8.23.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/build": "^21.2.19",
|
||||
"@angular/cli": "^21.2.19",
|
||||
"@angular/compiler-cli": "^21.2.0",
|
||||
"jsdom": "^28.0.0",
|
||||
"prettier": "^3.8.1",
|
||||
"typescript": "~5.9.2",
|
||||
"vitest": "^4.0.8"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"/api": {
|
||||
"target": "http://localhost:19000",
|
||||
"secure": false
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,11 @@
|
||||
import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
|
||||
import { provideRouter } from '@angular/router';
|
||||
|
||||
import { routes } from './app.routes';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideBrowserGlobalErrorListeners(),
|
||||
provideRouter(routes)
|
||||
]
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.items-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .7em;
|
||||
padding: 0 .5em;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<h1>Lumière frontend</h1>
|
||||
<div>
|
||||
<button type="button" (click)="loadLibrary()">Reload library</button>
|
||||
</div>
|
||||
<div class="items-container">
|
||||
@for (item of libraryItems.value(); track item.id) {
|
||||
@if (item.type === 'VIDEO') {
|
||||
<button type="button" (click)="activeVideo.set(item); initializeVideoPlayer(item.id)">
|
||||
[{{item.type[0]}}] ({{item.id.substring(0, 4)}}…) {{item.name}}
|
||||
</button>
|
||||
} @else {
|
||||
<div class="item">
|
||||
[{{item.type[0]}}] ({{item.id.substring(0, 4)}}…) {{item.name}}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
@if (activeVideo(); as firstVideo) {
|
||||
<video
|
||||
id="video-player-{{firstVideo.id}}"
|
||||
class="video-js vjs-default-skin"
|
||||
controls
|
||||
preload="auto"
|
||||
width="1024"
|
||||
height="640">
|
||||
<p class="vjs-no-js">
|
||||
To view this video please enable JavaScript, and consider upgrading to a
|
||||
web browser that
|
||||
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
|
||||
</p>
|
||||
</video>
|
||||
}
|
||||
</div>
|
||||
<router-outlet />
|
||||
@@ -0,0 +1,3 @@
|
||||
import { Routes } from '@angular/router';
|
||||
|
||||
export const routes: Routes = [];
|
||||
@@ -0,0 +1,23 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { App } from './app';
|
||||
|
||||
describe('App', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [App],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(App);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render title', async () => {
|
||||
const fixture = TestBed.createComponent(App);
|
||||
await fixture.whenStable();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, lumiere-frontend');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,88 @@
|
||||
import {Component, inject, OnInit, resource, signal} from '@angular/core';
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
import {firstValueFrom} from 'rxjs';
|
||||
import videojs from 'video.js';
|
||||
import type Player from 'video.js/dist/types/player';
|
||||
import 'video.js/dist/video-js.css';
|
||||
enum LibraryItemType {
|
||||
VIDEO = 'VIDEO',
|
||||
FOLDER = 'FOLDER'
|
||||
}
|
||||
|
||||
interface LibraryItem {
|
||||
id: string;
|
||||
name: string;
|
||||
type: LibraryItemType
|
||||
parentFolder: LibraryItem | null;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
imports: [RouterOutlet],
|
||||
templateUrl: './app.html',
|
||||
styleUrl: './app.css'
|
||||
})
|
||||
export class App implements OnInit {
|
||||
#httpClient = inject(HttpClient);
|
||||
|
||||
libraryItems = resource({
|
||||
loader: ({}) => firstValueFrom(this.#httpClient.get<LibraryItem[]>('/api/library'))
|
||||
});
|
||||
|
||||
activeVideo = signal<LibraryItem | null>(null);
|
||||
|
||||
// Store video.js player instances for cleanup
|
||||
#videoPlayers = new Map<string, Player>();
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadLibrary();
|
||||
}
|
||||
|
||||
loadLibrary(): void {
|
||||
this.libraryItems.reload();
|
||||
}
|
||||
|
||||
// Initialize or update the video player
|
||||
initializeVideoPlayer(videoId: string): void {
|
||||
// Wait for the next tick to ensure DOM is updated
|
||||
setTimeout(() => {
|
||||
const element = document.getElementById('video-player-' + videoId);
|
||||
if (!element) {
|
||||
console.error(`Video element with ID 'video-player-${videoId}' not found`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clean up previous player if it exists
|
||||
const previousPlayer = this.#videoPlayers.get(videoId);
|
||||
if (previousPlayer) {
|
||||
previousPlayer.dispose();
|
||||
this.#videoPlayers.delete(videoId);
|
||||
}
|
||||
|
||||
// Initialize new player
|
||||
const player = videojs('video-player-' + videoId, {
|
||||
controls: true,
|
||||
autoplay: false,
|
||||
fluid: true,
|
||||
sources: [{
|
||||
src: `/api/videos/${videoId}/stream`,
|
||||
type: 'video/mp4' // Use MP4 as it's widely supported
|
||||
}],
|
||||
error: (error: Event) => {
|
||||
console.error('Video.js error:', error);
|
||||
}
|
||||
});
|
||||
|
||||
this.#videoPlayers.set(videoId, player);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Clean up all video players on component destroy
|
||||
ngOnDestroy(): void {
|
||||
for (const player of this.#videoPlayers.values()) {
|
||||
player.dispose();
|
||||
}
|
||||
this.#videoPlayers.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>LumiereFrontend</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,6 @@
|
||||
import { bootstrapApplication } from '@angular/platform-browser';
|
||||
import { appConfig } from './app/app.config';
|
||||
import { App } from './app/app';
|
||||
|
||||
bootstrapApplication(App, appConfig)
|
||||
.catch((err) => console.error(err));
|
||||
@@ -0,0 +1 @@
|
||||
/* You can add global styles to this file, and also import other style files */
|
||||
@@ -0,0 +1,15 @@
|
||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/app",
|
||||
"types": []
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"src/**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"skipLibCheck": true,
|
||||
"isolatedModules": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"target": "ES2022",
|
||||
"module": "preserve"
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"strictTemplates": true
|
||||
},
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/spec",
|
||||
"types": [
|
||||
"vitest/globals"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user