@independo/capacitor-voice-recorder 8.1.0-dev.1 → 8.1.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +40 -30
  2. package/android/build.gradle +44 -1
  3. package/android/src/main/java/app/independo/capacitorvoicerecorder/VoiceRecorder.java +146 -0
  4. package/android/src/main/java/app/independo/capacitorvoicerecorder/adapters/PermissionChecker.java +8 -0
  5. package/android/src/main/java/app/independo/capacitorvoicerecorder/adapters/RecordDataMapper.java +32 -0
  6. package/android/src/main/java/app/independo/capacitorvoicerecorder/adapters/RecorderAdapter.java +39 -0
  7. package/android/src/main/java/app/independo/capacitorvoicerecorder/adapters/RecorderPlatform.java +25 -0
  8. package/android/src/main/java/app/independo/capacitorvoicerecorder/core/CurrentRecordingStatus.java +9 -0
  9. package/android/src/main/java/app/independo/capacitorvoicerecorder/core/ErrorCodes.java +19 -0
  10. package/android/src/main/java/{com/tchvu3/capacitorvoicerecorder → app/independo/capacitorvoicerecorder/core}/Messages.java +2 -1
  11. package/android/src/main/java/{com/tchvu3/capacitorvoicerecorder → app/independo/capacitorvoicerecorder/core}/RecordData.java +15 -1
  12. package/android/src/main/java/app/independo/capacitorvoicerecorder/core/RecordOptions.java +4 -0
  13. package/android/src/main/java/app/independo/capacitorvoicerecorder/core/ResponseFormat.java +18 -0
  14. package/android/src/main/java/{com/tchvu3/capacitorvoicerecorder → app/independo/capacitorvoicerecorder/core}/ResponseGenerator.java +7 -1
  15. package/android/src/main/java/{com/tchvu3/capacitorvoicerecorder → app/independo/capacitorvoicerecorder/platform}/CustomMediaRecorder.java +33 -2
  16. package/android/src/main/java/app/independo/capacitorvoicerecorder/platform/DefaultRecorderPlatform.java +86 -0
  17. package/android/src/main/java/app/independo/capacitorvoicerecorder/platform/NotSupportedOsVersion.java +4 -0
  18. package/android/src/main/java/app/independo/capacitorvoicerecorder/service/VoiceRecorderService.java +144 -0
  19. package/android/src/main/java/app/independo/capacitorvoicerecorder/service/VoiceRecorderServiceException.java +23 -0
  20. package/dist/esm/adapters/VoiceRecorderWebAdapter.d.ts +23 -0
  21. package/dist/esm/adapters/VoiceRecorderWebAdapter.js +41 -0
  22. package/dist/esm/adapters/VoiceRecorderWebAdapter.js.map +1 -0
  23. package/dist/esm/core/error-codes.d.ts +4 -0
  24. package/dist/esm/core/error-codes.js +21 -0
  25. package/dist/esm/core/error-codes.js.map +1 -0
  26. package/dist/esm/core/recording-contract.d.ts +3 -0
  27. package/dist/esm/core/recording-contract.js +15 -0
  28. package/dist/esm/core/recording-contract.js.map +1 -0
  29. package/dist/esm/core/response-format.d.ts +8 -0
  30. package/dist/esm/core/response-format.js +17 -0
  31. package/dist/esm/core/response-format.js.map +1 -0
  32. package/dist/esm/platform/web/VoiceRecorderImpl.d.ts +45 -0
  33. package/dist/esm/{VoiceRecorderImpl.js → platform/web/VoiceRecorderImpl.js} +20 -2
  34. package/dist/esm/platform/web/VoiceRecorderImpl.js.map +1 -0
  35. package/dist/esm/platform/web/get-blob-duration.js.map +1 -0
  36. package/dist/esm/{predefined-web-responses.d.ts → platform/web/predefined-web-responses.d.ts} +12 -1
  37. package/dist/esm/{predefined-web-responses.js → platform/web/predefined-web-responses.js} +11 -0
  38. package/dist/esm/platform/web/predefined-web-responses.js.map +1 -0
  39. package/dist/esm/service/VoiceRecorderService.d.ts +47 -0
  40. package/dist/esm/service/VoiceRecorderService.js +60 -0
  41. package/dist/esm/service/VoiceRecorderService.js.map +1 -0
  42. package/dist/esm/web.d.ts +12 -1
  43. package/dist/esm/web.js +26 -12
  44. package/dist/esm/web.js.map +1 -1
  45. package/dist/plugin.cjs.js +200 -9
  46. package/dist/plugin.cjs.js.map +1 -1
  47. package/dist/plugin.js +200 -9
  48. package/dist/plugin.js.map +1 -1
  49. package/ios/Sources/VoiceRecorder/Adapters/DefaultRecorderPlatform.swift +33 -0
  50. package/ios/Sources/VoiceRecorder/Adapters/RecordDataMapper.swift +38 -0
  51. package/ios/Sources/VoiceRecorder/Adapters/RecorderAdapter.swift +24 -0
  52. package/ios/Sources/VoiceRecorder/Adapters/RecorderPlatform.swift +11 -0
  53. package/ios/Sources/VoiceRecorder/Bridge/VoiceRecorder.swift +172 -0
  54. package/ios/Sources/VoiceRecorder/{CurrentRecordingStatus.swift → Core/CurrentRecordingStatus.swift} +1 -0
  55. package/ios/Sources/VoiceRecorder/Core/ErrorCodes.swift +16 -0
  56. package/ios/Sources/VoiceRecorder/{Messages.swift → Core/Messages.swift} +1 -0
  57. package/ios/Sources/VoiceRecorder/{RecordData.swift → Core/RecordData.swift} +6 -0
  58. package/ios/Sources/VoiceRecorder/Core/RecordOptions.swift +11 -0
  59. package/ios/Sources/VoiceRecorder/Core/ResponseFormat.swift +22 -0
  60. package/ios/Sources/VoiceRecorder/{ResponseGenerator.swift → Core/ResponseGenerator.swift} +6 -0
  61. package/ios/Sources/VoiceRecorder/{CustomMediaRecorder.swift → Platform/CustomMediaRecorder.swift} +25 -1
  62. package/ios/Sources/VoiceRecorder/Service/VoiceRecorderService.swift +128 -0
  63. package/ios/Sources/VoiceRecorder/Service/VoiceRecorderServiceError.swift +14 -0
  64. package/package.json +10 -4
  65. package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/CurrentRecordingStatus.java +0 -8
  66. package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/NotSupportedOsVersion.java +0 -3
  67. package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/RecordOptions.java +0 -3
  68. package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/VoiceRecorder.java +0 -205
  69. package/dist/esm/VoiceRecorderImpl.d.ts +0 -27
  70. package/dist/esm/VoiceRecorderImpl.js.map +0 -1
  71. package/dist/esm/helper/get-blob-duration.js.map +0 -1
  72. package/dist/esm/predefined-web-responses.js.map +0 -1
  73. package/ios/Sources/VoiceRecorder/RecordOptions.swift +0 -8
  74. package/ios/Sources/VoiceRecorder/VoiceRecorder.swift +0 -170
  75. /package/dist/esm/{helper → platform/web}/get-blob-duration.d.ts +0 -0
  76. /package/dist/esm/{helper → platform/web}/get-blob-duration.js +0 -0
