refactor: merge workspace (core/ + ui/) into a single flat binary crate
integrate CLI into main.rs, no lib.rs by design (YAGNI)
This commit is contained in:
parent
9ec407d9aa
commit
1a0b8c49aa
27 changed files with 171 additions and 249 deletions
73
Cargo.toml
73
Cargo.toml
|
|
@ -1,8 +1,73 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# Cargo.toml
|
||||
#
|
||||
# Workspace manifest for the Noctua project.
|
||||
# Noctua COSMIC desktop application
|
||||
|
||||
[workspace]
|
||||
members = ["core", "ui"]
|
||||
resolver = "2"
|
||||
[package]
|
||||
name = "noctua"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "Noctua – a document viewer for the COSMIC™ desktop"
|
||||
repository = "https://codeberg.org/wfx/noctua"
|
||||
authors = ["Wolfgang Morawetz <wfx@mailbox.org>"]
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[features]
|
||||
default = ["image", "vector", "portable"]
|
||||
image = ["dep:image", "dep:kamadak-exif"]
|
||||
vector = ["dep:resvg"]
|
||||
portable = ["dep:pdfium-render"]
|
||||
full = ["image", "vector", "portable"]
|
||||
|
||||
[dependencies]
|
||||
# Serialization
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
ron = "0.8"
|
||||
|
||||
# Feature-gated document backends
|
||||
image = { version = "0.25", optional = true }
|
||||
kamadak-exif = { version = "0.5", optional = true }
|
||||
pdfium-render = { version = "0.8", optional = true }
|
||||
resvg = { version = "0.45", optional = true }
|
||||
|
||||
# Logging
|
||||
log = "0.4"
|
||||
env_logger = "0.11"
|
||||
|
||||
# i18n / localization
|
||||
i18n-embed = { version = "0.16", features = [
|
||||
"fluent-system",
|
||||
"desktop-requester",
|
||||
] }
|
||||
i18n-embed-fl = "0.10"
|
||||
|
||||
# Resource embedding
|
||||
rust-embed = "8"
|
||||
|
||||
# Open files/URLs with the system default application
|
||||
open = "5"
|
||||
|
||||
# Thumbnail cache (freedesktop.org spec)
|
||||
dirs = "5.0"
|
||||
md5 = "0.7"
|
||||
png = "0.17"
|
||||
|
||||
# CLI argument parsing
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
|
||||
# Async runtime (required by libcosmic)
|
||||
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
|
||||
|
||||
[dependencies.libcosmic]
|
||||
git = "https://github.com/pop-os/libcosmic.git"
|
||||
features = [
|
||||
"a11y",
|
||||
"about",
|
||||
"dbus-config",
|
||||
"multi-window",
|
||||
"single-instance",
|
||||
"tokio",
|
||||
"winit",
|
||||
"wayland",
|
||||
"wgpu",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# core/Cargo.toml
|
||||
#
|
||||
# Core library crate – no UI dependencies.
|
||||
|
||||
[package]
|
||||
name = "noctua_core"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "Document core library for the Noctua viewer"
|
||||
repository = "https://codeberg.org/wfx/noctua"
|
||||
authors = ["Wolfgang Morawetz <wfx@mailbox.org>"]
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[lib]
|
||||
name = "noctua_core"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
default = ["image", "vector", "portable"]
|
||||
image = ["dep:image", "dep:kamadak-exif"]
|
||||
vector = ["dep:resvg"]
|
||||
portable = ["dep:pdfium-render"]
|
||||
full = ["image", "vector", "portable"]
|
||||
|
||||
[dependencies]
|
||||
# Serialization
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
ron = "0.8"
|
||||
|
||||
# Feature-gated document backends
|
||||
image = { version = "0.25", optional = true }
|
||||
kamadak-exif = { version = "0.5", optional = true }
|
||||
pdfium-render = { version = "0.8", optional = true }
|
||||
resvg = { version = "0.45", optional = true }
|
||||
|
||||
# Logging interface
|
||||
log = "0.4"
|
||||
|
||||
# Thumbnail cache (freedesktop.org spec)
|
||||
dirs = "5.0"
|
||||
md5 = "0.7"
|
||||
png = "0.17"
|
||||
|
||||
[dev-dependencies]
|
||||
# CLI test harness (examples/cli.rs only)
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
env_logger = "0.11"
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// src/lib.rs
|
||||
//
|
||||
// Public API of the noctua_core library.
|
||||
|
||||
pub mod error;
|
||||
|
||||
pub mod document;
|
||||
pub mod render;
|
||||
|
||||
pub use document::command::DocumentCommand;
|
||||
pub use document::manager::DocumentManager;
|
||||
pub use document::session::SessionCommand;
|
||||
pub use document::types::RawImage;
|
||||
8
justfile
8
justfile
|
|
@ -60,13 +60,9 @@ check-json: (check '--message-format=json')
|
|||
test *args:
|
||||
cargo test --workspace {{args}}
|
||||
|
||||
# Runs the COSMIC UI application
|
||||
# Runs the application (no args = COSMIC UI, with args = CLI mode)
|
||||
run *args:
|
||||
env RUST_BACKTRACE=full cargo run --release -p noctua_ui {{args}}
|
||||
|
||||
# Runs the CLI test harness (core only, no UI deps)
|
||||
run-cli *args:
|
||||
env RUST_BACKTRACE=full cargo run --example cli -p noctua_core {{args}}
|
||||
env RUST_BACKTRACE=full cargo run --release {{args}}
|
||||
|
||||
# Installs files
|
||||
install:
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use self::model::{PortableModel, RasterModel, VectorModel};
|
|||
|
||||
/// The decoded content of a loaded document.
|
||||
///
|
||||
/// This enum is internal to `noctua_core`. The UI only ever sees a `RawImage`
|
||||
/// This enum is internal to Noctua. The UI only ever sees a `RawImage`
|
||||
/// produced by the render subsystem – it never matches on this type.
|
||||
#[derive(Debug)]
|
||||
pub enum DocumentContent {
|
||||
|
|
@ -6,6 +6,3 @@
|
|||
pub mod command;
|
||||
pub mod data;
|
||||
pub mod store;
|
||||
|
||||
pub use command::SessionCommand;
|
||||
pub use data::{CollectionKind, SessionData, SessionItem};
|
||||
|
|
@ -7,6 +7,5 @@ pub mod image;
|
|||
pub mod layout;
|
||||
pub mod viewbox;
|
||||
|
||||
pub use image::RawImage;
|
||||
pub use layout::PageLayout;
|
||||
pub use viewbox::ViewBox;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// src/error.rs
|
||||
//
|
||||
// Central error and result types for noctua_core.
|
||||
// Central error and result types for Noctua.
|
||||
|
||||
use std::fmt;
|
||||
|
||||
|
|
@ -13,8 +13,6 @@ pub enum Error {
|
|||
NotFound(String),
|
||||
/// The file format or operation is not supported.
|
||||
Unsupported(String),
|
||||
/// A rendering operation failed.
|
||||
Render(String),
|
||||
/// A session could not be loaded or saved.
|
||||
Session(String),
|
||||
/// An underlying I/O error.
|
||||
|
|
@ -26,7 +24,6 @@ impl fmt::Display for Error {
|
|||
match self {
|
||||
Error::NotFound(msg) => write!(f, "Not found: {msg}"),
|
||||
Error::Unsupported(msg) => write!(f, "Unsupported: {msg}"),
|
||||
Error::Render(msg) => write!(f, "Render error: {msg}"),
|
||||
Error::Session(msg) => write!(f, "Session error: {msg}"),
|
||||
Error::Io(err) => write!(f, "I/O error: {err}"),
|
||||
}
|
||||
|
|
@ -1,13 +1,17 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// examples/cli.rs
|
||||
// src/main.rs
|
||||
//
|
||||
// CLI test harness for the noctua_core document foundation.
|
||||
// Entry point for the Noctua COSMIC application.
|
||||
|
||||
use clap::{ArgGroup, Parser};
|
||||
use noctua_core::document::manager::{DocumentManager, DocumentState};
|
||||
use noctua_core::document::session::command::SessionCommand;
|
||||
use noctua_core::document::session::data::{CollectionKind, SessionData};
|
||||
use std::path::PathBuf;
|
||||
mod document;
|
||||
mod error;
|
||||
mod render;
|
||||
|
||||
use clap::Parser;
|
||||
use document::manager::{DocumentManager, DocumentState};
|
||||
use document::session::command::SessionCommand;
|
||||
use document::session::data::{CollectionKind, SessionData};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
// ANSI helpers
|
||||
|
||||
|
|
@ -87,50 +91,45 @@ fn print_active_session(mgr: &DocumentManager) {
|
|||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(
|
||||
name = "noctua",
|
||||
about = "A document viewer for the COSMIC desktop",
|
||||
group(
|
||||
ArgGroup::new("source")
|
||||
.required(true)
|
||||
.args(["open_document", "open_directory", "open_session"])
|
||||
)
|
||||
)]
|
||||
struct Opt {
|
||||
#[command(name = "noctua", about = "A document viewer for the COSMIC desktop")]
|
||||
struct Args {
|
||||
/// Open a document (raster, vector, portable)
|
||||
#[arg(long, value_name = "PATH")]
|
||||
open_document: Option<PathBuf>,
|
||||
#[arg(long = "open-document", value_name = "PATH")]
|
||||
document: Option<PathBuf>,
|
||||
|
||||
/// Open a directory
|
||||
#[arg(long, value_name = "PATH")]
|
||||
open_directory: Option<PathBuf>,
|
||||
#[arg(long = "open-directory", value_name = "PATH")]
|
||||
directory: Option<PathBuf>,
|
||||
|
||||
/// Open a session file (.ron)
|
||||
#[arg(long, value_name = "PATH")]
|
||||
open_session: Option<PathBuf>,
|
||||
#[arg(long = "open-session", value_name = "PATH")]
|
||||
session: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let cli = Opt::parse();
|
||||
let mut mgr = DocumentManager::new();
|
||||
let args = Args::parse();
|
||||
|
||||
// Open source
|
||||
if args.document.is_none() && args.directory.is_none() && args.session.is_none() {
|
||||
// TODO: Launch COSMIC UI.
|
||||
return;
|
||||
}
|
||||
|
||||
heading("Opening source");
|
||||
run_cli(args);
|
||||
}
|
||||
|
||||
if let Some(path) = cli.open_session {
|
||||
fn open_source(mgr: &mut DocumentManager, args: Args) {
|
||||
if let Some(path) = args.session {
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
"Open session file",
|
||||
SessionCommand::OpenSession { path },
|
||||
);
|
||||
} else if let Some(path) = cli.open_document {
|
||||
} else if let Some(path) = args.document {
|
||||
let dir = path
|
||||
.parent()
|
||||
.map(|p| p.to_path_buf())
|
||||
.unwrap_or_else(|| PathBuf::from("."));
|
||||
.map_or_else(|| PathBuf::from("."), Path::to_path_buf);
|
||||
|
||||
let session_name = dir
|
||||
.file_name()
|
||||
|
|
@ -139,30 +138,30 @@ fn main() {
|
|||
.to_string();
|
||||
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
&format!("New session '{session_name}'"),
|
||||
SessionCommand::NewSession {
|
||||
name: session_name.clone(),
|
||||
},
|
||||
);
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
&format!("Select '{session_name}'"),
|
||||
SessionCommand::SelectSession {
|
||||
name: session_name.clone(),
|
||||
},
|
||||
);
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
&format!("Add directory {}", dir.display()),
|
||||
SessionCommand::AddDirectoryToSession { dir },
|
||||
);
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
&format!("Add document {}", path.display()),
|
||||
SessionCommand::AddDocumentToSession { path },
|
||||
);
|
||||
} else if let Some(path) = cli.open_directory {
|
||||
} else if let Some(path) = args.directory {
|
||||
let session_name = path
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
|
|
@ -170,69 +169,44 @@ fn main() {
|
|||
.to_string();
|
||||
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
&format!("New session '{session_name}'"),
|
||||
SessionCommand::NewSession {
|
||||
name: session_name.clone(),
|
||||
},
|
||||
);
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
&format!("Select '{session_name}'"),
|
||||
SessionCommand::SelectSession {
|
||||
name: session_name.clone(),
|
||||
},
|
||||
);
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
&format!("Add directory {}", path.display()),
|
||||
SessionCommand::AddDirectoryToSession { dir: path },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// State summary
|
||||
|
||||
heading("State after open");
|
||||
|
||||
match &mgr.state {
|
||||
DocumentState::Empty => info("No document loaded"),
|
||||
DocumentState::Loading => info("Loading…"),
|
||||
DocumentState::Error(e) => err(&format!("{e}")),
|
||||
DocumentState::Loaded(_) => ok("Document loaded"),
|
||||
}
|
||||
|
||||
let active_name = match mgr.active_session().map(|s| s.name.clone()) {
|
||||
Some(n) => n,
|
||||
None => {
|
||||
info("No active session – nothing more to test.");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
print_active_session(&mgr);
|
||||
|
||||
// Navigation
|
||||
|
||||
fn run_navigation_test(mgr: &mut DocumentManager) {
|
||||
heading("Navigation");
|
||||
|
||||
exec(&mut mgr, "NextDocument", SessionCommand::NextDocument);
|
||||
exec(mgr, "NextDocument", SessionCommand::NextDocument);
|
||||
ok(&format!(
|
||||
"After NextDocument → index {:?}",
|
||||
mgr.active_document_index()
|
||||
));
|
||||
|
||||
exec(
|
||||
&mut mgr,
|
||||
"PreviousDocument",
|
||||
SessionCommand::PreviousDocument,
|
||||
);
|
||||
exec(mgr, "PreviousDocument", SessionCommand::PreviousDocument);
|
||||
ok(&format!(
|
||||
"After PreviousDocument → index {:?}",
|
||||
mgr.active_document_index()
|
||||
));
|
||||
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
"SelectDocument { index: 0 }",
|
||||
SessionCommand::SelectDocument { index: 0 },
|
||||
);
|
||||
|
|
@ -241,42 +215,36 @@ fn main() {
|
|||
mgr.active_document_index()
|
||||
));
|
||||
|
||||
// Move operations
|
||||
|
||||
heading("Move operations");
|
||||
|
||||
step("Before MoveDocumentDown:");
|
||||
print_active_session(&mgr);
|
||||
print_active_session(mgr);
|
||||
|
||||
exec(
|
||||
&mut mgr,
|
||||
"MoveDocumentDown",
|
||||
SessionCommand::MoveDocumentDown,
|
||||
);
|
||||
exec(mgr, "MoveDocumentDown", SessionCommand::MoveDocumentDown);
|
||||
ok(&format!(
|
||||
"After MoveDocumentDown → index {:?}",
|
||||
mgr.active_document_index()
|
||||
));
|
||||
|
||||
exec(&mut mgr, "MoveDocumentUp", SessionCommand::MoveDocumentUp);
|
||||
exec(mgr, "MoveDocumentUp", SessionCommand::MoveDocumentUp);
|
||||
ok(&format!(
|
||||
"After MoveDocumentUp → index {:?}",
|
||||
mgr.active_document_index()
|
||||
));
|
||||
}
|
||||
|
||||
// Copy / Paste
|
||||
|
||||
fn run_copy_paste_test(mgr: &mut DocumentManager, active_name: &str) {
|
||||
heading("Copy / Paste");
|
||||
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
"New session 'Favorites'",
|
||||
SessionCommand::NewSession {
|
||||
name: "Favorites".to_string(),
|
||||
},
|
||||
);
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
"New session 'Workspace'",
|
||||
SessionCommand::NewSession {
|
||||
name: "Workspace".to_string(),
|
||||
|
|
@ -288,61 +256,56 @@ fn main() {
|
|||
print_session(session, None);
|
||||
}
|
||||
|
||||
// SelectSession source → SelectDocument → CopyDocument → SelectSession target → PasteDocument
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
&format!("SelectSession '{active_name}'"),
|
||||
SessionCommand::SelectSession {
|
||||
name: active_name.clone(),
|
||||
name: active_name.to_string(),
|
||||
},
|
||||
);
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
"SelectDocument { index: 0 }",
|
||||
SessionCommand::SelectDocument { index: 0 },
|
||||
);
|
||||
exec(&mut mgr, "CopyDocument", SessionCommand::CopyDocument);
|
||||
exec(mgr, "CopyDocument", SessionCommand::CopyDocument);
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
"SelectSession 'Favorites'",
|
||||
SessionCommand::SelectSession {
|
||||
name: "Favorites".to_string(),
|
||||
},
|
||||
);
|
||||
exec(&mut mgr, "PasteDocument", SessionCommand::PasteDocument);
|
||||
exec(mgr, "PasteDocument", SessionCommand::PasteDocument);
|
||||
|
||||
step("Favorites after paste:");
|
||||
print_active_session(&mgr);
|
||||
|
||||
// Move pasted item to front via MoveDocumentTo
|
||||
print_active_session(mgr);
|
||||
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
"MoveDocumentTo { index: 0 }",
|
||||
SessionCommand::MoveDocumentTo { index: 0 },
|
||||
);
|
||||
step("Favorites after MoveDocumentTo(0):");
|
||||
print_active_session(&mgr);
|
||||
print_active_session(mgr);
|
||||
|
||||
// Remove active document
|
||||
|
||||
exec(&mut mgr, "RemoveDocument", SessionCommand::RemoveDocument);
|
||||
exec(mgr, "RemoveDocument", SessionCommand::RemoveDocument);
|
||||
step("Favorites after RemoveDocument:");
|
||||
print_active_session(&mgr);
|
||||
|
||||
// Session operations
|
||||
print_active_session(mgr);
|
||||
}
|
||||
|
||||
fn run_session_test(mgr: &mut DocumentManager, active_name: &str) {
|
||||
heading("Session operations");
|
||||
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
&format!("SelectSession '{active_name}'"),
|
||||
SessionCommand::SelectSession {
|
||||
name: active_name.clone(),
|
||||
name: active_name.to_string(),
|
||||
},
|
||||
);
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
"DuplicateSession 'Snapshot'",
|
||||
SessionCommand::DuplicateSession {
|
||||
new_name: "Snapshot".to_string(),
|
||||
|
|
@ -355,14 +318,14 @@ fn main() {
|
|||
}
|
||||
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
"SelectSession 'Workspace'",
|
||||
SessionCommand::SelectSession {
|
||||
name: "Workspace".to_string(),
|
||||
},
|
||||
);
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
"RenameSession 'Archive'",
|
||||
SessionCommand::RenameSession {
|
||||
name: "Archive".to_string(),
|
||||
|
|
@ -371,9 +334,7 @@ fn main() {
|
|||
|
||||
step("All sessions after rename:");
|
||||
for session in mgr.sessions() {
|
||||
let is_active = mgr
|
||||
.active_session()
|
||||
.map_or(false, |a| a.name == session.name);
|
||||
let is_active = mgr.active_session().is_some_and(|a| a.name == session.name);
|
||||
let marker = if is_active {
|
||||
format!("{GREEN}*{RESET}")
|
||||
} else {
|
||||
|
|
@ -383,7 +344,7 @@ fn main() {
|
|||
}
|
||||
|
||||
exec(
|
||||
&mut mgr,
|
||||
mgr,
|
||||
"CloseSession (closes 'Archive')",
|
||||
SessionCommand::CloseSession,
|
||||
);
|
||||
|
|
@ -392,6 +353,33 @@ fn main() {
|
|||
for session in mgr.sessions() {
|
||||
println!(" {DIM}-{RESET} {}", session.name);
|
||||
}
|
||||
}
|
||||
|
||||
fn run_cli(args: Args) {
|
||||
let mut mgr = DocumentManager::new();
|
||||
|
||||
heading("Opening source");
|
||||
open_source(&mut mgr, args);
|
||||
|
||||
heading("State after open");
|
||||
|
||||
match &mgr.state {
|
||||
DocumentState::Empty => info("No document loaded"),
|
||||
DocumentState::Loading => info("Loading…"),
|
||||
DocumentState::Error(e) => err(&format!("{e}")),
|
||||
DocumentState::Loaded(_) => ok("Document loaded"),
|
||||
}
|
||||
|
||||
let Some(active_name) = mgr.active_session().map(|s| s.name.clone()) else {
|
||||
info("No active session – nothing more to test.");
|
||||
return;
|
||||
};
|
||||
|
||||
print_active_session(&mgr);
|
||||
|
||||
run_navigation_test(&mut mgr);
|
||||
run_copy_paste_test(&mut mgr, &active_name);
|
||||
run_session_test(&mut mgr, &active_name);
|
||||
|
||||
heading("Done");
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# ui/Cargo.toml
|
||||
#
|
||||
# Binary crate for the Noctua COSMIC desktop application.
|
||||
|
||||
[package]
|
||||
name = "noctua"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "Noctua – a document viewer for the COSMIC™ desktop"
|
||||
repository = "https://codeberg.org/wfx/noctua"
|
||||
authors = ["Wolfgang Morawetz <wfx@mailbox.org>"]
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[dependencies]
|
||||
noctua_core = { path = "../core" }
|
||||
|
||||
# Logging
|
||||
log = "0.4"
|
||||
env_logger = "0.11"
|
||||
|
||||
# i18n / localization
|
||||
i18n-embed = { version = "0.16", features = [
|
||||
"fluent-system",
|
||||
"desktop-requester",
|
||||
] }
|
||||
i18n-embed-fl = "0.10"
|
||||
|
||||
# Resource embedding
|
||||
rust-embed = "8"
|
||||
|
||||
# Open files/URLs with the system default application
|
||||
open = "5"
|
||||
|
||||
# Async runtime (required by libcosmic)
|
||||
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
|
||||
|
||||
[dependencies.libcosmic]
|
||||
git = "https://github.com/pop-os/libcosmic.git"
|
||||
features = [
|
||||
"a11y",
|
||||
"about",
|
||||
"dbus-config",
|
||||
"multi-window",
|
||||
"single-instance",
|
||||
"tokio",
|
||||
"winit",
|
||||
"wayland",
|
||||
"wgpu",
|
||||
]
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// src/main.rs
|
||||
//
|
||||
// Entry point for the Noctua COSMIC application.
|
||||
|
||||
fn main() {
|
||||
// TODO: Initialize the COSMIC application.
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue