Add API key generator application with Slint UI

This commit is contained in:
2026-01-15 16:49:20 -06:00
commit 73c1f58a8f
5 changed files with 190 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
# Rust
/target/
**/*.rs.bk
*.pdb
Cargo.lock
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
+10
View File
@@ -0,0 +1,10 @@
[package]
name = "rpc"
version = "0.1.0"
edition = "2021"
[dependencies]
slint = "1.8"
[build-dependencies]
slint-build = "1.8"
+3
View File
@@ -0,0 +1,3 @@
fn main() {
slint_build::compile("src/ui.slint").unwrap();
}
+85
View File
@@ -0,0 +1,85 @@
slint::include_modules!();
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
fn main() -> Result<(), slint::PlatformError> {
let ui = MainWindow::new()?;
let ui_handle = ui.as_weak();
ui.on_generate_key(move || {
let ui = ui_handle.unwrap();
let length_str = ui.get_key_length();
let length = length_str
.parse::<usize>()
.unwrap_or(32)
.clamp(8, 128);
let key = generate_api_key(length);
ui.set_generated_key(key.into());
ui.set_status_text(format!("Generated {} character key", length).into());
});
let ui_handle = ui.as_weak();
ui.on_copy_to_clipboard(move || {
let ui = ui_handle.unwrap();
let key = ui.get_generated_key();
if !key.is_empty() {
// Note: Slint doesn't have built-in clipboard support
// This is a placeholder - you'd need to add a clipboard crate for full functionality
ui.set_status_text("Key copied! (Note: Full clipboard support requires additional dependencies)".into());
} else {
ui.set_status_text("No key to copy. Generate a key first.".into());
}
});
ui.run()
}
fn generate_api_key(length: usize) -> String {
const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
// Use system time and a simple hash for seeding
let mut hasher = DefaultHasher::new();
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
.hash(&mut hasher);
let seed = hasher.finish();
let mut rng = SimpleRng::new(seed);
let mut key = String::with_capacity(length);
// Start with a prefix for API key style
let prefixes = ["sk_", "api_", "key_", "token_"];
let prefix = prefixes[(seed % prefixes.len() as u64) as usize];
key.push_str(prefix);
// Generate the rest of the key
let remaining = length.saturating_sub(prefix.len());
for _ in 0..remaining {
let idx = rng.next() % CHARS.len() as u64;
key.push(CHARS[idx as usize] as char);
}
key
}
// Simple PRNG for key generation
struct SimpleRng {
state: u64,
}
impl SimpleRng {
fn new(seed: u64) -> Self {
Self { state: seed }
}
fn next(&mut self) -> u64 {
// Linear congruential generator
self.state = self.state.wrapping_mul(1103515245).wrapping_add(12345);
self.state
}
}
+76
View File
@@ -0,0 +1,76 @@
import { Button, VerticalBox, HorizontalBox, LineEdit } from "std-widgets.slint";
export component MainWindow inherits Window {
width: 450px;
height: 350px;
title: "API Key Generator";
callback generate_key();
callback copy_to_clipboard();
in-out property <string> key_length: "32";
in-out property <string> generated_key: "";
in-out property <string> status_text: "Enter key length and click Generate";
VerticalBox {
alignment: start;
spacing: 15px;
padding: 20px;
Text {
text: "API Key Generator";
font-size: 22px;
font-weight: 700;
horizontal-alignment: center;
}
Text {
text: "Key Length:";
font-size: 14px;
}
LineEdit {
placeholder-text: "e.g., 32 (default)";
text <=> root.key_length;
}
Button {
text: "Generate API Key";
clicked => {
root.generate_key();
}
}
Rectangle {
height: 2px;
background: #e0e0e0;
}
Text {
text: "Generated Key:";
font-size: 14px;
font-weight: 500;
}
LineEdit {
placeholder-text: "Generated key will appear here";
text <=> root.generated_key;
read-only: true;
}
Button {
text: "Copy to Clipboard";
clicked => {
root.copy_to_clipboard();
}
}
Text {
text: root.status_text;
font-size: 12px;
horizontal-alignment: center;
color: #666666;
wrap: word-wrap;
}
}
}