@@ -1,8 +1,8 @@
1
1
  import { Filesystem } from '@capacitor/filesystem';
2
2
  import write_blob from 'capacitor-blob-writer';
3
- import getBlobDuration from "./helper/get-blob-duration";
3
+ import getBlobDuration from './get-blob-duration';
4
4
  import { alreadyRecordingError, couldNotQueryPermissionStatusError, deviceCannotVoiceRecordError, emptyRecordingError, failedToFetchRecordingError, failedToRecordError, failureResponse, missingPermissionError, recordingHasNotStartedError, successResponse, } from './predefined-web-responses';
5
- // these mime types will be checked one by one in order until one of them is found to be supported by the current browser
5
+ /** Preferred MIME types to probe in order of fallback. */
6
6
  const POSSIBLE_MIME_TYPES = {
7
7
  'audio/aac': '.aac',
8
8
  'audio/webm;codecs=opus': '.ogg',
@@ -10,13 +10,19 @@ const POSSIBLE_MIME_TYPES = {
10
10
  'audio/webm': '.ogg',
11
11
  'audio/ogg;codecs=opus': '.ogg',
12
12
  };
13
+ /** Creates a promise that never resolves. */
13
14
  const neverResolvingPromise = () => new Promise(() => undefined);
15
+ /** Browser implementation backed by MediaRecorder and Capacitor Filesystem. */
14
16
  export class VoiceRecorderImpl {
15
17
  constructor() {
18
+ /** Active MediaRecorder instance, if recording. */
16
19
  this.mediaRecorder = null;
20
+ /** Collected data chunks from MediaRecorder. */
17
21
  this.chunks = [];
22
+ /** Promise resolved when the recorder stops and payload is ready. */
18
23
  this.pendingResult = neverResolvingPromise();
19
24
  }
25
+ /** Returns whether the browser can start a recording session. */
20
26
  static async canDeviceVoiceRecord() {
21
27
  var _a;
22
28
  if (((_a = navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia) == null || VoiceRecorderImpl.getSupportedMimeType() == null) {
@@ -26,6 +32,7 @@ export class VoiceRecorderImpl {
26
32
  return successResponse();
27
33
  }
28
34
  }
35
+ /** Starts a recording session using MediaRecorder. */
29
36
  async startRecording(options) {
30
37
  if (this.mediaRecorder != null) {
31
38
  throw alreadyRecordingError();
@@ -43,6 +50,7 @@ export class VoiceRecorderImpl {
43
50
  .then((stream) => this.onSuccessfullyStartedRecording(stream, options))
44
51
  .catch(this.onFailedToStartRecording.bind(this));
45
52
  }
53
+ /** Stops the current recording and resolves the pending payload. */
46
54
  async stopRecording() {
47
55
  if (this.mediaRecorder == null) {
48
56
  throw recordingHasNotStartedError();
@@ -59,6 +67,7 @@ export class VoiceRecorderImpl {
59
67
  this.prepareInstanceForNextOperation();
60
68
  }
61
69
  }
70
+ /** Returns whether the browser has microphone permission. */
62
71
  static async hasAudioRecordingPermission() {
63
72
  // Safari does not support navigator.permissions.query
64
73
  if (!navigator.permissions.query) {
@@ -78,6 +87,7 @@ export class VoiceRecorderImpl {
78
87
  throw couldNotQueryPermissionStatusError();
79
88
  });
80
89
  }
90
+ /** Requests microphone permission from the browser. */
81
91
  static async requestAudioRecordingPermission() {
82
92
  const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => failureResponse());
83
93
  if (havingPermission.value) {
@@ -88,6 +98,7 @@ export class VoiceRecorderImpl {
88
98
  .then(() => successResponse())
89
99
  .catch(() => failureResponse());
90
100
  }
101
+ /** Pauses the recording session when supported. */
91
102
  pauseRecording() {
92
103
  if (this.mediaRecorder == null) {
93
104
  throw recordingHasNotStartedError();
@@ -100,6 +111,7 @@ export class VoiceRecorderImpl {
100
111
  return Promise.resolve(failureResponse());
101
112
  }
102
113
  }
114
+ /** Resumes a paused recording session when supported. */
103
115
  resumeRecording() {
104
116
  if (this.mediaRecorder == null) {
105
117
  throw recordingHasNotStartedError();
@@ -112,6 +124,7 @@ export class VoiceRecorderImpl {
112
124
  return Promise.resolve(failureResponse());
113
125
  }
114
126
  }
127
+ /** Returns the current recording status from MediaRecorder. */
115
128
  getCurrentStatus() {
116
129
  if (this.mediaRecorder == null) {
117
130
  return Promise.resolve({ status: 'NONE' });
@@ -126,12 +139,14 @@ export class VoiceRecorderImpl {
126
139
  return Promise.resolve({ status: 'NONE' });
127
140
  }
128
141
  }
142
+ /** Returns the first supported MIME type, if any. */
129
143
  static getSupportedMimeType() {
130
144
  if ((MediaRecorder === null || MediaRecorder === void 0 ? void 0 : MediaRecorder.isTypeSupported) == null)
131
145
  return null;
132
146
  const foundSupportedType = Object.keys(POSSIBLE_MIME_TYPES).find((type) => MediaRecorder.isTypeSupported(type));
133
147
  return foundSupportedType !== null && foundSupportedType !== void 0 ? foundSupportedType : null;
134
148
  }
149
+ /** Initializes MediaRecorder and wires up handlers. */
135
150
  onSuccessfullyStartedRecording(stream, options) {
136
151
  this.pendingResult = new Promise((resolve, reject) => {
137
152
  this.mediaRecorder = new MediaRecorder(stream);
@@ -179,10 +194,12 @@ export class VoiceRecorderImpl {
179
194
  });
180
195
  return successResponse();
181
196
  }
197
+ /** Handles failures from getUserMedia. */
182
198
  onFailedToStartRecording() {
183
199
  this.prepareInstanceForNextOperation();
184
200
  throw failedToRecordError();
185
201
  }
202
+ /** Converts a Blob payload into a base64 string. */
186
203
  static blobToBase64(blob) {
187
204
  return new Promise((resolve) => {
188
205
  const reader = new FileReader();
@@ -195,6 +212,7 @@ export class VoiceRecorderImpl {
195
212
  reader.readAsDataURL(blob);
196
213
  });
197
214
  }
215
+ /** Resets state for the next recording attempt. */
198
216
  prepareInstanceForNextOperation() {
199
217
  if (this.mediaRecorder != null && this.mediaRecorder.state === 'recording') {
200
218
  try {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceRecorderImpl.js","sourceRoot":"","sources":["../../../../src/platform/web/VoiceRecorderImpl.ts"],"names":[],"mappings":"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","sourcesContent":["import {Filesystem} from '@capacitor/filesystem';\nimport write_blob from 'capacitor-blob-writer';\n\nimport type {\n Base64String,\n CurrentRecordingStatus,\n GenericResponse,\n RecordingData,\n RecordingOptions,\n} from '../../definitions';\n\nimport getBlobDuration from './get-blob-duration';\nimport {\n alreadyRecordingError,\n couldNotQueryPermissionStatusError,\n deviceCannotVoiceRecordError,\n emptyRecordingError,\n failedToFetchRecordingError,\n failedToRecordError,\n failureResponse,\n missingPermissionError,\n recordingHasNotStartedError,\n successResponse,\n} from './predefined-web-responses';\n\n/** Preferred MIME types to probe in order of fallback. */\nconst POSSIBLE_MIME_TYPES = {\n 'audio/aac': '.aac',\n 'audio/webm;codecs=opus': '.ogg',\n 'audio/mp4': '.mp3',\n 'audio/webm': '.ogg',\n 'audio/ogg;codecs=opus': '.ogg',\n};\n\n/** Creates a promise that never resolves. */\nconst neverResolvingPromise = (): Promise<any> => new Promise(() => undefined);\n\n/** Browser implementation backed by MediaRecorder and Capacitor Filesystem. */\nexport class VoiceRecorderImpl {\n /** Active MediaRecorder instance, if recording. */\n private mediaRecorder: MediaRecorder | null = null;\n /** Collected data chunks from MediaRecorder. */\n private chunks: any[] = [];\n /** Promise resolved when the recorder stops and payload is ready. */\n private pendingResult: Promise<RecordingData> = neverResolvingPromise();\n\n /** Returns whether the browser can start a recording session. */\n public static async canDeviceVoiceRecord(): Promise<GenericResponse> {\n if (navigator?.mediaDevices?.getUserMedia == null || VoiceRecorderImpl.getSupportedMimeType() == null) {\n return failureResponse();\n } else {\n return successResponse();\n }\n }\n\n /** Starts a recording session using MediaRecorder. */\n public async startRecording(options?: RecordingOptions): Promise<GenericResponse> {\n if (this.mediaRecorder != null) {\n throw alreadyRecordingError();\n }\n const deviceCanRecord = await VoiceRecorderImpl.canDeviceVoiceRecord();\n if (!deviceCanRecord.value) {\n throw deviceCannotVoiceRecordError();\n }\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => successResponse());\n if (!havingPermission.value) {\n throw missingPermissionError();\n }\n\n return navigator.mediaDevices\n .getUserMedia({audio: true})\n .then((stream) => this.onSuccessfullyStartedRecording(stream, options))\n .catch(this.onFailedToStartRecording.bind(this));\n }\n\n /** Stops the current recording and resolves the pending payload. */\n public async stopRecording(): Promise<RecordingData> {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n try {\n this.mediaRecorder.stop();\n this.mediaRecorder.stream.getTracks().forEach((track) => track.stop());\n return this.pendingResult;\n } catch (ignore) {\n throw failedToFetchRecordingError();\n } finally {\n this.prepareInstanceForNextOperation();\n }\n }\n\n /** Returns whether the browser has microphone permission. */\n public static async hasAudioRecordingPermission(): Promise<GenericResponse> {\n // Safari does not support navigator.permissions.query\n if (!navigator.permissions.query) {\n if (navigator.mediaDevices !== undefined) {\n return navigator.mediaDevices\n .getUserMedia({audio: true})\n .then(() => successResponse())\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n }\n return navigator.permissions\n .query({name: 'microphone' as any})\n .then((result) => ({value: result.state === 'granted'}))\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n\n /** Requests microphone permission from the browser. */\n public static async requestAudioRecordingPermission(): Promise<GenericResponse> {\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => failureResponse());\n if (havingPermission.value) {\n return successResponse();\n }\n\n return navigator.mediaDevices\n .getUserMedia({audio: true})\n .then(() => successResponse())\n .catch(() => failureResponse());\n }\n\n /** Pauses the recording session when supported. */\n public pauseRecording(): Promise<GenericResponse> {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n } else if (this.mediaRecorder.state === 'recording') {\n this.mediaRecorder.pause();\n return Promise.resolve(successResponse());\n } else {\n return Promise.resolve(failureResponse());\n }\n }\n\n /** Resumes a paused recording session when supported. */\n public resumeRecording(): Promise<GenericResponse> {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n } else if (this.mediaRecorder.state === 'paused') {\n this.mediaRecorder.resume();\n return Promise.resolve(successResponse());\n } else {\n return Promise.resolve(failureResponse());\n }\n }\n\n /** Returns the current recording status from MediaRecorder. */\n public getCurrentStatus(): Promise<CurrentRecordingStatus> {\n if (this.mediaRecorder == null) {\n return Promise.resolve({status: 'NONE'});\n } else if (this.mediaRecorder.state === 'recording') {\n return Promise.resolve({status: 'RECORDING'});\n } else if (this.mediaRecorder.state === 'paused') {\n return Promise.resolve({status: 'PAUSED'});\n } else {\n return Promise.resolve({status: 'NONE'});\n }\n }\n\n /** Returns the first supported MIME type, if any. */\n public static getSupportedMimeType<T extends keyof typeof POSSIBLE_MIME_TYPES>(): T | null {\n if (MediaRecorder?.isTypeSupported == null) return null;\n\n const foundSupportedType = Object.keys(POSSIBLE_MIME_TYPES).find((type) => MediaRecorder.isTypeSupported(type)) as\n | T\n | undefined;\n\n return foundSupportedType ?? null;\n }\n\n /** Initializes MediaRecorder and wires up handlers. */\n private onSuccessfullyStartedRecording(stream: MediaStream, options?: RecordingOptions): GenericResponse {\n this.pendingResult = new Promise((resolve, reject) => {\n this.mediaRecorder = new MediaRecorder(stream);\n this.mediaRecorder.onerror = () => {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n };\n this.mediaRecorder.onstop = async () => {\n const mimeType = VoiceRecorderImpl.getSupportedMimeType();\n if (mimeType == null) {\n this.prepareInstanceForNextOperation();\n reject(failedToFetchRecordingError());\n return;\n }\n const blobVoiceRecording = new Blob(this.chunks, {type: mimeType});\n if (blobVoiceRecording.size <= 0) {\n this.prepareInstanceForNextOperation();\n reject(emptyRecordingError());\n return;\n }\n\n let uri: string | undefined = undefined;\n let recordDataBase64 = '';\n if (options?.directory) {\n const subDirectory = options.subDirectory?.match(/^\\/?(.+[^/])\\/?$/)?.[1] ?? '';\n const path = `${subDirectory}/recording-${new Date().getTime()}${POSSIBLE_MIME_TYPES[mimeType]}`;\n\n await write_blob({\n blob: blobVoiceRecording,\n directory: options.directory,\n fast_mode: true,\n path,\n recursive: true,\n });\n\n ({uri} = await Filesystem.getUri({directory: options.directory, path}));\n } else {\n recordDataBase64 = await VoiceRecorderImpl.blobToBase64(blobVoiceRecording);\n }\n\n const recordingDuration = await getBlobDuration(blobVoiceRecording);\n this.prepareInstanceForNextOperation();\n resolve({value: {recordDataBase64, mimeType, msDuration: recordingDuration * 1000, uri}});\n };\n this.mediaRecorder.ondataavailable = (event: any) => this.chunks.push(event.data);\n this.mediaRecorder.start();\n });\n return successResponse();\n }\n\n /** Handles failures from getUserMedia. */\n private onFailedToStartRecording(): GenericResponse {\n this.prepareInstanceForNextOperation();\n throw failedToRecordError();\n }\n\n /** Converts a Blob payload into a base64 string. */\n private static blobToBase64(blob: Blob): Promise<Base64String> {\n return new Promise((resolve) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n const recordingResult = String(reader.result);\n const splitResult = recordingResult.split('base64,');\n const toResolve = splitResult.length > 1 ? splitResult[1] : recordingResult;\n resolve(toResolve.trim());\n };\n reader.readAsDataURL(blob);\n });\n }\n\n /** Resets state for the next recording attempt. */\n private prepareInstanceForNextOperation(): void {\n if (this.mediaRecorder != null && this.mediaRecorder.state === 'recording') {\n try {\n this.mediaRecorder.stop();\n } catch (ignore) {\n console.warn('Failed to stop recording during cleanup');\n }\n }\n this.pendingResult = neverResolvingPromise();\n this.mediaRecorder = null;\n this.chunks = [];\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-blob-duration.js","sourceRoot":"","sources":["../../../../src/platform/web/get-blob-duration.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,IAAmB;IACvD,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACpD,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtD,WAAW,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,GAAG,EAAE;YAChD,2EAA2E;YAC3E,IAAI,WAAW,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACpC,WAAW,CAAC,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC;gBAClD,WAAW,CAAC,YAAY,GAAG,GAAG,EAAE;oBAC5B,WAAW,CAAC,YAAY,GAAG,IAAI,CAAC;oBAChC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;oBAC9B,WAAW,CAAC,WAAW,GAAG,CAAC,CAAC;gBAChC,CAAC,CAAC;YACN,CAAC;iBAAM,CAAC;gBACJ,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAClC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,WAAW,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;YAC5B,MAAM,KAAK,GAAI,KAAoB,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACjF,MAAM,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,WAAW,CAAC,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAE9E,OAAO,SAAS,CAAC;AACrB,CAAC","sourcesContent":["/**\n * @param {Blob | string} blob\n * @returns {Promise<number>} Blob duration in seconds.\n */\nexport default function getBlobDuration(blob: Blob | string): Promise<number> {\n const tempVideoEl = document.createElement('video');\n if (!tempVideoEl) throw new Error('Failed to create video element');\n const durationP = new Promise<number>((resolve, reject) => {\n tempVideoEl.addEventListener('loadedmetadata', () => {\n // Chrome bug: https://bugs.chromium.org/p/chromium/issues/detail?id=642012\n if (tempVideoEl.duration === Infinity) {\n tempVideoEl.currentTime = Number.MAX_SAFE_INTEGER;\n tempVideoEl.ontimeupdate = () => {\n tempVideoEl.ontimeupdate = null;\n resolve(tempVideoEl.duration);\n tempVideoEl.currentTime = 0;\n };\n } else {\n resolve(tempVideoEl.duration);\n }\n });\n\n tempVideoEl.onerror = (event) => {\n const error = (event as ErrorEvent).error || new Error('Unknown error occurred');\n reject(error);\n };\n });\n\n tempVideoEl.src = typeof blob === 'string' ? blob : URL.createObjectURL(blob);\n\n return durationP;\n}\n"]}
@@ -1,12 +1,23 @@
1
- import type { GenericResponse } from './definitions';
1
+ import type { GenericResponse } from '../../definitions';
2
+ /** Success wrapper for boolean plugin responses. */
2
3
  export declare const successResponse: () => GenericResponse;
4
+ /** Failure wrapper for boolean plugin responses. */
3
5
  export declare const failureResponse: () => GenericResponse;
6
+ /** Error for missing microphone permission. */
4
7
  export declare const missingPermissionError: () => Error;
8
+ /** Error for attempting to start while already recording. */
5
9
  export declare const alreadyRecordingError: () => Error;
10
+ /** Error for microphone in use by another app or recorder. */
6
11
  export declare const microphoneBeingUsedError: () => Error;
12
+ /** Error for devices that cannot record audio. */
7
13
  export declare const deviceCannotVoiceRecordError: () => Error;
14
+ /** Error for recorder start failures. */
8
15
  export declare const failedToRecordError: () => Error;
16
+ /** Error for empty or zero-length recordings. */
9
17
  export declare const emptyRecordingError: () => Error;
18
+ /** Error for stopping without an active recording. */
10
19
  export declare const recordingHasNotStartedError: () => Error;
20
+ /** Error for failures when fetching recording data. */
11
21
  export declare const failedToFetchRecordingError: () => Error;
22
+ /** Error for browsers that do not support permission queries. */
12
23
  export declare const couldNotQueryPermissionStatusError: () => Error;
@@ -1,12 +1,23 @@
1
+ /** Success wrapper for boolean plugin responses. */
1
2
  export const successResponse = () => ({ value: true });
3
+ /** Failure wrapper for boolean plugin responses. */
2
4
  export const failureResponse = () => ({ value: false });
5
+ /** Error for missing microphone permission. */
3
6
  export const missingPermissionError = () => new Error('MISSING_PERMISSION');
7
+ /** Error for attempting to start while already recording. */
4
8
  export const alreadyRecordingError = () => new Error('ALREADY_RECORDING');
9
+ /** Error for microphone in use by another app or recorder. */
5
10
  export const microphoneBeingUsedError = () => new Error('MICROPHONE_BEING_USED');
11
+ /** Error for devices that cannot record audio. */
6
12
  export const deviceCannotVoiceRecordError = () => new Error('DEVICE_CANNOT_VOICE_RECORD');
13
+ /** Error for recorder start failures. */
7
14
  export const failedToRecordError = () => new Error('FAILED_TO_RECORD');
15
+ /** Error for empty or zero-length recordings. */
8
16
  export const emptyRecordingError = () => new Error('EMPTY_RECORDING');
17
+ /** Error for stopping without an active recording. */
9
18
  export const recordingHasNotStartedError = () => new Error('RECORDING_HAS_NOT_STARTED');
19
+ /** Error for failures when fetching recording data. */
10
20
  export const failedToFetchRecordingError = () => new Error('FAILED_TO_FETCH_RECORDING');
21
+ /** Error for browsers that do not support permission queries. */
11
22
  export const couldNotQueryPermissionStatusError = () => new Error('COULD_NOT_QUERY_PERMISSION_STATUS');
12
23
  //# sourceMappingURL=predefined-web-responses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predefined-web-responses.js","sourceRoot":"","sources":["../../../../src/platform/web/predefined-web-responses.ts"],"names":[],"mappings":"AAEA,oDAAoD;AACpD,MAAM,CAAC,MAAM,eAAe,GAAG,GAAoB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACxE,oDAAoD;AACpD,MAAM,CAAC,MAAM,eAAe,GAAG,GAAoB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AAEzE,+CAA+C;AAC/C,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAU,EAAE,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;AACnF,6DAA6D;AAC7D,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAU,EAAE,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;AACjF,8DAA8D;AAC9D,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAU,EAAE,CAAC,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;AACxF,kDAAkD;AAClD,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAU,EAAE,CAAC,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;AACjG,yCAAyC;AACzC,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAU,EAAE,CAAC,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;AAC9E,iDAAiD;AACjD,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAU,EAAE,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAE7E,sDAAsD;AACtD,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAU,EAAE,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;AAC/F,uDAAuD;AACvD,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAU,EAAE,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;AAE/F,iEAAiE;AACjE,MAAM,CAAC,MAAM,kCAAkC,GAAG,GAAU,EAAE,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC","sourcesContent":["import type { GenericResponse } from '../../definitions';\n\n/** Success wrapper for boolean plugin responses. */\nexport const successResponse = (): GenericResponse => ({ value: true });\n/** Failure wrapper for boolean plugin responses. */\nexport const failureResponse = (): GenericResponse => ({ value: false });\n\n/** Error for missing microphone permission. */\nexport const missingPermissionError = (): Error => new Error('MISSING_PERMISSION');\n/** Error for attempting to start while already recording. */\nexport const alreadyRecordingError = (): Error => new Error('ALREADY_RECORDING');\n/** Error for microphone in use by another app or recorder. */\nexport const microphoneBeingUsedError = (): Error => new Error('MICROPHONE_BEING_USED');\n/** Error for devices that cannot record audio. */\nexport const deviceCannotVoiceRecordError = (): Error => new Error('DEVICE_CANNOT_VOICE_RECORD');\n/** Error for recorder start failures. */\nexport const failedToRecordError = (): Error => new Error('FAILED_TO_RECORD');\n/** Error for empty or zero-length recordings. */\nexport const emptyRecordingError = (): Error => new Error('EMPTY_RECORDING');\n\n/** Error for stopping without an active recording. */\nexport const recordingHasNotStartedError = (): Error => new Error('RECORDING_HAS_NOT_STARTED');\n/** Error for failures when fetching recording data. */\nexport const failedToFetchRecordingError = (): Error => new Error('FAILED_TO_FETCH_RECORDING');\n\n/** Error for browsers that do not support permission queries. */\nexport const couldNotQueryPermissionStatusError = (): Error => new Error('COULD_NOT_QUERY_PERMISSION_STATUS');\n"]}
@@ -0,0 +1,47 @@
1
+ import type { ResponseFormat } from '../core/response-format';
2
+ import type { CurrentRecordingStatus, GenericResponse, RecordingData, RecordingOptions } from '../definitions';
3
+ /** Platform abstraction used by the service layer. */
4
+ export interface VoiceRecorderPlatform {
5
+ /** Checks whether the device can record audio. */
6
+ canDeviceVoiceRecord(): Promise<GenericResponse>;
7
+ /** Returns whether microphone permission is currently granted. */
8
+ hasAudioRecordingPermission(): Promise<GenericResponse>;
9
+ /** Requests microphone permission from the user. */
10
+ requestAudioRecordingPermission(): Promise<GenericResponse>;
11
+ /** Starts a recording session. */
12
+ startRecording(options?: RecordingOptions): Promise<GenericResponse>;
13
+ /** Stops the current recording session and returns the payload. */
14
+ stopRecording(): Promise<RecordingData>;
15
+ /** Pauses the recording session when supported. */
16
+ pauseRecording(): Promise<GenericResponse>;
17
+ /** Resumes a paused recording session when supported. */
18
+ resumeRecording(): Promise<GenericResponse>;
19
+ /** Returns the current recording state. */
20
+ getCurrentStatus(): Promise<CurrentRecordingStatus>;
21
+ }
22
+ /** Orchestrates platform calls and normalizes responses when requested. */
23
+ export declare class VoiceRecorderService {
24
+ /** Selected response format derived from plugin config. */
25
+ private readonly responseFormat;
26
+ /** Platform adapter that performs the actual recording work. */
27
+ private readonly platform;
28
+ constructor(platform: VoiceRecorderPlatform, responseFormat: ResponseFormat);
29
+ /** Checks whether the device can record audio. */
30
+ canDeviceVoiceRecord(): Promise<GenericResponse>;
31
+ /** Returns whether microphone permission is currently granted. */
32
+ hasAudioRecordingPermission(): Promise<GenericResponse>;
33
+ /** Requests microphone permission from the user. */
34
+ requestAudioRecordingPermission(): Promise<GenericResponse>;
35
+ /** Starts a recording session. */
36
+ startRecording(options?: RecordingOptions): Promise<GenericResponse>;
37
+ /** Stops the recording session and formats the payload if needed. */
38
+ stopRecording(): Promise<RecordingData>;
39
+ /** Pauses the recording session when supported. */
40
+ pauseRecording(): Promise<GenericResponse>;
41
+ /** Resumes a paused recording session when supported. */
42
+ resumeRecording(): Promise<GenericResponse>;
43
+ /** Returns the current recording state. */
44
+ getCurrentStatus(): Promise<CurrentRecordingStatus>;
45
+ /** Wraps calls to apply canonical error codes when requested. */
46
+ private execute;
47
+ }
@@ -0,0 +1,60 @@
1
+ import { attachCanonicalErrorCode } from '../core/error-codes';
2
+ import { normalizeRecordingData } from '../core/recording-contract';
3
+ /** Orchestrates platform calls and normalizes responses when requested. */
4
+ export class VoiceRecorderService {
5
+ constructor(platform, responseFormat) {
6
+ this.platform = platform;
7
+ this.responseFormat = responseFormat;
8
+ }
9
+ /** Checks whether the device can record audio. */
10
+ canDeviceVoiceRecord() {
11
+ return this.execute(() => this.platform.canDeviceVoiceRecord());
12
+ }
13
+ /** Returns whether microphone permission is currently granted. */
14
+ hasAudioRecordingPermission() {
15
+ return this.execute(() => this.platform.hasAudioRecordingPermission());
16
+ }
17
+ /** Requests microphone permission from the user. */
18
+ requestAudioRecordingPermission() {
19
+ return this.execute(() => this.platform.requestAudioRecordingPermission());
20
+ }
21
+ /** Starts a recording session. */
22
+ startRecording(options) {
23
+ return this.execute(() => this.platform.startRecording(options));
24
+ }
25
+ /** Stops the recording session and formats the payload if needed. */
26
+ async stopRecording() {
27
+ return this.execute(async () => {
28
+ const data = await this.platform.stopRecording();
29
+ if (this.responseFormat === 'normalized') {
30
+ return normalizeRecordingData(data);
31
+ }
32
+ return data;
33
+ });
34
+ }
35
+ /** Pauses the recording session when supported. */
36
+ pauseRecording() {
37
+ return this.execute(() => this.platform.pauseRecording());
38
+ }
39
+ /** Resumes a paused recording session when supported. */
40
+ resumeRecording() {
41
+ return this.execute(() => this.platform.resumeRecording());
42
+ }
43
+ /** Returns the current recording state. */
44
+ getCurrentStatus() {
45
+ return this.execute(() => this.platform.getCurrentStatus());
46
+ }
47
+ /** Wraps calls to apply canonical error codes when requested. */
48
+ async execute(fn) {
49
+ try {
50
+ return await fn();
51
+ }
52
+ catch (error) {
53
+ if (this.responseFormat === 'normalized') {
54
+ attachCanonicalErrorCode(error);
55
+ }
56
+ throw error;
57
+ }
58
+ }
59
+ }
60
+ //# sourceMappingURL=VoiceRecorderService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceRecorderService.js","sourceRoot":"","sources":["../../../src/service/VoiceRecorderService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AA6BpE,2EAA2E;AAC3E,MAAM,OAAO,oBAAoB;IAM7B,YAAmB,QAA+B,EAAE,cAA8B;QAC9E,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACzC,CAAC;IAED,kDAAkD;IAC3C,oBAAoB;QACvB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,kEAAkE;IAC3D,2BAA2B;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,2BAA2B,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,oDAAoD;IAC7C,+BAA+B;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,+BAA+B,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,kCAAkC;IAC3B,cAAc,CAAC,OAA0B;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,qEAAqE;IAC9D,KAAK,CAAC,aAAa;QACtB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;YACjD,IAAI,IAAI,CAAC,cAAc,KAAK,YAAY,EAAE,CAAC;gBACvC,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,mDAAmD;IAC5C,cAAc;QACjB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,yDAAyD;IAClD,eAAe;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,2CAA2C;IACpC,gBAAgB;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,iEAAiE;IACzD,KAAK,CAAC,OAAO,CAAI,EAAoB;QACzC,IAAI,CAAC;YACD,OAAO,MAAM,EAAE,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,cAAc,KAAK,YAAY,EAAE,CAAC;gBACvC,wBAAwB,CAAC,KAAK,CAAC,CAAC;YACpC,CAAC;YACD,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CACJ","sourcesContent":["import { attachCanonicalErrorCode } from '../core/error-codes';\nimport { normalizeRecordingData } from '../core/recording-contract';\nimport type { ResponseFormat } from '../core/response-format';\nimport type {\n CurrentRecordingStatus,\n GenericResponse,\n RecordingData,\n RecordingOptions,\n} from '../definitions';\n\n/** Platform abstraction used by the service layer. */\nexport interface VoiceRecorderPlatform {\n /** Checks whether the device can record audio. */\n canDeviceVoiceRecord(): Promise<GenericResponse>;\n /** Returns whether microphone permission is currently granted. */\n hasAudioRecordingPermission(): Promise<GenericResponse>;\n /** Requests microphone permission from the user. */\n requestAudioRecordingPermission(): Promise<GenericResponse>;\n /** Starts a recording session. */\n startRecording(options?: RecordingOptions): Promise<GenericResponse>;\n /** Stops the current recording session and returns the payload. */\n stopRecording(): Promise<RecordingData>;\n /** Pauses the recording session when supported. */\n pauseRecording(): Promise<GenericResponse>;\n /** Resumes a paused recording session when supported. */\n resumeRecording(): Promise<GenericResponse>;\n /** Returns the current recording state. */\n getCurrentStatus(): Promise<CurrentRecordingStatus>;\n}\n\n/** Orchestrates platform calls and normalizes responses when requested. */\nexport class VoiceRecorderService {\n /** Selected response format derived from plugin config. */\n private readonly responseFormat: ResponseFormat;\n /** Platform adapter that performs the actual recording work. */\n private readonly platform: VoiceRecorderPlatform;\n\n public constructor(platform: VoiceRecorderPlatform, responseFormat: ResponseFormat) {\n this.platform = platform;\n this.responseFormat = responseFormat;\n }\n\n /** Checks whether the device can record audio. */\n public canDeviceVoiceRecord(): Promise<GenericResponse> {\n return this.execute(() => this.platform.canDeviceVoiceRecord());\n }\n\n /** Returns whether microphone permission is currently granted. */\n public hasAudioRecordingPermission(): Promise<GenericResponse> {\n return this.execute(() => this.platform.hasAudioRecordingPermission());\n }\n\n /** Requests microphone permission from the user. */\n public requestAudioRecordingPermission(): Promise<GenericResponse> {\n return this.execute(() => this.platform.requestAudioRecordingPermission());\n }\n\n /** Starts a recording session. */\n public startRecording(options?: RecordingOptions): Promise<GenericResponse> {\n return this.execute(() => this.platform.startRecording(options));\n }\n\n /** Stops the recording session and formats the payload if needed. */\n public async stopRecording(): Promise<RecordingData> {\n return this.execute(async () => {\n const data = await this.platform.stopRecording();\n if (this.responseFormat === 'normalized') {\n return normalizeRecordingData(data);\n }\n return data;\n });\n }\n\n /** Pauses the recording session when supported. */\n public pauseRecording(): Promise<GenericResponse> {\n return this.execute(() => this.platform.pauseRecording());\n }\n\n /** Resumes a paused recording session when supported. */\n public resumeRecording(): Promise<GenericResponse> {\n return this.execute(() => this.platform.resumeRecording());\n }\n\n /** Returns the current recording state. */\n public getCurrentStatus(): Promise<CurrentRecordingStatus> {\n return this.execute(() => this.platform.getCurrentStatus());\n }\n\n /** Wraps calls to apply canonical error codes when requested. */\n private async execute<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (this.responseFormat === 'normalized') {\n attachCanonicalErrorCode(error);\n }\n throw error;\n }\n }\n}\n"]}
package/dist/esm/web.d.ts CHANGED
@@ -1,13 +1,24 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
2
  import type { CurrentRecordingStatus, GenericResponse, RecordingData, RecordingOptions, VoiceRecorderPlugin } from './definitions';
3
+ /** Web implementation of the VoiceRecorder Capacitor plugin. */
3
4
  export declare class VoiceRecorderWeb extends WebPlugin implements VoiceRecorderPlugin {
4
- private voiceRecorderInstance;
5
+ /** Service layer that normalizes behavior and errors. */
6
+ private readonly service;
7
+ constructor();
8
+ /** Checks whether the browser can record audio. */
5
9
  canDeviceVoiceRecord(): Promise<GenericResponse>;
10
+ /** Returns whether microphone permission is currently granted. */
6
11
  hasAudioRecordingPermission(): Promise<GenericResponse>;
12
+ /** Requests microphone permission from the user. */
7
13
  requestAudioRecordingPermission(): Promise<GenericResponse>;
14
+ /** Starts a recording session. */
8
15
  startRecording(options?: RecordingOptions): Promise<GenericResponse>;
16
+ /** Stops the current recording session and returns the payload. */
9
17
  stopRecording(): Promise<RecordingData>;
18
+ /** Pauses the recording session when supported. */
10
19
  pauseRecording(): Promise<GenericResponse>;
20
+ /** Resumes a paused recording session when supported. */
11
21
  resumeRecording(): Promise<GenericResponse>;
22
+ /** Returns the current recording state. */
12
23
  getCurrentStatus(): Promise<CurrentRecordingStatus>;
13
24
  }
package/dist/esm/web.js CHANGED
@@ -1,33 +1,47 @@
1
- import { WebPlugin } from '@capacitor/core';
2
- import { VoiceRecorderImpl } from './VoiceRecorderImpl';
1
+ import { Capacitor, WebPlugin } from '@capacitor/core';
2
+ import { VoiceRecorderWebAdapter } from './adapters/VoiceRecorderWebAdapter';
3
+ import { getResponseFormatFromConfig } from './core/response-format';
4
+ import { VoiceRecorderService } from './service/VoiceRecorderService';
5
+ /** Web implementation of the VoiceRecorder Capacitor plugin. */
3
6
  export class VoiceRecorderWeb extends WebPlugin {
4
7
  constructor() {
5
- super(...arguments);
6
- this.voiceRecorderInstance = new VoiceRecorderImpl();
8
+ var _a, _b;
9
+ super();
10
+ const pluginConfig = (_b = (_a = Capacitor === null || Capacitor === void 0 ? void 0 : Capacitor.config) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.VoiceRecorder;
11
+ const responseFormat = getResponseFormatFromConfig(pluginConfig);
12
+ this.service = new VoiceRecorderService(new VoiceRecorderWebAdapter(), responseFormat);
7
13
  }
14
+ /** Checks whether the browser can record audio. */
8
15
  canDeviceVoiceRecord() {
9
- return VoiceRecorderImpl.canDeviceVoiceRecord();
16
+ return this.service.canDeviceVoiceRecord();
10
17
  }
18
+ /** Returns whether microphone permission is currently granted. */
11
19
  hasAudioRecordingPermission() {
12
- return VoiceRecorderImpl.hasAudioRecordingPermission();
20
+ return this.service.hasAudioRecordingPermission();
13
21
  }
22
+ /** Requests microphone permission from the user. */
14
23
  requestAudioRecordingPermission() {
15
- return VoiceRecorderImpl.requestAudioRecordingPermission();
24
+ return this.service.requestAudioRecordingPermission();
16
25
  }
26
+ /** Starts a recording session. */
17
27
  startRecording(options) {
18
- return this.voiceRecorderInstance.startRecording(options);
28
+ return this.service.startRecording(options);
19
29
  }
30
+ /** Stops the current recording session and returns the payload. */
20
31
  stopRecording() {
21
- return this.voiceRecorderInstance.stopRecording();
32
+ return this.service.stopRecording();
22
33
  }
34
+ /** Pauses the recording session when supported. */
23
35
  pauseRecording() {
24
- return this.voiceRecorderInstance.pauseRecording();
36
+ return this.service.pauseRecording();
25
37
  }
38
+ /** Resumes a paused recording session when supported. */
26
39
  resumeRecording() {
27
- return this.voiceRecorderInstance.resumeRecording();
40
+ return this.service.resumeRecording();
28
41
  }
42
+ /** Returns the current recording state. */
29
43
  getCurrentStatus() {
30
- return this.voiceRecorderInstance.getCurrentStatus();
44
+ return this.service.getCurrentStatus();
31
45
  }
32
46
  }
33
47
  //# sourceMappingURL=web.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AASxD,MAAM,OAAO,gBAAiB,SAAQ,SAAS;IAA/C;;QACU,0BAAqB,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAiC1D,CAAC;IA/BQ,oBAAoB;QACzB,OAAO,iBAAiB,CAAC,oBAAoB,EAAE,CAAC;IAClD,CAAC;IAEM,2BAA2B;QAChC,OAAO,iBAAiB,CAAC,2BAA2B,EAAE,CAAC;IACzD,CAAC;IAEM,+BAA+B;QACpC,OAAO,iBAAiB,CAAC,+BAA+B,EAAE,CAAC;IAC7D,CAAC;IAEM,cAAc,CAAC,OAA0B;QAC9C,OAAO,IAAI,CAAC,qBAAqB,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC5D,CAAC;IAEM,aAAa;QAClB,OAAO,IAAI,CAAC,qBAAqB,CAAC,aAAa,EAAE,CAAC;IACpD,CAAC;IAEM,cAAc;QACnB,OAAO,IAAI,CAAC,qBAAqB,CAAC,cAAc,EAAE,CAAC;IACrD,CAAC;IAEM,eAAe;QACpB,OAAO,IAAI,CAAC,qBAAqB,CAAC,eAAe,EAAE,CAAC;IACtD,CAAC;IAEM,gBAAgB;QACrB,OAAO,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,EAAE,CAAC;IACvD,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport { VoiceRecorderImpl } from './VoiceRecorderImpl';\nimport type {\n CurrentRecordingStatus,\n GenericResponse,\n RecordingData,\n RecordingOptions,\n VoiceRecorderPlugin,\n} from './definitions';\n\nexport class VoiceRecorderWeb extends WebPlugin implements VoiceRecorderPlugin {\n private voiceRecorderInstance = new VoiceRecorderImpl();\n\n public canDeviceVoiceRecord(): Promise<GenericResponse> {\n return VoiceRecorderImpl.canDeviceVoiceRecord();\n }\n\n public hasAudioRecordingPermission(): Promise<GenericResponse> {\n return VoiceRecorderImpl.hasAudioRecordingPermission();\n }\n\n public requestAudioRecordingPermission(): Promise<GenericResponse> {\n return VoiceRecorderImpl.requestAudioRecordingPermission();\n }\n\n public startRecording(options?: RecordingOptions): Promise<GenericResponse> {\n return this.voiceRecorderInstance.startRecording(options);\n }\n\n public stopRecording(): Promise<RecordingData> {\n return this.voiceRecorderInstance.stopRecording();\n }\n\n public pauseRecording(): Promise<GenericResponse> {\n return this.voiceRecorderInstance.pauseRecording();\n }\n\n public resumeRecording(): Promise<GenericResponse> {\n return this.voiceRecorderInstance.resumeRecording();\n }\n\n public getCurrentStatus(): Promise<CurrentRecordingStatus> {\n return this.voiceRecorderInstance.getCurrentStatus();\n }\n}\n"]}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAQrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE,gEAAgE;AAChE,MAAM,OAAO,gBAAiB,SAAQ,SAAS;IAI7C;;QACE,KAAK,EAAE,CAAC;QACR,MAAM,YAAY,GAAG,MAAA,MAAC,SAAiB,aAAjB,SAAS,uBAAT,SAAS,CAAU,MAAM,0CAAE,OAAO,0CAAE,aAAa,CAAC;QACxE,MAAM,cAAc,GAAG,2BAA2B,CAAC,YAAY,CAAC,CAAC;QACjE,IAAI,CAAC,OAAO,GAAG,IAAI,oBAAoB,CAAC,IAAI,uBAAuB,EAAE,EAAE,cAAc,CAAC,CAAC;IACzF,CAAC;IAED,mDAAmD;IAC5C,oBAAoB;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAC7C,CAAC;IAED,kEAAkE;IAC3D,2BAA2B;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,2BAA2B,EAAE,CAAC;IACpD,CAAC;IAED,oDAAoD;IAC7C,+BAA+B;QACpC,OAAO,IAAI,CAAC,OAAO,CAAC,+BAA+B,EAAE,CAAC;IACxD,CAAC;IAED,kCAAkC;IAC3B,cAAc,CAAC,OAA0B;QAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,mEAAmE;IAC5D,aAAa;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;IACtC,CAAC;IAED,mDAAmD;IAC5C,cAAc;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;IACvC,CAAC;IAED,yDAAyD;IAClD,eAAe;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;IACxC,CAAC;IAED,2CAA2C;IACpC,gBAAgB;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;IACzC,CAAC;CACF","sourcesContent":["import { Capacitor, WebPlugin } from '@capacitor/core';\n\nimport { VoiceRecorderWebAdapter } from './adapters/VoiceRecorderWebAdapter';\nimport { getResponseFormatFromConfig } from './core/response-format';\nimport type {\n CurrentRecordingStatus,\n GenericResponse,\n RecordingData,\n RecordingOptions,\n VoiceRecorderPlugin,\n} from './definitions';\nimport { VoiceRecorderService } from './service/VoiceRecorderService';\n\n/** Web implementation of the VoiceRecorder Capacitor plugin. */\nexport class VoiceRecorderWeb extends WebPlugin implements VoiceRecorderPlugin {\n /** Service layer that normalizes behavior and errors. */\n private readonly service: VoiceRecorderService;\n\n public constructor() {\n super();\n const pluginConfig = (Capacitor as any)?.config?.plugins?.VoiceRecorder;\n const responseFormat = getResponseFormatFromConfig(pluginConfig);\n this.service = new VoiceRecorderService(new VoiceRecorderWebAdapter(), responseFormat);\n }\n\n /** Checks whether the browser can record audio. */\n public canDeviceVoiceRecord(): Promise<GenericResponse> {\n return this.service.canDeviceVoiceRecord();\n }\n\n /** Returns whether microphone permission is currently granted. */\n public hasAudioRecordingPermission(): Promise<GenericResponse> {\n return this.service.hasAudioRecordingPermission();\n }\n\n /** Requests microphone permission from the user. */\n public requestAudioRecordingPermission(): Promise<GenericResponse> {\n return this.service.requestAudioRecordingPermission();\n }\n\n /** Starts a recording session. */\n public startRecording(options?: RecordingOptions): Promise<GenericResponse> {\n return this.service.startRecording(options);\n }\n\n /** Stops the current recording session and returns the payload. */\n public stopRecording(): Promise<RecordingData> {\n return this.service.stopRecording();\n }\n\n /** Pauses the recording session when supported. */\n public pauseRecording(): Promise<GenericResponse> {\n return this.service.pauseRecording();\n }\n\n /** Resumes a paused recording session when supported. */\n public resumeRecording(): Promise<GenericResponse> {\n return this.service.resumeRecording();\n }\n\n /** Returns the current recording state. */\n public getCurrentStatus(): Promise<CurrentRecordingStatus> {\n return this.service.getCurrentStatus();\n }\n}\n"]}