rename app

This commit is contained in:
2026-08-31 15:36:36 +08:00
parent 78eb5c773c
commit 4e80a081e9
30 changed files with 1593 additions and 449 deletions
Generated
+57 -57
View File
@@ -1323,6 +1323,63 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "friendolls"
version = "0.1.0"
dependencies = [
"base64 0.22.1",
"device_query",
"ed25519-dalek",
"friendolls-common",
"futures-util",
"getrandom 0.4.3",
"image",
"lazy_static",
"objc2",
"objc2-app-kit",
"objc2-foundation",
"serde",
"serde_json",
"sha2 0.10.9",
"specta",
"specta-typescript",
"sqlx",
"tauri",
"tauri-build",
"tauri-plugin-dialog",
"tauri-plugin-opener",
"tauri-specta",
"tokio",
"tokio-tungstenite 0.28.0",
"uuid",
"webp",
"windows 0.58.0",
]
[[package]]
name = "friendolls-common"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
"specta",
]
[[package]]
name = "friendolls-server"
version = "0.1.0"
dependencies = [
"axum",
"base64 0.22.1",
"ed25519-dalek",
"friendolls-common",
"futures-util",
"image",
"serde_json",
"tokio",
"uuid",
]
[[package]]
name = "futures-channel"
version = "0.3.32"
@@ -6264,63 +6321,6 @@ dependencies = [
"x11-dl",
]
[[package]]
name = "wyd"
version = "0.1.0"
dependencies = [
"base64 0.22.1",
"device_query",
"ed25519-dalek",
"futures-util",
"getrandom 0.4.3",
"image",
"lazy_static",
"objc2",
"objc2-app-kit",
"objc2-foundation",
"serde",
"serde_json",
"sha2 0.10.9",
"specta",
"specta-typescript",
"sqlx",
"tauri",
"tauri-build",
"tauri-plugin-dialog",
"tauri-plugin-opener",
"tauri-specta",
"tokio",
"tokio-tungstenite 0.28.0",
"uuid",
"webp",
"windows 0.58.0",
"wyd-common",
]
[[package]]
name = "wyd-common"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
"specta",
]
[[package]]
name = "wyd-server"
version = "0.1.0"
dependencies = [
"axum",
"base64 0.22.1",
"ed25519-dalek",
"futures-util",
"image",
"serde_json",
"tokio",
"uuid",
"wyd-common",
]
[[package]]
name = "x11"
version = "2.21.0"
+1479 -337
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "wyd",
"name": "friendolls",
"version": "0.1.0",
"description": "",
"type": "module",
+1 -1
View File
@@ -1,5 +1,5 @@
[package]
name = "wyd-common"
name = "friendolls-common"
version = "0.1.0"
edition = "2024"
publish = false
+5 -5
View File
@@ -170,7 +170,7 @@ pub enum ServerMessage {
pub fn register_bytes(challenge: &str, profile: &Profile, friends: &[String]) -> Vec<u8> {
format!(
"wyd-register-v{VERSION}\n{challenge}\n{}\n{}\n{}\n{}",
"friendolls-register-v{VERSION}\n{challenge}\n{}\n{}\n{}\n{}",
profile.id,
profile.display_name,
profile.skin_hash.as_deref().unwrap_or(""),
@@ -180,11 +180,11 @@ pub fn register_bytes(challenge: &str, profile: &Profile, friends: &[String]) ->
}
pub fn message_bytes(payload: &str) -> Vec<u8> {
format!("wyd-message-v{VERSION}\n{payload}").into_bytes()
format!("friendolls-message-v{VERSION}\n{payload}").into_bytes()
}
pub fn interaction_bytes(interaction_id: &str, recipient_id: &str, payload: &str) -> Vec<u8> {
let mut bytes = format!("wyd-interaction-v{VERSION}\0").into_bytes();
let mut bytes = format!("friendolls-interaction-v{VERSION}\0").into_bytes();
for value in [
interaction_id.as_bytes(),
recipient_id.as_bytes(),
@@ -198,7 +198,7 @@ pub fn interaction_bytes(interaction_id: &str, recipient_id: &str, payload: &str
pub fn profile_bytes(profile: &Profile) -> Vec<u8> {
format!(
"wyd-profile-v{VERSION}\n{}\n{}\n{}",
"friendolls-profile-v{VERSION}\n{}\n{}\n{}",
profile.id,
profile.display_name,
profile.skin_hash.as_deref().unwrap_or("")
@@ -207,7 +207,7 @@ pub fn profile_bytes(profile: &Profile) -> Vec<u8> {
}
pub fn friends_bytes(friends: &[String]) -> Vec<u8> {
format!("wyd-friends-v{VERSION}\n{}", friends.join("\n")).into_bytes()
format!("friendolls-friends-v{VERSION}\n{}", friends.join("\n")).into_bytes()
}
#[cfg(test)]
+2 -2
View File
@@ -1,5 +1,5 @@
[package]
name = "wyd-server"
name = "friendolls-server"
version = "0.1.0"
edition = "2024"
publish = false
@@ -13,4 +13,4 @@ futures-util = "0.3"
image = { version = "0.25", default-features = false, features = ["jpeg", "webp"] }
serde_json = "1"
uuid = { version = "1", features = ["v4"] }
wyd-common = { path = "../src-common" }
friendolls-common = { path = "../src-common" }
+1 -1
View File
@@ -12,7 +12,7 @@ async fn main() -> std::io::Result<()> {
.merge(network::routes())
.fallback((StatusCode::NOT_FOUND, "not found"));
println!("wyd-server listening on http://{bind_addr}");
println!("friendolls-server listening on http://{bind_addr}");
axum::serve(listener, app).await
}
+2 -2
View File
@@ -5,7 +5,7 @@ use base64::Engine;
use base64::engine::general_purpose::STANDARD;
use tokio::sync::mpsc;
use uuid::Uuid;
use wyd_common::{
use friendolls_common::{
InteractionContent, InteractionDeliveryStatus, MAX_IMAGE_DIMENSION,
MAX_INTERACTION_PAYLOAD_BYTES, ServerMessage, interaction_bytes,
};
@@ -102,7 +102,7 @@ mod tests {
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use ed25519_dalek::{Signer, SigningKey};
use image::{Rgb, RgbImage};
use wyd_common::{MAX_TEXT_CHARS, Profile};
use friendolls_common::{MAX_TEXT_CHARS, Profile};
use super::*;
use crate::network::Client;
+4 -4
View File
@@ -10,10 +10,10 @@ use axum::routing::get;
use base64::Engine;
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use ed25519_dalek::{Signature, Verifier, VerifyingKey};
use friendolls_common::{ClientMessage, Profile, ServerMessage, message_bytes, register_bytes};
use futures_util::{SinkExt, StreamExt};
use tokio::sync::{Mutex, mpsc};
use uuid::Uuid;
use wyd_common::{ClientMessage, Profile, ServerMessage, message_bytes, register_bytes};
mod interactions;
mod presence;
@@ -50,7 +50,7 @@ async fn connected(mut socket: WebSocket, clients: Clients) {
if send(
&mut socket,
&ServerMessage::Challenge {
version: wyd_common::VERSION,
version: friendolls_common::VERSION,
challenge: challenge.clone(),
},
)
@@ -74,7 +74,7 @@ async fn connected(mut socket: WebSocket, clients: Clients) {
if profile
.skin_hash
.as_deref()
.is_some_and(|hash| !wyd_common::is_skin_hash(hash))
.is_some_and(|hash| !friendolls_common::is_skin_hash(hash))
{
return;
}
@@ -335,7 +335,7 @@ fn verify(key: &VerifyingKey, bytes: &[u8], signature: &str) -> bool {
#[cfg(test)]
mod tests {
use ed25519_dalek::{Signer, SigningKey};
use wyd_common::friends_bytes;
use friendolls_common::friends_bytes;
use super::*;
+1 -1
View File
@@ -1,7 +1,7 @@
use axum::extract::ws::Message;
use friendolls_common::{ServerMessage, friends_bytes};
use tokio::sync::mpsc;
use uuid::Uuid;
use wyd_common::{ServerMessage, friends_bytes};
use super::{Clients, are_mutual_friends, verify};
+2 -2
View File
@@ -1,7 +1,7 @@
use axum::extract::ws::Message;
use tokio::sync::mpsc;
use uuid::Uuid;
use wyd_common::{Profile, ServerMessage, profile_bytes};
use friendolls_common::{Profile, ServerMessage, profile_bytes};
use super::{Client, Clients, verify};
@@ -23,7 +23,7 @@ pub(super) async fn update(
|| profile
.skin_hash
.as_deref()
.is_some_and(|hash| !wyd_common::is_skin_hash(hash))
.is_some_and(|hash| !friendolls_common::is_skin_hash(hash))
|| !verify(&client.key, &profile_bytes(&profile), signature)
{
return false;
+2 -2
View File
@@ -1,6 +1,6 @@
use axum::extract::ws::Message;
use friendolls_common::{MAX_SKIN_B64_SIZE, ServerMessage};
use uuid::Uuid;
use wyd_common::{MAX_SKIN_B64_SIZE, ServerMessage};
use super::{Clients, are_mutual_friends};
@@ -110,8 +110,8 @@ mod tests {
use base64::Engine;
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use ed25519_dalek::SigningKey;
use friendolls_common::Profile;
use tokio::sync::mpsc;
use wyd_common::Profile;
use super::*;
use crate::network::Client;
+3 -3
View File
@@ -1,5 +1,5 @@
[package]
name = "wyd"
name = "friendolls"
version = "0.1.0"
description = "A Tauri App"
authors = ["you"]
@@ -11,7 +11,7 @@ edition = "2024"
# The `_lib` suffix may seem redundant but it is necessary
# to make the lib name unique and wouldn't conflict with the bin name.
# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
name = "wyd_lib"
name = "friendolls_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
@@ -39,7 +39,7 @@ specta = "2.0.0-rc.21"
specta-typescript = { version = "0.0.9" }
uuid = { version = "1", features = ["v4"] }
webp = { version = "0.3.1", default-features = false }
wyd-common = { path = "../src-common" }
friendolls-common = { path = "../src-common" }
[dev-dependencies]
tokio = { version = "1.53.1", features = ["macros", "rt-multi-thread"] }
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Capability for Wyd UI windows",
"description": "Capability for Friendolls UI windows",
"windows": ["control-panel", "control-panel-action-*", "debug", "scene"],
"permissions": [
"core:default",
+1 -1
View File
@@ -3,7 +3,7 @@ use sqlx::{Pool, Sqlite};
use std::error::Error;
use tauri::{AppHandle, Manager};
const DATABASE_FILE: &str = "wyd.sqlite";
const DATABASE_FILE: &str = "friendolls.sqlite";
pub struct AppDatabase {
pool: Pool<Sqlite>,
+7 -7
View File
@@ -41,7 +41,7 @@ async fn emit_changed(handle: &AppHandle, database: &AppDatabase) -> Result<(),
async fn update_profiles(
database: &AppDatabase,
profiles: &[wyd_common::Profile],
profiles: &[friendolls_common::Profile],
) -> Result<bool, sqlx::Error> {
let mut transaction = database.pool().begin().await?;
let mut changed = false;
@@ -49,7 +49,7 @@ async fn update_profiles(
if profile
.skin_hash
.as_deref()
.is_some_and(|hash| !wyd_common::is_skin_hash(hash))
.is_some_and(|hash| !friendolls_common::is_skin_hash(hash))
{
continue;
}
@@ -71,7 +71,7 @@ async fn update_profiles(
pub(crate) async fn apply_profile_update(
handle: &AppHandle,
database: &AppDatabase,
profile: wyd_common::Profile,
profile: friendolls_common::Profile,
) -> Result<bool, String> {
apply_profile_sync(handle, database, vec![profile]).await
}
@@ -79,7 +79,7 @@ pub(crate) async fn apply_profile_update(
pub(crate) async fn apply_profile_sync(
handle: &AppHandle,
database: &AppDatabase,
profiles: Vec<wyd_common::Profile>,
profiles: Vec<friendolls_common::Profile>,
) -> Result<bool, String> {
let changed = update_profiles(database, &profiles)
.await
@@ -205,12 +205,12 @@ mod tests {
update_profiles(
&database,
&[
wyd_common::Profile {
friendolls_common::Profile {
id: "friend-id".to_owned(),
display_name: "New".to_owned(),
skin_hash: Some("a".repeat(64)),
},
wyd_common::Profile {
friendolls_common::Profile {
id: "missing".to_owned(),
display_name: "Name".to_owned(),
skin_hash: None,
@@ -223,7 +223,7 @@ mod tests {
assert!(
!update_profiles(
&database,
&[wyd_common::Profile {
&[friendolls_common::Profile {
id: "friend-id".to_owned(),
display_name: "New".to_owned(),
skin_hash: Some("a".repeat(64)),
+1 -1
View File
@@ -2,12 +2,12 @@ use std::io::Cursor;
use base64::Engine;
use base64::engine::general_purpose::STANDARD;
use friendolls_common::{InteractionContent, MAX_IMAGE_B64_SIZE, MAX_IMAGE_DIMENSION};
use image::codecs::jpeg::JpegEncoder;
use image::imageops::FilterType;
use image::{DynamicImage, ImageReader, Limits, Rgb, RgbImage};
use tauri::{AppHandle, State};
use tauri_plugin_dialog::DialogExt;
use wyd_common::{InteractionContent, MAX_IMAGE_B64_SIZE, MAX_IMAGE_DIMENSION};
use crate::network::Network;
+2 -2
View File
@@ -3,11 +3,11 @@ use std::sync::Mutex;
use base64::Engine;
use base64::engine::general_purpose::STANDARD;
use friendolls_common::InteractionContent;
use serde::Serialize;
use specta::Type;
use tauri::{AppHandle, Manager, State};
use tauri_specta::Event;
use wyd_common::InteractionContent;
use crate::network::Network;
@@ -106,7 +106,7 @@ pub async fn send_interaction(
#[cfg(test)]
mod tests {
use super::*;
use wyd_common::MAX_TEXT_CHARS;
use friendolls_common::MAX_TEXT_CHARS;
#[test]
fn validates_interaction_content_limits() {
+1 -1
View File
@@ -2,5 +2,5 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
wyd_lib::run()
friendolls_lib::run()
}
+7 -5
View File
@@ -1,14 +1,14 @@
use std::collections::HashMap;
use std::time::Duration;
use friendolls_common::{
ClientMessage, InteractionDeliveryStatus, Profile, ServerMessage, friends_bytes,
interaction_bytes, message_bytes, profile_bytes, register_bytes,
};
use futures_util::{SinkExt, StreamExt};
use tauri::{AppHandle, Manager};
use tokio::sync::{mpsc, oneshot, watch};
use tokio_tungstenite::tungstenite::Message;
use wyd_common::{
ClientMessage, InteractionDeliveryStatus, Profile, ServerMessage, friends_bytes,
interaction_bytes, message_bytes, profile_bytes, register_bytes,
};
use super::presence::FriendPresence;
use super::{
@@ -113,7 +113,9 @@ async fn connect(
let (mut writer, mut reader) = socket.split();
let challenge = match recv(&mut reader).await? {
ServerMessage::Challenge { version, challenge } if version == wyd_common::VERSION => {
ServerMessage::Challenge { version, challenge }
if version == friendolls_common::VERSION =>
{
challenge
}
_ => return Err("server did not send a compatible challenge".into()),
+1 -1
View File
@@ -3,12 +3,12 @@ use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use friendolls_common::{InteractionContent, InteractionDeliveryStatus};
use serde::{Deserialize, Serialize};
use specta::Type;
use tauri::{AppHandle, Manager, State};
use tauri_specta::Event;
use tokio::sync::{mpsc, oneshot, watch};
use wyd_common::{InteractionContent, InteractionDeliveryStatus};
use crate::db::AppDatabase;
use crate::friends::{self, FriendsChanged};
+2 -2
View File
@@ -13,7 +13,7 @@ const SKIN_WIDTH: u32 = 64;
const SKIN_HEIGHT: u32 = 64;
fn validate_hash(hash: &str) -> Result<(), String> {
if wyd_common::is_skin_hash(hash) {
if friendolls_common::is_skin_hash(hash) {
Ok(())
} else {
Err("Skin hash must be a 64-character SHA-256 value".to_owned())
@@ -72,7 +72,7 @@ fn read_verified(path: PathBuf, expected_hash: &str) -> Result<Option<Vec<u8>>,
}
pub(crate) fn decode_response(data: &str, expected_hash: &str) -> Option<Vec<u8>> {
if data.len() > wyd_common::MAX_SKIN_B64_SIZE {
if data.len() > friendolls_common::MAX_SKIN_B64_SIZE {
return None;
}
let bytes = STANDARD.decode(data).ok()?;
+1 -1
View File
@@ -14,7 +14,7 @@ pub fn init(handle: &AppHandle) {
WINDOW_LABEL,
WebviewUrl::App("/control-panel".into()),
)
.title("Wyd Control Panel")
.title("Friendolls")
.inner_size(400.0, 600.0)
.min_inner_size(400.0, 600.0)
.resizable(false)
+1 -1
View File
@@ -14,7 +14,7 @@ pub fn init(handle: &AppHandle) {
let builder =
tauri::WebviewWindowBuilder::new(handle, WINDOW_LABEL, WebviewUrl::App("/".into()))
.title("Wyd Debug")
.title("Friendolls Debug")
.inner_size(800.0, 600.0)
.min_inner_size(500.0, 400.0)
.visible(true);
+1 -1
View File
@@ -24,7 +24,7 @@ pub fn init(handle: &AppHandle) {
.expect("Tray menu should be created");
let mut builder = TrayIconBuilder::new()
.tooltip("Wyd")
.tooltip("Friendolls")
.menu(&menu)
.show_menu_on_left_click(true)
.on_menu_event(|app, event| match event.id().as_ref() {
+2 -2
View File
@@ -1,8 +1,8 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "wyd",
"productName": "friendolls",
"version": "0.1.0",
"identifier": "com.adamcv.wyd",
"identifier": "com.adamcv.friendolls",
"build": {
"beforeDevCommand": "bun run dev",
"devUrl": "http://localhost:1420",
+1 -1
View File
@@ -4,7 +4,7 @@
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>wyd</title>
<title>friendolls</title>
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
+1 -1
View File
@@ -72,7 +72,7 @@
}
</script>
<svelte:head><title>Wyd Properties</title></svelte:head>
<svelte:head><title>Friendolls Properties</title></svelte:head>
<main
class="flex h-full min-h-0 flex-col overflow-hidden bg-base-100 p-2 text-base-content"
@@ -87,8 +87,8 @@
{#if error}<PanelMessage kind="error">{error}</PanelMessage>{/if}
<PanelMessage>
Their display name will appear after Wyd learns their profile from a
shared server.
Their display name will appear after Friendolls learns their profile from
a shared server.
</PanelMessage>
<fieldset class="fieldset border border-base-300 bg-base-100 p-3">
@@ -109,7 +109,7 @@
<div>
<h1 class="text-sm font-bold">Edit server</h1>
<p class="text-xs text-base-content/65">
Update how Wyd connects to this remote server.
Update how Friendolls connects to this remote server.
</p>
</div>