reset to default skin btn
This commit is contained in:
@@ -75,6 +75,7 @@ fn specta_builder() -> tauri_specta::Builder<tauri::Wry> {
|
|||||||
remotes::delete_remote,
|
remotes::delete_remote,
|
||||||
profile::get_profile,
|
profile::get_profile,
|
||||||
profile::update_profile,
|
profile::update_profile,
|
||||||
|
profile::reset_profile_skin,
|
||||||
keypair::get_public_key,
|
keypair::get_public_key,
|
||||||
network::list_statuses,
|
network::list_statuses,
|
||||||
network::list_friend_statuses,
|
network::list_friend_statuses,
|
||||||
|
|||||||
@@ -52,6 +52,15 @@ async fn update(
|
|||||||
get(database, public_key).await
|
get(database, public_key).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn reset_skin(database: &AppDatabase, public_key: &str) -> Result<User, sqlx::Error> {
|
||||||
|
sqlx::query("UPDATE profile SET skin_hash = NULL WHERE id = ?1")
|
||||||
|
.bind(PROFILE_ID)
|
||||||
|
.execute(database.pool())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
get(database, public_key).await
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_changed(handle: &AppHandle, profile: User) -> Result<(), String> {
|
fn emit_changed(handle: &AppHandle, profile: User) -> Result<(), String> {
|
||||||
ProfileChanged { profile }
|
ProfileChanged { profile }
|
||||||
.emit(handle)
|
.emit(handle)
|
||||||
@@ -94,6 +103,22 @@ pub async fn update_profile(
|
|||||||
Ok(profile)
|
Ok(profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
#[specta::specta]
|
||||||
|
pub async fn reset_profile_skin(
|
||||||
|
handle: AppHandle,
|
||||||
|
database: State<'_, AppDatabase>,
|
||||||
|
keypair: State<'_, AppKeypair>,
|
||||||
|
network: State<'_, Network>,
|
||||||
|
) -> Result<User, String> {
|
||||||
|
let profile = reset_skin(&database, keypair.public_key())
|
||||||
|
.await
|
||||||
|
.map_err(db::command_error)?;
|
||||||
|
network.update_profile(profile.clone());
|
||||||
|
emit_changed(&handle, profile.clone())?;
|
||||||
|
Ok(profile)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use sqlx::sqlite::SqlitePoolOptions;
|
use sqlx::sqlite::SqlitePoolOptions;
|
||||||
@@ -162,4 +187,30 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(columns, vec!["id", "display_name", "skin_hash"]);
|
assert_eq!(columns, vec!["id", "display_name", "skin_hash"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn resetting_skin_preserves_the_display_name() {
|
||||||
|
let database = database().await;
|
||||||
|
update(
|
||||||
|
&database,
|
||||||
|
"public-key",
|
||||||
|
"Wind".to_owned(),
|
||||||
|
Some("a".repeat(64)),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("set profile skin");
|
||||||
|
|
||||||
|
let profile = reset_skin(&database, "public-key")
|
||||||
|
.await
|
||||||
|
.expect("reset profile skin");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
profile,
|
||||||
|
User {
|
||||||
|
id: "public-key".to_owned(),
|
||||||
|
display_name: "Wind".to_owned(),
|
||||||
|
skin_hash: None,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ async getProfile() : Promise<User> {
|
|||||||
async updateProfile(displayName: string, skinData: number[] | null) : Promise<User> {
|
async updateProfile(displayName: string, skinData: number[] | null) : Promise<User> {
|
||||||
return await TAURI_INVOKE("update_profile", { displayName, skinData });
|
return await TAURI_INVOKE("update_profile", { displayName, skinData });
|
||||||
},
|
},
|
||||||
|
async resetProfileSkin() : Promise<User> {
|
||||||
|
return await TAURI_INVOKE("reset_profile_skin");
|
||||||
|
},
|
||||||
async getPublicKey() : Promise<string> {
|
async getPublicKey() : Promise<string> {
|
||||||
return await TAURI_INVOKE("get_public_key");
|
return await TAURI_INVOKE("get_public_key");
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
let skinFile = $state<File | null>(null);
|
let skinFile = $state<File | null>(null);
|
||||||
let skinPreviewUrl = $state<string | null>(null);
|
let skinPreviewUrl = $state<string | null>(null);
|
||||||
let skinInput = $state<HTMLInputElement | null>(null);
|
let skinInput = $state<HTMLInputElement | null>(null);
|
||||||
|
let pendingSkinReset = $state(false);
|
||||||
let dirty = $state(false);
|
let dirty = $state(false);
|
||||||
let busy = $state(false);
|
let busy = $state(false);
|
||||||
let error = $state("");
|
let error = $state("");
|
||||||
@@ -45,7 +46,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateDirty() {
|
function updateDirty() {
|
||||||
dirty = hasConfigurationChanges() || skinFile !== null;
|
dirty = hasConfigurationChanges() || skinFile !== null || pendingSkinReset;
|
||||||
error = "";
|
error = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,16 +59,24 @@
|
|||||||
|
|
||||||
function selectSkinFile(file: File | null) {
|
function selectSkinFile(file: File | null) {
|
||||||
clearSkinDraft();
|
clearSkinDraft();
|
||||||
|
pendingSkinReset = false;
|
||||||
skinFile = file;
|
skinFile = file;
|
||||||
skinPreviewUrl = file ? URL.createObjectURL(file) : null;
|
skinPreviewUrl = file ? URL.createObjectURL(file) : null;
|
||||||
updateDirty();
|
updateDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetSkin() {
|
||||||
|
clearSkinDraft();
|
||||||
|
pendingSkinReset = true;
|
||||||
|
updateDirty();
|
||||||
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
puppetScale = $sceneConfiguration.puppetScale;
|
puppetScale = $sceneConfiguration.puppetScale;
|
||||||
puppetOpacity = $sceneConfiguration.puppetOpacity;
|
puppetOpacity = $sceneConfiguration.puppetOpacity;
|
||||||
puppetMovementMode = $sceneConfiguration.puppetMovementMode;
|
puppetMovementMode = $sceneConfiguration.puppetMovementMode;
|
||||||
clearSkinDraft();
|
clearSkinDraft();
|
||||||
|
pendingSkinReset = false;
|
||||||
dirty = false;
|
dirty = false;
|
||||||
error = "";
|
error = "";
|
||||||
}
|
}
|
||||||
@@ -78,7 +87,10 @@
|
|||||||
busy = true;
|
busy = true;
|
||||||
error = "";
|
error = "";
|
||||||
try {
|
try {
|
||||||
if (skinFile) {
|
if (pendingSkinReset) {
|
||||||
|
await commands.resetProfileSkin();
|
||||||
|
pendingSkinReset = false;
|
||||||
|
} else if (skinFile) {
|
||||||
const currentProfile = await commands.getProfile();
|
const currentProfile = await commands.getProfile();
|
||||||
const skinData = Array.from(
|
const skinData = Array.from(
|
||||||
new Uint8Array(await skinFile.arrayBuffer()),
|
new Uint8Array(await skinFile.arrayBuffer()),
|
||||||
@@ -100,7 +112,8 @@
|
|||||||
dirty = false;
|
dirty = false;
|
||||||
return true;
|
return true;
|
||||||
} catch (cause) {
|
} catch (cause) {
|
||||||
dirty = hasConfigurationChanges() || skinFile !== null;
|
dirty =
|
||||||
|
hasConfigurationChanges() || skinFile !== null || pendingSkinReset;
|
||||||
error = String(cause);
|
error = String(cause);
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -141,7 +154,7 @@
|
|||||||
<div class="size-full z-10">
|
<div class="size-full z-10">
|
||||||
<PuppetPreview
|
<PuppetPreview
|
||||||
userId={$profile.id}
|
userId={$profile.id}
|
||||||
skinHash={$profile.skinHash}
|
skinHash={pendingSkinReset ? null : $profile.skinHash}
|
||||||
skinSource={skinPreviewUrl}
|
skinSource={skinPreviewUrl}
|
||||||
scale={puppetScale}
|
scale={puppetScale}
|
||||||
opacity={puppetOpacity}
|
opacity={puppetOpacity}
|
||||||
@@ -192,14 +205,22 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<div>
|
<div class="grid grid-cols-[minmax(0,1fr)_auto] gap-2">
|
||||||
<button
|
<button
|
||||||
class="btn w-full"
|
class="btn w-full"
|
||||||
type="button"
|
type="button"
|
||||||
disabled={!$profile || busy}
|
disabled={!$profile || busy}
|
||||||
onclick={() => skinInput?.click()}
|
onclick={() => skinInput?.click()}
|
||||||
>
|
>
|
||||||
Choose a custom skin
|
Choose a skin
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
type="button"
|
||||||
|
disabled={!$profile || busy || (!$profile.skinHash && !skinFile)}
|
||||||
|
onclick={resetSkin}
|
||||||
|
>
|
||||||
|
Reset
|
||||||
</button>
|
</button>
|
||||||
<input
|
<input
|
||||||
id="skin-file"
|
id="skin-file"
|
||||||
|
|||||||
Reference in New Issue
Block a user