feat: upgrade buttplug package to protocol v4 and WASM v10
All checks were successful
Build and Push Docker Image to Gitea / build-and-push (push) Successful in 7m30s
All checks were successful
Build and Push Docker Image to Gitea / build-and-push (push) Successful in 7m30s
Upgrade the buttplug TypeScript client from class-based v3 protocol to interface-based v4 protocol, and the Rust/WASM server from the monolithic buttplug 9.0.9 crate to the split buttplug_core/buttplug_server/ buttplug_server_device_config 10.0.0 crates. TypeScript changes: - Messages are now plain interfaces with msgId()/setMsgId() helpers - ActuatorType → OutputType, SensorType → InputType - ScalarCmd/RotateCmd/LinearCmd → OutputCmd, SensorReadCmd → InputCmd - Client.ts → ButtplugClient.ts, new DeviceCommand/DeviceFeature files - Devices getter returns Map instead of array - Removed class-transformer/reflect-metadata dependencies Rust/WASM changes: - Split imports across buttplug_core, buttplug_server, buttplug_server_device_config - Removed ButtplugServerDowngradeWrapper (use ButtplugServer directly) - Replaced ButtplugFuture/ButtplugFutureStateShared with tokio::sync::oneshot - Updated Hardware::new for new 6-arg signature - Uses git fork (valknarthing/buttplug) to fix missing wasm deps in buttplug_core Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,6 @@ import { Label } from "$lib/components/ui/label";
|
||||
import { Card, CardContent, CardHeader } from "$lib/components/ui/card";
|
||||
import type { BluetoothDevice } from "$lib/types";
|
||||
import { _ } from "svelte-i18n";
|
||||
import { ActuatorType } from "@sexy.pivoine.art/buttplug";
|
||||
|
||||
interface Props {
|
||||
device: BluetoothDevice;
|
||||
@@ -16,7 +15,7 @@ interface Props {
|
||||
let { device, onChange, onStop }: Props = $props();
|
||||
|
||||
function getBatteryColor(level: number) {
|
||||
if (!device.info.hasBattery) {
|
||||
if (!device.hasBattery) {
|
||||
return "text-gray-400";
|
||||
}
|
||||
if (level > 60) return "text-green-400";
|
||||
@@ -25,7 +24,7 @@ function getBatteryColor(level: number) {
|
||||
}
|
||||
|
||||
function getBatteryBgColor(level: number) {
|
||||
if (!device.info.hasBattery) {
|
||||
if (!device.hasBattery) {
|
||||
return "bg-gray-400/20";
|
||||
}
|
||||
if (level > 60) return "bg-green-400/20";
|
||||
@@ -34,17 +33,13 @@ function getBatteryBgColor(level: number) {
|
||||
}
|
||||
|
||||
function getScalarAnimations() {
|
||||
const cmds: [{ ActuatorType: typeof ActuatorType }] =
|
||||
device.info.messageAttributes.ScalarCmd;
|
||||
return cmds
|
||||
.filter((_, i: number) => !!device.actuatorValues[i])
|
||||
.map(({ ActuatorType }) => `animate-${ActuatorType.toLowerCase()}`);
|
||||
return device.actuators
|
||||
.filter((a) => a.value > 0)
|
||||
.map((a) => `animate-${a.outputType.toLowerCase()}`);
|
||||
}
|
||||
|
||||
function isActive() {
|
||||
const cmds: [{ ActuatorType: typeof ActuatorType }] =
|
||||
device.info.messageAttributes.ScalarCmd;
|
||||
return cmds.some((_, i: number) => !!device.actuatorValues[i]);
|
||||
return device.actuators.some((a) => a.value > 0);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -119,7 +114,7 @@ function isActive() {
|
||||
></span>
|
||||
<span class="text-sm text-muted-foreground">{$_("device_card.battery")}</span>
|
||||
</div>
|
||||
{#if device.info.hasBattery}
|
||||
{#if device.hasBattery}
|
||||
<span class="text-sm font-medium {getBatteryColor(device.batteryLevel)}">
|
||||
{device.batteryLevel}%
|
||||
</span>
|
||||
@@ -144,19 +139,19 @@ function isActive() {
|
||||
</div> -->
|
||||
|
||||
<!-- Action Button -->
|
||||
{#each device.info.messageAttributes.ScalarCmd as scalarCmd}
|
||||
{#each device.actuators as actuator, idx}
|
||||
<div class="space-y-2">
|
||||
<Label for={`device-${device.info.index}-${scalarCmd.Index}`}
|
||||
<Label for={`device-${device.info.index}-${actuator.featureIndex}-${actuator.outputType}`}
|
||||
>{$_(
|
||||
`device_card.actuator_types.${scalarCmd.ActuatorType.toLowerCase()}`,
|
||||
`device_card.actuator_types.${actuator.outputType.toLowerCase()}`,
|
||||
)}</Label
|
||||
>
|
||||
<Slider
|
||||
id={`device-${device.info.index}-${scalarCmd.Index}`}
|
||||
id={`device-${device.info.index}-${actuator.featureIndex}-${actuator.outputType}`}
|
||||
type="single"
|
||||
value={device.actuatorValues[scalarCmd.Index]}
|
||||
onValueChange={(val) => onChange(scalarCmd.Index, val)}
|
||||
max={scalarCmd.StepCount}
|
||||
value={actuator.value}
|
||||
onValueChange={(val) => onChange(idx, val)}
|
||||
max={actuator.maxSteps}
|
||||
step={1}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -108,12 +108,20 @@ export interface Stats {
|
||||
viewers_count: number;
|
||||
}
|
||||
|
||||
export interface DeviceActuator {
|
||||
featureIndex: number;
|
||||
outputType: string;
|
||||
maxSteps: number;
|
||||
descriptor: string;
|
||||
value: number;
|
||||
}
|
||||
|
||||
export interface BluetoothDevice {
|
||||
id: string;
|
||||
name: string;
|
||||
actuatorValues: number[];
|
||||
sensorValues: number[];
|
||||
actuators: DeviceActuator[];
|
||||
batteryLevel: number;
|
||||
hasBattery: boolean;
|
||||
isConnected: boolean;
|
||||
lastSeen: Date;
|
||||
info: ButtplugClientDevice;
|
||||
|
||||
Reference in New Issue
Block a user