Skip to content
This repository was archived by the owner on Apr 14, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions config-overrides.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const path = require('path')
const webpack = require('webpack')

module.exports = function(config, env) {
// Add an exclusion rule to prevent the file-loader being used
const wasmExtensionRegExp = /\.wasm$/;
config.resolve.extensions.push('.wasm');
config.module.rules.forEach(rule => {
(rule.oneOf || []).forEach(oneOf => {
if (oneOf.loader && oneOf.loader.indexOf('file-loader') >= 0) {
oneOf.exclude.push(wasmExtensionRegExp);
}
});
});

// Add a dedicated loader for WASM
config.module.rules.push({
test: wasmExtensionRegExp,
include: path.resolve(__dirname, 'src'),
use: [{ loader: require.resolve('wasm-loader'), options: {} }]
});

// Tell webpack to use the Web, rather than NodeJS, version of Buttplug
config.plugins.push(
new webpack.NormalModuleReplacementPlugin(/^#/, resource => {
if (resource.request === "#buttplug_rs_ffi_bg") {
resource.request = "./buttplug_rs_ffi_bg_web.js"
}
})
)

return config;
}
20,164 changes: 20,121 additions & 43 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@
"@types/styled-components": "^4.4.3",
"axios": "^0.19.2",
"axios-jsonp": "^1.0.2",
"buttplug": "^0.13.2",
"buttplug": "1.0.17",
"husky": "^2.3.0",
"lint-staged": "^8.1.7",
"lodash": "^4.17.15",
"marked": "^0.8.0",
"prettier": "^1.17.1",
"raw.macro": "^0.3.0",
"react": "^16.13.1",
"react-app-rewired": "^2.2.1",
"react-dom": "^16.13.1",
"react-ga": "^2.7.0",
"react-redux": "^7.2.0",
Expand All @@ -38,7 +39,8 @@
"styled-components": "^4.4.1",
"tone": "^13.4.9",
"typescript": "^3.9.2",
"wafxr": "^0.1.1"
"wafxr": "^0.1.1",
"wasm-loader": "^1.3.0"
},
"husky": {
"hooks": {
Expand All @@ -56,9 +58,9 @@
"commit-hooks": false
},
"scripts": {
"start": "PORT=3006 react-scripts start",
"build": "react-scripts build",
"test:watch": "react-scripts test",
"start": "PORT=3006 react-app-rewired start",
"build": "react-app-rewired build",
"test:watch": "react-app-rewired test",
"test": "jest --passWithNoTests",
"eject": "react-scripts eject",
"lint": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json}'",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,34 @@ const VIBRATION_STYLE_MODES = [
{ mode: VibrationStyleMode.THUMP, name: 'Thump', description: 'Vibration thumps with the stroke pace.' },
]

const Wrapper = (props: PropsWithChildren<{}>) => (
<fieldset className="settings-group">
<legend>Vibrator</legend>
<div className="settings-row">
<strong>Connect any compatible device to your game.</strong>
<em>This requires a browser that supports WebBluetooth. Use Chrome.</em>
{props.children}
</div>
</fieldset>
)
const Wrapper = (props: PropsWithChildren<{}>) => {
if (navigator.bluetooth === undefined) {
return (
<fieldset className="settings-group">
<legend>Vibrator</legend>
<div className="settings-row">
<strong>WebBluetooth not detected</strong>
<em>
This requires a browser that supports the Web Bluetooth API, please see the
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API#browser_compatibility">compatability page</a>
to find a supported browser.
</em>
</div>
</fieldset>
)
} else {
return (
<fieldset className="settings-group">
<legend>Vibrator</legend>
<div className="settings-row">
<strong>Connect any compatible device to your game.</strong>
<em>This requires a browser that supports WebBluetooth. Use Chrome.</em>
{props.children}
</div>
</fieldset>
)
}
}

export function VibratorSetting(props: ILovenseSettingProps) {
if (props.vibrator) {
Expand Down
37 changes: 28 additions & 9 deletions src/features/settings/store/actions.vibrator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ButtplugClient, ButtplugEmbeddedClientConnector, ButtplugClientDevice } from 'buttplug'
import { ButtplugClient, ButtplugClientDevice, ButtplugEmbeddedConnectorOptions, ButtplugDeviceMessageType, buttplugInit } from 'buttplug'
import { Thunk } from '../../../store.types'
import { Vibrator } from '../../../services/vibrator'

Expand All @@ -7,9 +7,6 @@ export const T_VIBRATOR_PAIRED = 'VIBRATOR_PAIRED'
export const T_VIBRATOR_UNPAIRED = 'VIBRATOR_UNPAIRED'
export const T_VIBRATOR_SET_MODE = 'VIBRATOR_SET_MODE'

const client = new ButtplugClient('JOI.how Client')
const connector = new ButtplugEmbeddedClientConnector()

export class DeviceNotSupportedError extends Error {}

export enum VibrationStyleMode {
Expand All @@ -18,20 +15,41 @@ export enum VibrationStyleMode {
}

class SettingsVibratorActionsBase {
private client?: ButtplugClient

private connector?: ButtplugEmbeddedConnectorOptions

private buttplugInitialised: boolean = false

private async getButtplug(): Promise<[ButtplugClient, ButtplugEmbeddedConnectorOptions]> {
if (!this.buttplugInitialised) {
await buttplugInit()

this.client = new ButtplugClient('JOI.how Client')
this.connector = new ButtplugEmbeddedConnectorOptions()

this.buttplugInitialised = true
}

return [this.client!, this.connector!]
}

TryToPair(): Thunk {
return async dispatch => {
const [client, connector] = await this.getButtplug()

client.removeAllListeners()
client.addListener('deviceadded', (device: ButtplugClientDevice) => {
if (device.AllowedMessages.indexOf('VibrateCmd') >= 0) {
if (device.AllowedMessages.indexOf(ButtplugDeviceMessageType.VibrateCmd) >= 0) {
dispatch(this.Paired(device))
} else {
dispatch(this.PairFailed(new DeviceNotSupportedError()))
}
})

try {
await client.Connect(connector)
await client.StartScanning()
await client.connect(connector)
await client.startScanning()
} catch (e) {
dispatch(this.PairFailed(e))
}
Expand All @@ -40,8 +58,9 @@ class SettingsVibratorActionsBase {

TryToUnpair(): Thunk {
return async dispatch => {
await client.StopAllDevices()
await client.Disconnect()
const [client, _] = await this.getButtplug()
await client.stopAllDevices()
await client.disconnect()
dispatch(this.Unpaired())
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/features/settings/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import { ThunkDispatch } from 'redux-thunk'
import { IState } from '../../store'
import { SettingsVibratorAction } from './store/actions.vibrator'

declare global {
interface Navigator {
bluetooth?: any
}
}

export interface PropsForConnectedComponent {
dispatch: ThunkDispatch<IState, unknown, ReturnType<SettingsAction | SettingsVibratorAction>>
}
Expand Down
6 changes: 3 additions & 3 deletions src/services/vibrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ export class Vibrator {
constructor(private device: ButtplugClientDevice) {}

async setVibration(intensity: number) {
return this.device.SendVibrateCmd(intensity)
return this.device.vibrate(intensity)
}

async thump(timeout: number, intensity: number = 1) {
if (!this.active) {
this.active = true
await this.device.SendVibrateCmd(intensity)
await this.device.vibrate(intensity)
await wait(timeout)
await this.device.SendStopDeviceCmd()
await this.device.stop()
this.active = false
} else {
return wait(timeout)
Expand Down
Loading