Add API key generator application with Slint UI
This commit is contained in:
+16
@@ -0,0 +1,16 @@
|
||||
# Rust
|
||||
/target/
|
||||
**/*.rs.bk
|
||||
*.pdb
|
||||
Cargo.lock
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "rpc"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
slint = "1.8"
|
||||
|
||||
[build-dependencies]
|
||||
slint-build = "1.8"
|
||||
+85
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user