From 831aaf2c4b1b00e77dae0f9f9818a9a41b027d11 Mon Sep 17 00:00:00 2001 From: jadeddelta <101148768+jadeddelta@users.noreply.github.com> Date: Sat, 8 Oct 2022 16:38:04 -0400 Subject: [PATCH 1/6] handle input permission rejections --- examples/jspsych-initialize-camera.html | 36 +++++++++++-------- .../plugin-html-audio-response/src/index.ts | 6 +++- .../plugin-html-video-response/src/index.ts | 6 +++- .../plugin-initialize-camera/src/index.ts | 21 ++++++++++- .../plugin-initialize-microphone/src/index.ts | 22 ++++++++++-- 5 files changed, 71 insertions(+), 20 deletions(-) diff --git a/examples/jspsych-initialize-camera.html b/examples/jspsych-initialize-camera.html index face9569..86b7b883 100644 --- a/examples/jspsych-initialize-camera.html +++ b/examples/jspsych-initialize-camera.html @@ -1,20 +1,28 @@ - - - - - - - + + + + + + - \ No newline at end of file + jsPsych.run([init_camera, vr]); + + diff --git a/packages/plugin-html-audio-response/src/index.ts b/packages/plugin-html-audio-response/src/index.ts index dfe602a7..48cf45fd 100644 --- a/packages/plugin-html-audio-response/src/index.ts +++ b/packages/plugin-html-audio-response/src/index.ts @@ -73,11 +73,15 @@ class HtmlAudioResponsePlugin implements JsPsychPlugin { private data_available_handler; private recorded_data_chunks = []; - constructor(private jsPsych: JsPsych) {} + constructor(private jsPsych: JsPsych) { } trial(display_element: HTMLElement, trial: TrialType) { this.recorder = this.jsPsych.pluginAPI.getMicrophoneRecorder(); + if (this.recorder === null) { + throw new Error('Error in html-audio-response plugin. A microphone has not been found, have you ran the initialize-microphone plugin?'); + } + this.setupRecordingEvents(display_element, trial); this.startRecording(); diff --git a/packages/plugin-html-video-response/src/index.ts b/packages/plugin-html-video-response/src/index.ts index cdfd2f92..c631d9f2 100644 --- a/packages/plugin-html-video-response/src/index.ts +++ b/packages/plugin-html-video-response/src/index.ts @@ -73,11 +73,15 @@ class HtmlVideoResponsePlugin implements JsPsychPlugin { private data_available_handler; private recorded_data_chunks = []; - constructor(private jsPsych: JsPsych) {} + constructor(private jsPsych: JsPsych) { } trial(display_element: HTMLElement, trial: TrialType) { this.recorder = this.jsPsych.pluginAPI.getCameraRecorder(); + if (this.recorder === null) { + throw new Error("Error in html-video-response plugin. A camera has not been found, have you ran the initialize-camera plugin?"); + } + this.setupRecordingEvents(display_element, trial); this.startRecording(); diff --git a/packages/plugin-initialize-camera/src/index.ts b/packages/plugin-initialize-camera/src/index.ts index 4e8d9c08..97a3df58 100644 --- a/packages/plugin-initialize-camera/src/index.ts +++ b/packages/plugin-initialize-camera/src/index.ts @@ -33,6 +33,11 @@ const info = { type: ParameterType.STRING, default: null, }, + /** The message to display when permission to access the camera is rejected. */ + rejection_message: { + type: ParameterType.HTML_STRING, + default: `

You must allow access to a camera in order to participate in the experiment.

`, + }, }, }; @@ -61,7 +66,15 @@ class InitializeCameraPlugin implements JsPsychPlugin { } private async run_trial(display_element: HTMLElement, trial: TrialType) { - await this.askForPermission(trial); + try { + console.log("test1") + await this.askForPermission(trial); + } catch (e) { + console.log("test") + // TODO: does not properly display rejection message + this.rejectPermission(trial); + return; + } this.showCameraSelection(display_element, trial); @@ -147,6 +160,12 @@ class InitializeCameraPlugin implements JsPsychPlugin { }); }); } + + private rejectPermission(trial: TrialType) { + this.jsPsych.getDisplayElement().innerHTML = ""; + + this.jsPsych.endExperiment(trial.rejection_message, {}); + } } export default InitializeCameraPlugin; diff --git a/packages/plugin-initialize-microphone/src/index.ts b/packages/plugin-initialize-microphone/src/index.ts index 9a08c97b..b62ce4c2 100644 --- a/packages/plugin-initialize-microphone/src/index.ts +++ b/packages/plugin-initialize-microphone/src/index.ts @@ -3,16 +3,21 @@ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; const info = { name: "initialize-microphone", parameters: { - /** Function to call */ + /** The message that prompts the participant to select a microphone. */ device_select_message: { type: ParameterType.HTML_STRING, default: `

Please select the microphone you would like to use.

`, }, - /** Is the function call asynchronous? */ + /** Label of the button that confirms selection of the microphone. */ button_label: { type: ParameterType.STRING, default: "Use this microphone", }, + /** The message to display when permission to access the microphone is rejected. */ + rejection_message: { + type: ParameterType.HTML_STRING, + default: `

You must allow access to a microphone in order to participate in the experiment.

`, + }, }, }; @@ -40,7 +45,12 @@ class InitializeMicrophonePlugin implements JsPsychPlugin { } private async run_trial(display_element: HTMLElement, trial: TrialType) { - await this.askForPermission(); + try { + await this.askForPermission(); + } catch(e) { + this.rejectPermission(trial); + return; + } this.showMicrophoneSelection(display_element, trial); @@ -106,6 +116,12 @@ class InitializeMicrophonePlugin implements JsPsychPlugin { }); }); } + + private rejectPermission(trial: TrialType) { + this.jsPsych.getDisplayElement().innerHTML = ""; + + this.jsPsych.endExperiment(trial.rejection_message, {}); + } } export default InitializeMicrophonePlugin; From 28bd4a0187cf0b2c6c7147e9875b85644cb7f9a5 Mon Sep 17 00:00:00 2001 From: jadeddelta <101148768+jadeddelta@users.noreply.github.com> Date: Tue, 18 Oct 2022 16:03:16 -0400 Subject: [PATCH 2/6] docs update + remove console.logs --- docs/plugins/initialize-camera.md | 3 ++- docs/plugins/initialize-microphone.md | 3 ++- packages/plugin-initialize-camera/src/index.ts | 4 +--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/plugins/initialize-camera.md b/docs/plugins/initialize-camera.md index 5f5271b4..4674b8c3 100644 --- a/docs/plugins/initialize-camera.md +++ b/docs/plugins/initialize-camera.md @@ -18,11 +18,12 @@ In addition to the [parameters available in all plugins](../overview/plugins.md# Parameter | Type | Default Value | Description ----------|------|---------------|------------ device_select_message | html string | `

Please select the camera you would like to use.

` | The message to display when the user is presented with a dropdown list of available devices. -button_label | sting | 'Use this camera.' | The label for the select button. +button_label | string | 'Use this camera.' | The label for the select button. include_audio | bool | false | Set to `true` to include an audio track in the recordings. width | int | null | Request a specific width for the recording. This is not a guarantee that this width will be used, as it depends on the capabilities of the participant's device. Learn more about `MediaRecorder` constraints [here](https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints#requesting_a_specific_value_for_a_setting). height | int | null | Request a specific height for the recording. This is not a guarantee that this height will be used, as it depends on the capabilities of the participant's device. Learn more about `MediaRecorder` constraints [here](https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints#requesting_a_specific_value_for_a_setting). mime_type | string | null | Set this to use a specific [MIME type](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/mimeType) for the recording. Set the entire type, e.g., `'video/mp4; codecs="avc1.424028, mp4a.40.2"'`. +rejection_message | html string | `

You must allow access to a camera in order to participate in the experiment.

` | The message to display if the user rejects access to the camera. ## Data Generated diff --git a/docs/plugins/initialize-microphone.md b/docs/plugins/initialize-microphone.md index 06a643ca..f3d7e11f 100644 --- a/docs/plugins/initialize-microphone.md +++ b/docs/plugins/initialize-microphone.md @@ -18,7 +18,8 @@ In addition to the [parameters available in all plugins](../overview/plugins.md# Parameter | Type | Default Value | Description ----------|------|---------------|------------ device_select_message | html string | `

Please select the microphone you would like to use.

` | The message to display when the user is presented with a dropdown list of available devices. -button_label | sting | 'Use this microphone.' | The label for the select button. +button_label | string | 'Use this microphone.' | The label for the select button. +rejection_message | html string | `

You must allow access to a microphone in order to participate in the experiment.

` | The message to display if the user rejects access to the microphone. ## Data Generated diff --git a/packages/plugin-initialize-camera/src/index.ts b/packages/plugin-initialize-camera/src/index.ts index 97a3df58..aaff515f 100644 --- a/packages/plugin-initialize-camera/src/index.ts +++ b/packages/plugin-initialize-camera/src/index.ts @@ -54,7 +54,7 @@ type Info = typeof info; class InitializeCameraPlugin implements JsPsychPlugin { static info = info; - constructor(private jsPsych: JsPsych) {} + constructor(private jsPsych: JsPsych) { } trial(display_element: HTMLElement, trial: TrialType) { this.run_trial(display_element, trial).then((id) => { @@ -67,10 +67,8 @@ class InitializeCameraPlugin implements JsPsychPlugin { private async run_trial(display_element: HTMLElement, trial: TrialType) { try { - console.log("test1") await this.askForPermission(trial); } catch (e) { - console.log("test") // TODO: does not properly display rejection message this.rejectPermission(trial); return; From 8fec0457a7c869de44638e79f8f76f2056bd183c Mon Sep 17 00:00:00 2001 From: jadeddelta <101148768+jadeddelta@users.noreply.github.com> Date: Tue, 1 Nov 2022 15:16:55 -0400 Subject: [PATCH 3/6] changesets --- .changeset/fluffy-books-act.md | 6 ++++++ .changeset/hungry-elephants-jam.md | 5 +++++ .changeset/poor-cherries-pay.md | 5 +++++ .changeset/violet-hairs-tap.md | 5 ----- 4 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 .changeset/fluffy-books-act.md create mode 100644 .changeset/hungry-elephants-jam.md create mode 100644 .changeset/poor-cherries-pay.md delete mode 100644 .changeset/violet-hairs-tap.md diff --git a/.changeset/fluffy-books-act.md b/.changeset/fluffy-books-act.md new file mode 100644 index 00000000..22c8378d --- /dev/null +++ b/.changeset/fluffy-books-act.md @@ -0,0 +1,6 @@ +--- +"@jspsych/plugin-html-audio-response": minor +"@jspsych/plugin-html-video-response": minor +--- + +added handling and a custom rejection message if the media device does not have access permissions diff --git a/.changeset/hungry-elephants-jam.md b/.changeset/hungry-elephants-jam.md new file mode 100644 index 00000000..2792ee1c --- /dev/null +++ b/.changeset/hungry-elephants-jam.md @@ -0,0 +1,5 @@ +--- +"@jspsych/plugin-initialize-microphone": patch +--- + +added error handling if permission to the microphone is rejected diff --git a/.changeset/poor-cherries-pay.md b/.changeset/poor-cherries-pay.md new file mode 100644 index 00000000..55bedd67 --- /dev/null +++ b/.changeset/poor-cherries-pay.md @@ -0,0 +1,5 @@ +--- +"@jspsych/plugin-initialize-camera": patch +--- + +added error handling if permission to the camera is rejected diff --git a/.changeset/violet-hairs-tap.md b/.changeset/violet-hairs-tap.md deleted file mode 100644 index d24fd8a8..00000000 --- a/.changeset/violet-hairs-tap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@jspsych/plugin-cloze": minor ---- - -added `allow_blanks` as a field, allowing for completion checking of answers From 820abb0a49e0065eb30e09b69b643280951f260f Mon Sep 17 00:00:00 2001 From: jadeddelta <101148768+jadeddelta@users.noreply.github.com> Date: Tue, 1 Nov 2022 15:52:49 -0400 Subject: [PATCH 4/6] specify and clean up changesets --- .changeset/cool-creatures-crawl.md | 5 +++++ .changeset/fluffy-books-act.md | 5 ++--- .changeset/hungry-elephants-jam.md | 4 ++-- .changeset/poor-cherries-pay.md | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 .changeset/cool-creatures-crawl.md diff --git a/.changeset/cool-creatures-crawl.md b/.changeset/cool-creatures-crawl.md new file mode 100644 index 00000000..21d12de1 --- /dev/null +++ b/.changeset/cool-creatures-crawl.md @@ -0,0 +1,5 @@ +--- +"@jspsych/plugin-html-audio-response": patch +--- + +added error handling if a microphone is not detected on trial start \ No newline at end of file diff --git a/.changeset/fluffy-books-act.md b/.changeset/fluffy-books-act.md index 22c8378d..38a4bfbc 100644 --- a/.changeset/fluffy-books-act.md +++ b/.changeset/fluffy-books-act.md @@ -1,6 +1,5 @@ --- -"@jspsych/plugin-html-audio-response": minor -"@jspsych/plugin-html-video-response": minor +"@jspsych/plugin-html-video-response": patch --- -added handling and a custom rejection message if the media device does not have access permissions +added error handling if a camera is not detected on trial start diff --git a/.changeset/hungry-elephants-jam.md b/.changeset/hungry-elephants-jam.md index 2792ee1c..85a40ceb 100644 --- a/.changeset/hungry-elephants-jam.md +++ b/.changeset/hungry-elephants-jam.md @@ -1,5 +1,5 @@ --- -"@jspsych/plugin-initialize-microphone": patch +"@jspsych/plugin-initialize-microphone": minor --- -added error handling if permission to the microphone is rejected +added custom rejection message upon microphone permission denial diff --git a/.changeset/poor-cherries-pay.md b/.changeset/poor-cherries-pay.md index 55bedd67..65ee91ef 100644 --- a/.changeset/poor-cherries-pay.md +++ b/.changeset/poor-cherries-pay.md @@ -1,5 +1,5 @@ --- -"@jspsych/plugin-initialize-camera": patch +"@jspsych/plugin-initialize-camera": minor --- -added error handling if permission to the camera is rejected +added custom rejection message upon camera permission denial From 213f6ae7dce37843d1f6c041134ae99579a82b72 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Sun, 5 Jan 2025 05:46:00 -0700 Subject: [PATCH 5/6] use v8 `abortExperiment` --- packages/plugin-initialize-camera/src/index.ts | 2 +- packages/plugin-initialize-microphone/src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin-initialize-camera/src/index.ts b/packages/plugin-initialize-camera/src/index.ts index 64bd5f39..a2129969 100644 --- a/packages/plugin-initialize-camera/src/index.ts +++ b/packages/plugin-initialize-camera/src/index.ts @@ -186,7 +186,7 @@ class InitializeCameraPlugin implements JsPsychPlugin { private rejectPermission(trial: TrialType) { this.jsPsych.getDisplayElement().innerHTML = ""; - this.jsPsych.endExperiment(trial.rejection_message, {}); + this.jsPsych.abortExperiment(trial.rejection_message, {}); } } diff --git a/packages/plugin-initialize-microphone/src/index.ts b/packages/plugin-initialize-microphone/src/index.ts index d2749eae..18f1a6d6 100644 --- a/packages/plugin-initialize-microphone/src/index.ts +++ b/packages/plugin-initialize-microphone/src/index.ts @@ -140,7 +140,7 @@ class InitializeMicrophonePlugin implements JsPsychPlugin { private rejectPermission(trial: TrialType) { this.jsPsych.getDisplayElement().innerHTML = ""; - this.jsPsych.endExperiment(trial.rejection_message, {}); + this.jsPsych.abortExperiment(trial.rejection_message, {}); } } From b0569323e8c16907c05ea14eea3b9698b84671b8 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Fri, 10 Jan 2025 20:08:38 -0700 Subject: [PATCH 6/6] add return statements for rejection paths --- packages/plugin-initialize-camera/src/index.ts | 3 +-- packages/plugin-initialize-microphone/src/index.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/plugin-initialize-camera/src/index.ts b/packages/plugin-initialize-camera/src/index.ts index a2129969..ddea3bdb 100644 --- a/packages/plugin-initialize-camera/src/index.ts +++ b/packages/plugin-initialize-camera/src/index.ts @@ -93,9 +93,8 @@ class InitializeCameraPlugin implements JsPsychPlugin { try { await this.askForPermission(trial); } catch (e) { - // TODO: does not properly display rejection message this.rejectPermission(trial); - return; + return null; } this.showCameraSelection(display_element, trial); diff --git a/packages/plugin-initialize-microphone/src/index.ts b/packages/plugin-initialize-microphone/src/index.ts index 18f1a6d6..2c546b5b 100644 --- a/packages/plugin-initialize-microphone/src/index.ts +++ b/packages/plugin-initialize-microphone/src/index.ts @@ -69,7 +69,7 @@ class InitializeMicrophonePlugin implements JsPsychPlugin { await this.askForPermission(); } catch(e) { this.rejectPermission(trial); - return; + return null; } this.showMicrophoneSelection(display_element, trial);