mirror of
https://github.com/librekeys/picoforge.git
synced 2026-07-28 08:01:19 -07:00
chore: change code formatting, use space for tabs and indents instead of tabs
This commit is contained in:
Generated
-31
@@ -1469,15 +1469,6 @@ dependencies = [
|
||||
"dirs-sys 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
|
||||
dependencies = [
|
||||
"dirs-sys 0.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.7"
|
||||
@@ -2416,17 +2407,6 @@ dependencies = [
|
||||
"zed-sum-tree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gpui-component-assets"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5842ea3f1e596fbc611894dcc0266df7125bc226f603ca313f5460b700503564"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gpui",
|
||||
"rust-embed",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gpui-component-macros"
|
||||
version = "0.5.0"
|
||||
@@ -4304,7 +4284,6 @@ dependencies = [
|
||||
"directories",
|
||||
"gpui",
|
||||
"gpui-component",
|
||||
"gpui-component-assets",
|
||||
"hex",
|
||||
"hidapi",
|
||||
"log",
|
||||
@@ -4986,7 +4965,6 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rust-embed-utils",
|
||||
"shellexpand",
|
||||
"syn 2.0.114",
|
||||
"walkdir",
|
||||
]
|
||||
@@ -5503,15 +5481,6 @@ dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shellexpand"
|
||||
version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb"
|
||||
dependencies = [
|
||||
"dirs 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
|
||||
+1
-3
@@ -7,7 +7,7 @@ license = "AGPL-3.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tokio = { version = "1.49", features = ["full"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
log = "0.4" # Logging facade
|
||||
@@ -30,8 +30,6 @@ ring = "0.17" # For signing fido2 messages with pin token
|
||||
# For Application UI:
|
||||
gpui = "0.2.2"
|
||||
gpui-component = "0.5.0"
|
||||
# Optional, for default bundled assets
|
||||
gpui-component-assets = "0.5.0"
|
||||
rust-embed = "8.11.0"
|
||||
|
||||
[profile.dev]
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
edition = "2024"
|
||||
hard_tabs = true
|
||||
hard_tabs = false
|
||||
tab_spaces = 4
|
||||
max_width = 100
|
||||
|
||||
+34
-34
@@ -1,44 +1,44 @@
|
||||
/// Custom error types for Pico Forge application.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum PFError {
|
||||
#[error("No device found")]
|
||||
NoDevice,
|
||||
#[error("PCSC Error: {0}")]
|
||||
Pcsc(#[from] pcsc::Error),
|
||||
#[error("IO/Hex Error: {0}")]
|
||||
Io(String),
|
||||
#[error("Device Error: {0}")]
|
||||
Device(String),
|
||||
#[error("No device found")]
|
||||
NoDevice,
|
||||
#[error("PCSC Error: {0}")]
|
||||
Pcsc(#[from] pcsc::Error),
|
||||
#[error("IO/Hex Error: {0}")]
|
||||
Io(String),
|
||||
#[error("Device Error: {0}")]
|
||||
Device(String),
|
||||
}
|
||||
|
||||
// Allow error to be serialized to string for Tauri
|
||||
impl serde::Serialize for PFError {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
use serde::ser::SerializeStruct;
|
||||
let mut state = serializer.serialize_struct("PFError", 2)?;
|
||||
match self {
|
||||
PFError::NoDevice => {
|
||||
state.serialize_field("type", "NoDevice")?;
|
||||
state.serialize_field("message", "No device found")?;
|
||||
}
|
||||
PFError::Pcsc(err) => {
|
||||
state.serialize_field("type", "Pcsc")?;
|
||||
state.serialize_field("message", &err.to_string())?;
|
||||
}
|
||||
PFError::Io(msg) => {
|
||||
state.serialize_field("type", "Io")?;
|
||||
state.serialize_field("message", msg)?;
|
||||
}
|
||||
PFError::Device(msg) => {
|
||||
state.serialize_field("type", "Device")?;
|
||||
state.serialize_field("message", msg)?;
|
||||
}
|
||||
}
|
||||
state.end()
|
||||
}
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
use serde::ser::SerializeStruct;
|
||||
let mut state = serializer.serialize_struct("PFError", 2)?;
|
||||
match self {
|
||||
PFError::NoDevice => {
|
||||
state.serialize_field("type", "NoDevice")?;
|
||||
state.serialize_field("message", "No device found")?;
|
||||
}
|
||||
PFError::Pcsc(err) => {
|
||||
state.serialize_field("type", "Pcsc")?;
|
||||
state.serialize_field("message", &err.to_string())?;
|
||||
}
|
||||
PFError::Io(msg) => {
|
||||
state.serialize_field("type", "Io")?;
|
||||
state.serialize_field("message", msg)?;
|
||||
}
|
||||
PFError::Device(msg) => {
|
||||
state.serialize_field("type", "Device")?;
|
||||
state.serialize_field("message", msg)?;
|
||||
}
|
||||
}
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
// pub type Result<T> = std::result::Result<T, PFError>;
|
||||
|
||||
+223
-223
File diff suppressed because it is too large
Load Diff
+434
-434
File diff suppressed because it is too large
Load Diff
+396
-396
File diff suppressed because it is too large
Load Diff
+26
-26
@@ -2,57 +2,57 @@
|
||||
use crate::{device::error::PFError, device::fido, device::rescue, device::types::*};
|
||||
|
||||
pub fn read_device_details() -> Result<FullDeviceStatus, PFError> {
|
||||
match rescue::read_device_details() {
|
||||
Ok(status) => Ok(status),
|
||||
Err(e) => {
|
||||
log::warn!("Rescue method failed: {}. Falling back to FIDO...", e);
|
||||
fido::read_device_details()
|
||||
}
|
||||
}
|
||||
match rescue::read_device_details() {
|
||||
Ok(status) => Ok(status),
|
||||
Err(e) => {
|
||||
log::warn!("Rescue method failed: {}. Falling back to FIDO...", e);
|
||||
fido::read_device_details()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_config(
|
||||
config: AppConfigInput,
|
||||
method: DeviceMethod,
|
||||
pin: Option<String>,
|
||||
config: AppConfigInput,
|
||||
method: DeviceMethod,
|
||||
pin: Option<String>,
|
||||
) -> Result<String, PFError> {
|
||||
if method == DeviceMethod::Fido {
|
||||
fido::write_config(config, pin)
|
||||
} else {
|
||||
rescue::write_config(config)
|
||||
}
|
||||
if method == DeviceMethod::Fido {
|
||||
fido::write_config(config, pin)
|
||||
} else {
|
||||
rescue::write_config(config)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable_secure_boot(lock: bool) -> Result<String, PFError> {
|
||||
rescue::enable_secure_boot(lock)
|
||||
rescue::enable_secure_boot(lock)
|
||||
}
|
||||
|
||||
pub(crate) fn get_fido_info() -> Result<FidoDeviceInfo, String> {
|
||||
fido::get_fido_info()
|
||||
fido::get_fido_info()
|
||||
}
|
||||
|
||||
pub(crate) fn change_fido_pin(
|
||||
current_pin: Option<String>,
|
||||
new_pin: String,
|
||||
current_pin: Option<String>,
|
||||
new_pin: String,
|
||||
) -> Result<String, String> {
|
||||
fido::change_fido_pin(current_pin, new_pin)
|
||||
fido::change_fido_pin(current_pin, new_pin)
|
||||
}
|
||||
|
||||
pub(crate) fn set_min_pin_length(
|
||||
current_pin: String,
|
||||
min_pin_length: u8,
|
||||
current_pin: String,
|
||||
min_pin_length: u8,
|
||||
) -> Result<String, String> {
|
||||
fido::set_min_pin_length(current_pin, min_pin_length)
|
||||
fido::set_min_pin_length(current_pin, min_pin_length)
|
||||
}
|
||||
|
||||
pub fn reboot(to_bootsel: bool) -> Result<String, PFError> {
|
||||
rescue::reboot_device(to_bootsel)
|
||||
rescue::reboot_device(to_bootsel)
|
||||
}
|
||||
|
||||
pub fn get_credentials(pin: String) -> Result<Vec<StoredCredential>, String> {
|
||||
fido::get_credentials(pin)
|
||||
fido::get_credentials(pin)
|
||||
}
|
||||
|
||||
pub fn delete_credential(pin: String, credential_id: String) -> Result<String, String> {
|
||||
fido::delete_credential(pin, credential_id)
|
||||
fido::delete_credential(pin, credential_id)
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
use directories::ProjectDirs;
|
||||
use log::LevelFilter;
|
||||
use log4rs::{
|
||||
append::{
|
||||
console::{ConsoleAppender, Target},
|
||||
rolling_file::{
|
||||
policy::compound::{
|
||||
roll::delete::DeleteRoller, trigger::size::SizeTrigger, CompoundPolicy,
|
||||
},
|
||||
RollingFileAppender,
|
||||
policy::compound::{
|
||||
CompoundPolicy, roll::delete::DeleteRoller, trigger::size::SizeTrigger,
|
||||
},
|
||||
},
|
||||
},
|
||||
config::{Appender, Logger, Root},
|
||||
encode::pattern::PatternEncoder,
|
||||
};
|
||||
use std::fs;
|
||||
use directories::ProjectDirs;
|
||||
|
||||
/// Initializes log4rs with custom configuration for stdout and file logging.
|
||||
pub fn logger_init() {
|
||||
|
||||
@@ -29,53 +29,53 @@ pub const RESCUE_AID: &[u8] = &[0xA0, 0x58, 0x3F, 0xC1, 0x9B, 0x7E, 0x4F, 0x21];
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum RescueInstruction {
|
||||
KeyDevSign = 0x10,
|
||||
Write = 0x1C,
|
||||
Secure = 0x1D,
|
||||
Read = 0x1E,
|
||||
Reboot = 0x1F,
|
||||
KeyDevSign = 0x10,
|
||||
Write = 0x1C,
|
||||
Secure = 0x1D,
|
||||
Read = 0x1E,
|
||||
Reboot = 0x1F,
|
||||
}
|
||||
|
||||
/// P1 Parameters for RescueInstruction::Read (0x1E)
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ReadParam {
|
||||
PhyConfig = 0x01,
|
||||
FlashInfo = 0x02,
|
||||
SecureBootStatus = 0x03,
|
||||
PhyConfig = 0x01,
|
||||
FlashInfo = 0x02,
|
||||
SecureBootStatus = 0x03,
|
||||
}
|
||||
|
||||
/// P1 Parameters for WRITE (0x1C)
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum WriteParam {
|
||||
PhyConfig = 0x01,
|
||||
PhyConfig = 0x01,
|
||||
}
|
||||
|
||||
/// P1 Parameters for RescueInstruction::KeyDevSign (0x10)
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum SignParam {
|
||||
SignData = 0x01,
|
||||
GetPublicKey = 0x02,
|
||||
UploadCert = 0x03,
|
||||
SignData = 0x01,
|
||||
GetPublicKey = 0x02,
|
||||
UploadCert = 0x03,
|
||||
}
|
||||
|
||||
/// P1 Parameters for RescueInstruction::Reboot (0x1F)
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum RebootParam {
|
||||
Normal = 0x00,
|
||||
Bootsel = 0x01,
|
||||
Normal = 0x00,
|
||||
Bootsel = 0x01,
|
||||
}
|
||||
|
||||
/// P2 Parameters for SECURE (0x1D)
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub enum SecureLockParam {
|
||||
#[default]
|
||||
Unlock = 0x00,
|
||||
Lock = 0x01,
|
||||
#[default]
|
||||
Unlock = 0x00,
|
||||
Lock = 0x01,
|
||||
}
|
||||
|
||||
/// Default P2 value when not used
|
||||
@@ -87,45 +87,45 @@ pub const P2_UNUSED: u8 = 0x00;
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum PhyTag {
|
||||
VidPid = 0x00,
|
||||
LedGpio = 0x04,
|
||||
LedBrightness = 0x05,
|
||||
Opts = 0x06,
|
||||
PresenceTimeout = 0x08, // Previously TAG_UP_BTN
|
||||
UsbProduct = 0x09,
|
||||
Curves = 0x0A,
|
||||
LedDriver = 0x0C,
|
||||
VidPid = 0x00,
|
||||
LedGpio = 0x04,
|
||||
LedBrightness = 0x05,
|
||||
Opts = 0x06,
|
||||
PresenceTimeout = 0x08, // Previously TAG_UP_BTN
|
||||
UsbProduct = 0x09,
|
||||
Curves = 0x0A,
|
||||
LedDriver = 0x0C,
|
||||
}
|
||||
|
||||
impl PhyTag {
|
||||
/// Helper to convert raw u8 from device back to Enum
|
||||
pub fn from_u8(val: u8) -> Option<Self> {
|
||||
match val {
|
||||
0x00 => Some(Self::VidPid),
|
||||
0x04 => Some(Self::LedGpio),
|
||||
0x05 => Some(Self::LedBrightness),
|
||||
0x06 => Some(Self::Opts),
|
||||
0x08 => Some(Self::PresenceTimeout),
|
||||
0x09 => Some(Self::UsbProduct),
|
||||
0x0A => Some(Self::Curves),
|
||||
0x0C => Some(Self::LedDriver),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
/// Helper to convert raw u8 from device back to Enum
|
||||
pub fn from_u8(val: u8) -> Option<Self> {
|
||||
match val {
|
||||
0x00 => Some(Self::VidPid),
|
||||
0x04 => Some(Self::LedGpio),
|
||||
0x05 => Some(Self::LedBrightness),
|
||||
0x06 => Some(Self::Opts),
|
||||
0x08 => Some(Self::PresenceTimeout),
|
||||
0x09 => Some(Self::UsbProduct),
|
||||
0x0A => Some(Self::Curves),
|
||||
0x0C => Some(Self::LedDriver),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// Configuration options for TAG_OPTS (Tag 0x06)
|
||||
pub struct RescueOptions: u16 {
|
||||
const LED_DIMMABLE = 0x02;
|
||||
const DISABLE_POWER_RESET = 0x04;
|
||||
const LED_STEADY = 0x08;
|
||||
}
|
||||
/// Configuration options for TAG_OPTS (Tag 0x06)
|
||||
pub struct RescueOptions: u16 {
|
||||
const LED_DIMMABLE = 0x02;
|
||||
const DISABLE_POWER_RESET = 0x04;
|
||||
const LED_STEADY = 0x08;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// Enabled curves for TAG_CURVES (Tag 0x0A)
|
||||
pub struct RescueCurves: u32 {
|
||||
const SECP256K1 = 0x08;
|
||||
}
|
||||
/// Enabled curves for TAG_CURVES (Tag 0x0A)
|
||||
pub struct RescueCurves: u32 {
|
||||
const SECP256K1 = 0x08;
|
||||
}
|
||||
}
|
||||
|
||||
+342
-342
File diff suppressed because it is too large
Load Diff
+51
-51
@@ -3,66 +3,66 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
struct PForgeState {
|
||||
device_info: DeviceInfo,
|
||||
device_info: DeviceInfo,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DeviceInfo {
|
||||
pub serial: String,
|
||||
pub flash_used: u32,
|
||||
pub flash_total: u32,
|
||||
pub firmware_version: String,
|
||||
pub serial: String,
|
||||
pub flash_used: u32,
|
||||
pub flash_total: u32,
|
||||
pub firmware_version: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AppConfig {
|
||||
pub vid: String,
|
||||
pub pid: String,
|
||||
pub product_name: String,
|
||||
pub led_gpio: u8,
|
||||
pub led_brightness: u8,
|
||||
pub touch_timeout: u8,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub led_driver: Option<u8>,
|
||||
pub led_dimmable: bool,
|
||||
pub power_cycle_on_reset: bool,
|
||||
pub led_steady: bool,
|
||||
pub enable_secp256k1: bool,
|
||||
pub vid: String,
|
||||
pub pid: String,
|
||||
pub product_name: String,
|
||||
pub led_gpio: u8,
|
||||
pub led_brightness: u8,
|
||||
pub touch_timeout: u8,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub led_driver: Option<u8>,
|
||||
pub led_dimmable: bool,
|
||||
pub power_cycle_on_reset: bool,
|
||||
pub led_steady: bool,
|
||||
pub enable_secp256k1: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AppConfigInput {
|
||||
pub vid: Option<String>,
|
||||
pub pid: Option<String>,
|
||||
pub product_name: Option<String>,
|
||||
pub led_gpio: Option<u8>,
|
||||
pub led_brightness: Option<u8>,
|
||||
pub touch_timeout: Option<u8>,
|
||||
pub led_driver: Option<u8>,
|
||||
pub led_dimmable: Option<bool>,
|
||||
pub power_cycle_on_reset: Option<bool>,
|
||||
pub led_steady: Option<bool>,
|
||||
pub enable_secp256k1: Option<bool>,
|
||||
pub vid: Option<String>,
|
||||
pub pid: Option<String>,
|
||||
pub product_name: Option<String>,
|
||||
pub led_gpio: Option<u8>,
|
||||
pub led_brightness: Option<u8>,
|
||||
pub touch_timeout: Option<u8>,
|
||||
pub led_driver: Option<u8>,
|
||||
pub led_dimmable: Option<bool>,
|
||||
pub power_cycle_on_reset: Option<bool>,
|
||||
pub led_steady: Option<bool>,
|
||||
pub enable_secp256k1: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FullDeviceStatus {
|
||||
pub info: DeviceInfo,
|
||||
pub config: AppConfig,
|
||||
pub secure_boot: bool,
|
||||
pub secure_lock: bool,
|
||||
pub method: DeviceMethod,
|
||||
pub info: DeviceInfo,
|
||||
pub config: AppConfig,
|
||||
pub secure_boot: bool,
|
||||
pub secure_lock: bool,
|
||||
pub method: DeviceMethod,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
||||
pub enum DeviceMethod {
|
||||
#[serde(rename = "FIDO")]
|
||||
Fido,
|
||||
Rescue,
|
||||
#[serde(rename = "FIDO")]
|
||||
Fido,
|
||||
Rescue,
|
||||
}
|
||||
|
||||
// Fido stuff:
|
||||
@@ -70,24 +70,24 @@ pub enum DeviceMethod {
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FidoDeviceInfo {
|
||||
pub versions: Vec<String>,
|
||||
pub extensions: Vec<String>,
|
||||
pub aaguid: String,
|
||||
pub options: std::collections::HashMap<String, bool>,
|
||||
pub max_msg_size: i32,
|
||||
pub pin_protocols: Vec<u32>,
|
||||
// pub remaining_disc_creds: u32,
|
||||
pub min_pin_length: u32,
|
||||
pub firmware_version: String,
|
||||
pub versions: Vec<String>,
|
||||
pub extensions: Vec<String>,
|
||||
pub aaguid: String,
|
||||
pub options: std::collections::HashMap<String, bool>,
|
||||
pub max_msg_size: i32,
|
||||
pub pin_protocols: Vec<u32>,
|
||||
// pub remaining_disc_creds: u32,
|
||||
pub min_pin_length: u32,
|
||||
pub firmware_version: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct StoredCredential {
|
||||
pub rp_id: String,
|
||||
pub rp_name: String,
|
||||
pub user_name: String,
|
||||
pub user_display_name: String,
|
||||
pub user_id: String,
|
||||
pub credential_id: String,
|
||||
pub rp_id: String,
|
||||
pub rp_name: String,
|
||||
pub user_name: String,
|
||||
pub user_display_name: String,
|
||||
pub user_id: String,
|
||||
pub credential_id: String,
|
||||
}
|
||||
|
||||
+44
-47
@@ -2,69 +2,66 @@ use gpui::*;
|
||||
use gpui_component::Root;
|
||||
use gpui_component::{Theme, ThemeMode};
|
||||
use ui::rootview::ApplicationRoot;
|
||||
// use crate::ui::assets::Assets;
|
||||
|
||||
mod device;
|
||||
mod ui;
|
||||
|
||||
fn main() {
|
||||
// TODO: Configure and add custom assets.
|
||||
// let app = Application::new().with_assets(gpui_component_assets::Assets);
|
||||
let app = Application::new().with_assets(ui::assets::Assets);
|
||||
let app = Application::new().with_assets(ui::assets::Assets);
|
||||
|
||||
app.run(move |cx| {
|
||||
gpui_component::init(cx);
|
||||
Theme::change(ThemeMode::Dark, None, cx);
|
||||
// Theme::change(ThemeMode::Dark, Some(ui::theme::dark_theme()), cx);
|
||||
app.run(move |cx| {
|
||||
gpui_component::init(cx);
|
||||
Theme::change(ThemeMode::Dark, None, cx);
|
||||
// Theme::change(ThemeMode::Dark, Some(ui::theme::dark_theme()), cx);
|
||||
|
||||
cx.activate(true);
|
||||
cx.activate(true);
|
||||
|
||||
let mut window_size = size(px(1280.0), px(720.0));
|
||||
let mut window_size = size(px(1280.0), px(720.0));
|
||||
|
||||
// Basically, make sure that the window is max to max 85 percent size of the actual monitor/display,
|
||||
// so the window does not get too big on small monitors.
|
||||
if let Some(display) = cx.primary_display() {
|
||||
let display_size = display.bounds().size;
|
||||
// Basically, make sure that the window is max to max 85 percent size of the actual
|
||||
// monitor/display, so the window does not get too big on small monitors.
|
||||
if let Some(display) = cx.primary_display() {
|
||||
let display_size = display.bounds().size;
|
||||
|
||||
window_size.width = window_size.width.min(display_size.width * 0.85);
|
||||
window_size.height = window_size.height.min(display_size.height * 0.85);
|
||||
}
|
||||
window_size.width = window_size.width.min(display_size.width * 0.85);
|
||||
window_size.height = window_size.height.min(display_size.height * 0.85);
|
||||
}
|
||||
|
||||
let window_bounds = Bounds::centered(None, window_size, cx);
|
||||
let window_bounds = Bounds::centered(None, window_size, cx);
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
let window_options = WindowOptions {
|
||||
app_id: Some("in.suyogtandel.picoforge".into()),
|
||||
cx.spawn(async move |cx| {
|
||||
let window_options = WindowOptions {
|
||||
app_id: Some("in.suyogtandel.picoforge".into()),
|
||||
|
||||
window_bounds: Some(WindowBounds::Windowed(window_bounds)),
|
||||
window_bounds: Some(WindowBounds::Windowed(window_bounds)),
|
||||
|
||||
titlebar: Some(TitlebarOptions {
|
||||
title: Some("PicoForge".into()),
|
||||
appears_transparent: true,
|
||||
// TODO: This option needs to be tested and adjusted on macos
|
||||
traffic_light_position: Some(gpui::point(px(12.0), px(12.0))),
|
||||
}),
|
||||
titlebar: Some(TitlebarOptions {
|
||||
title: Some("PicoForge".into()),
|
||||
appears_transparent: true,
|
||||
// TODO: This option needs to be tested and adjusted on macos
|
||||
traffic_light_position: Some(gpui::point(px(12.0), px(12.0))),
|
||||
}),
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
window_background: gpui::WindowBackgroundAppearance::Transparent,
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
window_decorations: Some(gpui::WindowDecorations::Client),
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
window_background: gpui::WindowBackgroundAppearance::Transparent,
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
window_decorations: Some(gpui::WindowDecorations::Client),
|
||||
|
||||
window_min_size: Some(gpui::Size {
|
||||
width: px(650.),
|
||||
height: px(300.),
|
||||
}),
|
||||
kind: WindowKind::Normal,
|
||||
..Default::default()
|
||||
};
|
||||
window_min_size: Some(gpui::Size {
|
||||
width: px(650.),
|
||||
height: px(300.),
|
||||
}),
|
||||
kind: WindowKind::Normal,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
cx.open_window(window_options, |window, cx| {
|
||||
let view = cx.new(|_| ApplicationRoot::new());
|
||||
cx.new(|cx| Root::new(view, window, cx))
|
||||
})?;
|
||||
cx.open_window(window_options, |window, cx| {
|
||||
let view = cx.new(|_| ApplicationRoot::new());
|
||||
cx.new(|cx| Root::new(view, window, cx))
|
||||
})?;
|
||||
|
||||
Ok::<_, anyhow::Error>(())
|
||||
})
|
||||
.detach();
|
||||
});
|
||||
Ok::<_, anyhow::Error>(())
|
||||
})
|
||||
.detach();
|
||||
});
|
||||
}
|
||||
|
||||
+13
-13
@@ -11,19 +11,19 @@ use std::borrow::Cow;
|
||||
pub struct Assets;
|
||||
|
||||
impl AssetSource for Assets {
|
||||
fn load(&self, path: &str) -> Result<Option<Cow<'static, [u8]>>> {
|
||||
if path.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
fn load(&self, path: &str) -> Result<Option<Cow<'static, [u8]>>> {
|
||||
if path.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
Self::get(path)
|
||||
.map(|f| Some(f.data))
|
||||
.ok_or_else(|| anyhow!("could not find asset at path \"{path}\""))
|
||||
}
|
||||
Self::get(path)
|
||||
.map(|f| Some(f.data))
|
||||
.ok_or_else(|| anyhow!("could not find asset at path \"{path}\""))
|
||||
}
|
||||
|
||||
fn list(&self, path: &str) -> Result<Vec<SharedString>> {
|
||||
Ok(Self::iter()
|
||||
.filter_map(|p| p.starts_with(path).then(|| p.into()))
|
||||
.collect())
|
||||
}
|
||||
fn list(&self, path: &str) -> Result<Vec<SharedString>> {
|
||||
Ok(Self::iter()
|
||||
.filter_map(|p| p.starts_with(path).then(|| p.into()))
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
pub mod views;
|
||||
pub mod assets;
|
||||
pub mod rootview;
|
||||
pub mod colors;
|
||||
pub mod rootview;
|
||||
pub mod views;
|
||||
|
||||
+122
-122
@@ -1,141 +1,141 @@
|
||||
use crate::ui::colors;
|
||||
use crate::ui::views::{
|
||||
about::AboutView, config::ConfigView, home::HomeView, logs::LogsView, passkeys::PasskeysView,
|
||||
security::SecurityView,
|
||||
about::AboutView, config::ConfigView, home::HomeView, logs::LogsView, passkeys::PasskeysView,
|
||||
security::SecurityView,
|
||||
};
|
||||
use gpui::*;
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::scroll::ScrollableElement;
|
||||
use gpui_component::{ActiveTheme, Icon, IconName, TitleBar, h_flex, v_flex};
|
||||
use gpui_component::{ActiveTheme, Icon, IconName, StyledExt, TitleBar, h_flex, v_flex};
|
||||
use gpui_component::{Side, sidebar::*};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum ActiveView {
|
||||
Home,
|
||||
Passkeys,
|
||||
Configuration,
|
||||
Security,
|
||||
Logs,
|
||||
About,
|
||||
Home,
|
||||
Passkeys,
|
||||
Configuration,
|
||||
Security,
|
||||
Logs,
|
||||
About,
|
||||
}
|
||||
|
||||
pub struct ApplicationRoot {
|
||||
active_view: ActiveView,
|
||||
collapsed: bool,
|
||||
active_view: ActiveView,
|
||||
collapsed: bool,
|
||||
}
|
||||
|
||||
impl ApplicationRoot {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
active_view: ActiveView::Home,
|
||||
collapsed: false,
|
||||
}
|
||||
}
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
active_view: ActiveView::Home,
|
||||
collapsed: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ApplicationRoot {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
h_flex()
|
||||
.size_full()
|
||||
.child(
|
||||
Sidebar::new(Side::Left)
|
||||
.collapsed(self.collapsed)
|
||||
.collapsible(true)
|
||||
.h_full()
|
||||
.bg(rgb(0x18181b))
|
||||
// .header(SidebarHeader::new().child("PicoForge"))
|
||||
.child(
|
||||
SidebarGroup::new("Menu").child(
|
||||
SidebarMenu::new()
|
||||
.child(
|
||||
SidebarMenuItem::new("Home")
|
||||
.icon(Icon::default().path("icons/house.svg"))
|
||||
.active(self.active_view == ActiveView::Home)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::Home;
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
SidebarMenuItem::new("Passkeys")
|
||||
.icon(Icon::default().path("icons/key-round.svg"))
|
||||
.active(self.active_view == ActiveView::Passkeys)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::Passkeys;
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
SidebarMenuItem::new("Configuration")
|
||||
.icon(Icon::default().path("icons/settings.svg"))
|
||||
.active(self.active_view == ActiveView::Configuration)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::Configuration;
|
||||
})),
|
||||
)
|
||||
// TODO: Replace these icons with correct ones from lucide
|
||||
.child(
|
||||
SidebarMenuItem::new("Security")
|
||||
.icon(Icon::default().path("icons/shield-check.svg"))
|
||||
.active(self.active_view == ActiveView::Security)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::Security;
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
SidebarMenuItem::new("Logs")
|
||||
.icon(Icon::default().path("icons/scroll-text.svg"))
|
||||
.active(self.active_view == ActiveView::Logs)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::Logs;
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
SidebarMenuItem::new("About")
|
||||
.icon(Icon::default().path("icons/shield-check.svg"))
|
||||
.active(self.active_view == ActiveView::About)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::About;
|
||||
})),
|
||||
),
|
||||
),
|
||||
), // .footer(SidebarFooter::new().child("Device Status")),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
.size_full()
|
||||
.child(
|
||||
TitleBar::new().child(
|
||||
h_flex()
|
||||
.w_full()
|
||||
.justify_between()
|
||||
// .px_4()
|
||||
.items_center()
|
||||
.cursor(gpui::CursorStyle::OpenHand)
|
||||
.child(
|
||||
Button::new("sidebar_toggle")
|
||||
.ghost()
|
||||
.icon(IconName::PanelLeft)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.collapsed = !this.collapsed;
|
||||
}))
|
||||
.tooltip("Toggle Sidebar"),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
.min_h(px(0.))
|
||||
.min_w(px(0.))
|
||||
.overflow_y_scrollbar()
|
||||
.flex_grow()
|
||||
.bg(cx.theme().background)
|
||||
.child(match self.active_view {
|
||||
ActiveView::Home => HomeView::build(cx.theme()).into_any_element(),
|
||||
ActiveView::Passkeys => PasskeysView::build().into_any_element(),
|
||||
ActiveView::Configuration => ConfigView::build().into_any_element(),
|
||||
ActiveView::Security => SecurityView::build().into_any_element(),
|
||||
ActiveView::Logs => LogsView::build().into_any_element(),
|
||||
ActiveView::About => AboutView::build().into_any_element(),
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
h_flex()
|
||||
.size_full()
|
||||
.child(
|
||||
Sidebar::new(Side::Left)
|
||||
.collapsed(self.collapsed)
|
||||
.collapsible(true)
|
||||
.h_full()
|
||||
.bg(rgb(0x18181b))
|
||||
.child(
|
||||
SidebarGroup::new("Menu").child(
|
||||
SidebarMenu::new()
|
||||
.child(
|
||||
SidebarMenuItem::new("Home")
|
||||
.icon(Icon::default().path("icons/house.svg"))
|
||||
.active(self.active_view == ActiveView::Home)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::Home;
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
SidebarMenuItem::new("Passkeys")
|
||||
.icon(Icon::default().path("icons/key-round.svg"))
|
||||
.active(self.active_view == ActiveView::Passkeys)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::Passkeys;
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
SidebarMenuItem::new("Configuration")
|
||||
.icon(Icon::default().path("icons/settings.svg"))
|
||||
.active(self.active_view == ActiveView::Configuration)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::Configuration;
|
||||
})),
|
||||
)
|
||||
// TODO: Replace these icons with correct ones from lucide
|
||||
.child(
|
||||
SidebarMenuItem::new("Security")
|
||||
.icon(Icon::default().path("icons/shield-check.svg"))
|
||||
.active(self.active_view == ActiveView::Security)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::Security;
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
SidebarMenuItem::new("Logs")
|
||||
.icon(Icon::default().path("icons/scroll-text.svg"))
|
||||
.active(self.active_view == ActiveView::Logs)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::Logs;
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
SidebarMenuItem::new("About")
|
||||
.icon(IconName::Info)
|
||||
.active(self.active_view == ActiveView::About)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.active_view = ActiveView::About;
|
||||
})),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
.size_full()
|
||||
.child(
|
||||
TitleBar::new().bg(rgba(colors::zinc::ZINC900)).child(
|
||||
h_flex()
|
||||
.w_full()
|
||||
.justify_between()
|
||||
.bg(rgba(colors::zinc::ZINC900))
|
||||
.items_center()
|
||||
.cursor(gpui::CursorStyle::OpenHand)
|
||||
.child(
|
||||
Button::new("sidebar_toggle")
|
||||
.ghost()
|
||||
.icon(IconName::PanelLeft)
|
||||
.on_click(cx.listener(|this, _, _, _| {
|
||||
this.collapsed = !this.collapsed;
|
||||
}))
|
||||
.tooltip("Toggle Sidebar"),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
.min_h(px(0.))
|
||||
.min_w(px(0.))
|
||||
.overflow_y_scrollbar()
|
||||
.flex_grow()
|
||||
.bg(cx.theme().background)
|
||||
.child(match self.active_view {
|
||||
ActiveView::Home => HomeView::build(cx.theme()).into_any_element(),
|
||||
ActiveView::Passkeys => PasskeysView::build().into_any_element(),
|
||||
ActiveView::Configuration => ConfigView::build().into_any_element(),
|
||||
ActiveView::Security => SecurityView::build().into_any_element(),
|
||||
ActiveView::Logs => LogsView::build().into_any_element(),
|
||||
ActiveView::About => AboutView::build().into_any_element(),
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use gpui::*;
|
||||
pub struct AboutView;
|
||||
|
||||
impl AboutView {
|
||||
pub fn build() -> impl IntoElement {
|
||||
div().size_full().p_8().child("About goes here...")
|
||||
}
|
||||
pub fn build() -> impl IntoElement {
|
||||
div().size_full().p_8().child("About goes here...")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ use gpui::*;
|
||||
pub struct ConfigView;
|
||||
|
||||
impl ConfigView {
|
||||
pub fn build() -> impl IntoElement {
|
||||
div()
|
||||
.size_full()
|
||||
.p_8()
|
||||
.child("Passkey Management List goes here...")
|
||||
}
|
||||
pub fn build() -> impl IntoElement {
|
||||
div()
|
||||
.size_full()
|
||||
.p_8()
|
||||
.child("Passkey Management List goes here...")
|
||||
}
|
||||
}
|
||||
|
||||
+481
-481
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@ use gpui::*;
|
||||
pub struct LogsView;
|
||||
|
||||
impl LogsView {
|
||||
pub fn build() -> impl IntoElement {
|
||||
div().size_full().p_8().child("Logs goes here...")
|
||||
}
|
||||
pub fn build() -> impl IntoElement {
|
||||
div().size_full().p_8().child("Logs goes here...")
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user