@magmamath/students-features 1.3.23-rc.44 → 1.3.23-rc.46

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 (42) hide show
  1. package/dist/commonjs/features/voice/index.js +11 -0
  2. package/dist/commonjs/features/voice/index.js.map +1 -1
  3. package/dist/commonjs/features/voice/playing/hooks/useVoicePlayerLifecycle.js +53 -0
  4. package/dist/commonjs/features/voice/playing/hooks/useVoicePlayerLifecycle.js.map +1 -0
  5. package/dist/commonjs/features/voice/playing/hooks/useVoiceTranscriptionController.js +3 -26
  6. package/dist/commonjs/features/voice/playing/hooks/useVoiceTranscriptionController.js.map +1 -1
  7. package/dist/commonjs/features/voice/playing/model/Player.model.js +18 -11
  8. package/dist/commonjs/features/voice/playing/model/Player.model.js.map +1 -1
  9. package/dist/commonjs/features/voice/playing/model/VoicePlayer.model.js +12 -0
  10. package/dist/commonjs/features/voice/playing/model/VoicePlayer.model.js.map +1 -1
  11. package/dist/module/features/voice/index.js +1 -0
  12. package/dist/module/features/voice/index.js.map +1 -1
  13. package/dist/module/features/voice/playing/hooks/useVoicePlayerLifecycle.js +48 -0
  14. package/dist/module/features/voice/playing/hooks/useVoicePlayerLifecycle.js.map +1 -0
  15. package/dist/module/features/voice/playing/hooks/useVoiceTranscriptionController.js +3 -26
  16. package/dist/module/features/voice/playing/hooks/useVoiceTranscriptionController.js.map +1 -1
  17. package/dist/module/features/voice/playing/model/Player.model.js +19 -10
  18. package/dist/module/features/voice/playing/model/Player.model.js.map +1 -1
  19. package/dist/module/features/voice/playing/model/VoicePlayer.model.js +12 -0
  20. package/dist/module/features/voice/playing/model/VoicePlayer.model.js.map +1 -1
  21. package/dist/typescript/commonjs/features/voice/index.d.ts +1 -0
  22. package/dist/typescript/commonjs/features/voice/index.d.ts.map +1 -1
  23. package/dist/typescript/commonjs/features/voice/playing/hooks/useVoicePlayerLifecycle.d.ts +15 -0
  24. package/dist/typescript/commonjs/features/voice/playing/hooks/useVoicePlayerLifecycle.d.ts.map +1 -0
  25. package/dist/typescript/commonjs/features/voice/playing/hooks/useVoiceTranscriptionController.d.ts.map +1 -1
  26. package/dist/typescript/commonjs/features/voice/playing/model/Player.model.d.ts.map +1 -1
  27. package/dist/typescript/commonjs/features/voice/playing/model/VoicePlayer.model.d.ts +1 -0
  28. package/dist/typescript/commonjs/features/voice/playing/model/VoicePlayer.model.d.ts.map +1 -1
  29. package/dist/typescript/module/features/voice/index.d.ts +1 -0
  30. package/dist/typescript/module/features/voice/index.d.ts.map +1 -1
  31. package/dist/typescript/module/features/voice/playing/hooks/useVoicePlayerLifecycle.d.ts +15 -0
  32. package/dist/typescript/module/features/voice/playing/hooks/useVoicePlayerLifecycle.d.ts.map +1 -0
  33. package/dist/typescript/module/features/voice/playing/hooks/useVoiceTranscriptionController.d.ts.map +1 -1
  34. package/dist/typescript/module/features/voice/playing/model/Player.model.d.ts.map +1 -1
  35. package/dist/typescript/module/features/voice/playing/model/VoicePlayer.model.d.ts +1 -0
  36. package/dist/typescript/module/features/voice/playing/model/VoicePlayer.model.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/src/features/voice/index.ts +1 -0
  39. package/src/features/voice/playing/hooks/useVoicePlayerLifecycle.ts +64 -0
  40. package/src/features/voice/playing/hooks/useVoiceTranscriptionController.ts +3 -33
  41. package/src/features/voice/playing/model/Player.model.ts +18 -10
  42. package/src/features/voice/playing/model/VoicePlayer.model.ts +13 -0
@@ -69,6 +69,17 @@ Object.keys(_VoiceTranscription).forEach(function (key) {
69
69
  }
70
70
  });
71
71
  });
72
+ var _useVoicePlayerLifecycle = require("./playing/hooks/useVoicePlayerLifecycle.js");
73
+ Object.keys(_useVoicePlayerLifecycle).forEach(function (key) {
74
+ if (key === "default" || key === "__esModule") return;
75
+ if (key in exports && exports[key] === _useVoicePlayerLifecycle[key]) return;
76
+ Object.defineProperty(exports, key, {
77
+ enumerable: true,
78
+ get: function () {
79
+ return _useVoicePlayerLifecycle[key];
80
+ }
81
+ });
82
+ });
72
83
  var _VoiceIcon = require("./playing/components/VoiceIcon.js");
73
84
  Object.keys(_VoiceIcon).forEach(function (key) {
74
85
  if (key === "default" || key === "__esModule") return;
@@ -1 +1 @@
1
- {"version":3,"names":["_VoiceRecord","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_VoiceRecordModel","_VoiceRecordDeleteModal","_VoiceRecordUndoModal","_VoicePlayerModel","_VoiceTranscription","_VoiceIcon","_constants","_types"],"sourceRoot":"../../../../src","sources":["features/voice/index.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_VoiceRecord","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_VoiceRecordModel","_VoiceRecordDeleteModal","_VoiceRecordUndoModal","_VoicePlayerModel","_VoiceTranscription","_useVoicePlayerLifecycle","_VoiceIcon","_constants","_types"],"sourceRoot":"../../../../src","sources":["features/voice/index.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useVoicePlayerLifecycle = void 0;
7
+ var _react = require("react");
8
+ var _helpers = require("../../helpers.js");
9
+ // Owns playback engine mutations (init/reset/setCurrentAttempt/stopAudio).
10
+ // VoiceTranscription stays read-only; consumers call this once per page.
11
+ const useVoicePlayerLifecycle = ({
12
+ model,
13
+ answers,
14
+ attemptOffset,
15
+ attemptsCount,
16
+ problemId
17
+ }) => {
18
+ const activeAttempt = (0, _helpers.getActiveAttempt)(attemptOffset, attemptsCount);
19
+ const answersKey = (0, _react.useMemo)(() => answers.map(a => `${a._id}:${a.audioFileId ?? ''}`).join(','), [answers]);
20
+ const hasAnyAudio = (0, _react.useMemo)(() => answers.some(a => !!a.audioFileId), [answers]);
21
+ const answersRef = (0, _react.useRef)(answers);
22
+ answersRef.current = answers;
23
+ (0, _react.useEffect)(() => {
24
+ model.reinitializePlayer();
25
+ return () => {
26
+ model.stopAudio();
27
+ };
28
+ }, [model]);
29
+ (0, _react.useEffect)(() => {
30
+ model.resetPlayer();
31
+ }, [problemId]);
32
+ (0, _react.useEffect)(() => {
33
+ if (answersRef.current.some(a => a.audioFileId)) {
34
+ model.initializeWithAudios(answersRef.current);
35
+ }
36
+ }, [model, answersKey]);
37
+ (0, _react.useEffect)(() => {
38
+ // Skip stopAudio if VoiceSource has already queued playback for activeAttempt (timeline auto-progress).
39
+ if (model.$currentAttempt.getState() !== activeAttempt) {
40
+ model.stopAudio();
41
+ }
42
+ model.setCurrentAttempt(activeAttempt);
43
+ if (activeAttempt !== null) {
44
+ model.loader.loadTranscriptForAttempt(activeAttempt);
45
+ }
46
+ }, [model, activeAttempt, answersKey]);
47
+ return {
48
+ activeAttempt,
49
+ hasAnyAudio
50
+ };
51
+ };
52
+ exports.useVoicePlayerLifecycle = useVoicePlayerLifecycle;
53
+ //# sourceMappingURL=useVoicePlayerLifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_react","require","_helpers","useVoicePlayerLifecycle","model","answers","attemptOffset","attemptsCount","problemId","activeAttempt","getActiveAttempt","answersKey","useMemo","map","a","_id","audioFileId","join","hasAnyAudio","some","answersRef","useRef","current","useEffect","reinitializePlayer","stopAudio","resetPlayer","initializeWithAudios","$currentAttempt","getState","setCurrentAttempt","loader","loadTranscriptForAttempt","exports"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/hooks/useVoicePlayerLifecycle.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,QAAA,GAAAD,OAAA;AAYA;AACA;AACO,MAAME,uBAAuB,GAAGA,CAAC;EACtCC,KAAK;EACLC,OAAO;EACPC,aAAa;EACbC,aAAa;EACbC;AACM,CAAC,KAAK;EACZ,MAAMC,aAAa,GAAG,IAAAC,yBAAgB,EAACJ,aAAa,EAAEC,aAAa,CAAC;EAEpE,MAAMI,UAAU,GAAG,IAAAC,cAAO,EACxB,MAAMP,OAAO,CAACQ,GAAG,CAAEC,CAAC,IAAK,GAAGA,CAAC,CAACC,GAAG,IAAID,CAAC,CAACE,WAAW,IAAI,EAAE,EAAE,CAAC,CAACC,IAAI,CAAC,GAAG,CAAC,EACrE,CAACZ,OAAO,CACV,CAAC;EAED,MAAMa,WAAW,GAAG,IAAAN,cAAO,EAAC,MAAMP,OAAO,CAACc,IAAI,CAAEL,CAAC,IAAK,CAAC,CAACA,CAAC,CAACE,WAAW,CAAC,EAAE,CAACX,OAAO,CAAC,CAAC;EAElF,MAAMe,UAAU,GAAG,IAAAC,aAAM,EAAChB,OAAO,CAAC;EAClCe,UAAU,CAACE,OAAO,GAAGjB,OAAO;EAE5B,IAAAkB,gBAAS,EAAC,MAAM;IACdnB,KAAK,CAACoB,kBAAkB,CAAC,CAAC;IAC1B,OAAO,MAAM;MACXpB,KAAK,CAACqB,SAAS,CAAC,CAAC;IACnB,CAAC;EACH,CAAC,EAAE,CAACrB,KAAK,CAAC,CAAC;EAEX,IAAAmB,gBAAS,EAAC,MAAM;IACdnB,KAAK,CAACsB,WAAW,CAAC,CAAC;EACrB,CAAC,EAAE,CAAClB,SAAS,CAAC,CAAC;EAEf,IAAAe,gBAAS,EAAC,MAAM;IACd,IAAIH,UAAU,CAACE,OAAO,CAACH,IAAI,CAAEL,CAAC,IAAKA,CAAC,CAACE,WAAW,CAAC,EAAE;MACjDZ,KAAK,CAACuB,oBAAoB,CAACP,UAAU,CAACE,OAAO,CAAC;IAChD;EACF,CAAC,EAAE,CAAClB,KAAK,EAAEO,UAAU,CAAC,CAAC;EAEvB,IAAAY,gBAAS,EAAC,MAAM;IACd;IACA,IAAInB,KAAK,CAACwB,eAAe,CAACC,QAAQ,CAAC,CAAC,KAAKpB,aAAa,EAAE;MACtDL,KAAK,CAACqB,SAAS,CAAC,CAAC;IACnB;IACArB,KAAK,CAAC0B,iBAAiB,CAACrB,aAAa,CAAC;IACtC,IAAIA,aAAa,KAAK,IAAI,EAAE;MAC1BL,KAAK,CAAC2B,MAAM,CAACC,wBAAwB,CAACvB,aAAa,CAAC;IACtD;EACF,CAAC,EAAE,CAACL,KAAK,EAAEK,aAAa,EAAEE,UAAU,CAAC,CAAC;EAEtC,OAAO;IAAEF,aAAa;IAAES;EAAY,CAAC;AACvC,CAAC;AAAAe,OAAA,CAAA9B,uBAAA,GAAAA,uBAAA","ignoreList":[]}
@@ -24,7 +24,6 @@ const useVoiceTranscriptionController = ({
24
24
  } = (0, _reactI18next.useTranslation)();
25
25
  const [playerState, isLoadingTranscripts, isTranslationActive, translations, isTranslating] = (0, _effectorReact.useUnit)([model.$playerState, model.loader.loadTranscriptForAttempt.pending, model.translation.$isActive, model.translation.$translations, model.translation.translate.pending]);
26
26
  const activeAttempt = (0, _helpers.getActiveAttempt)(attemptOffset, attemptsCount);
27
- const answersKey = (0, _react.useMemo)(() => answers.map(a => `${a._id}:${a.audioFileId ?? ''}`).join(','), [answers]);
28
27
  const activeAudioFileId = activeAttempt !== null ? answers?.[activeAttempt - 1]?.audioFileId : undefined;
29
28
  const hasActiveAudio = activeAudioFileId !== undefined;
30
29
  const anyAttemptHasAudio = (0, _react.useMemo)(() => answers.some(a => !!a.audioFileId), [answers]);
@@ -39,39 +38,17 @@ const useVoiceTranscriptionController = ({
39
38
  const isTranslationLoading = showTranslation && !cachedTranslation && isTranslating;
40
39
  const displayText = showTranslation ? cachedTranslation ?? activeTranscript : hasTranscriptText ? activeTranscript : t('voice.transcriptNotAvailable');
41
40
 
42
- // Lifecycle effects
43
- const answersRef = (0, _react.useRef)(answers);
44
- answersRef.current = answers;
41
+ // UI-only lifecycle: collapse the dropdown on mount/unmount and on problem
42
+ // change. Playback engine mutations (init/reset/setCurrentAttempt/stopAudio)
43
+ // are owned by useVoicePlayerLifecycle, called by the page-level consumer.
45
44
  (0, _react.useEffect)(() => {
46
- model.reinitializePlayer();
47
45
  return () => {
48
- model.stopAudio();
49
46
  model.dropdown.setExpanded(false);
50
47
  };
51
48
  }, [model]);
52
49
  (0, _react.useEffect)(() => {
53
50
  model.dropdown.setExpanded(false);
54
- model.resetPlayer();
55
51
  }, [problemId]);
56
- (0, _react.useEffect)(() => {
57
- if (answersRef.current.some(a => a.audioFileId)) {
58
- model.initializeWithAudios(answersRef.current);
59
- }
60
- }, [model, answersKey]);
61
- (0, _react.useEffect)(() => {
62
- // Skip stopAudio when the audio is already targeting activeAttempt — that's
63
- // the case when the timeline scrubber auto-progressed to this attempt and
64
- // VoiceSource just activated playback for it. Stopping here would kill the
65
- // freshly-started audio (race: activation runs synchronously inside the
66
- // timeline tick, this effect fires after React commits).
67
- if (model.$currentAttempt.getState() !== activeAttempt) {
68
- model.stopAudio();
69
- }
70
- model.setCurrentAttempt(activeAttempt);
71
- if (activeAttempt !== null) {
72
- model.loader.loadTranscriptForAttempt(activeAttempt);
73
- }
74
- }, [model, activeAttempt, answersKey]);
75
52
 
76
53
  // Auto-activate translation once per (problemId, activeAttempt) when translatable
77
54
  const autoActivatedAttempts = (0, _react.useRef)(new Set());
@@ -1 +1 @@
1
- {"version":3,"names":["_effectorReact","require","_react","_reactI18next","_constants","_helpers","_supportedLanguages","_i18n","useVoiceTranscriptionController","model","answers","attemptOffset","attemptsCount","problemId","t","useText","i18n","useTranslation","playerState","isLoadingTranscripts","isTranslationActive","translations","isTranslating","useUnit","$playerState","loader","loadTranscriptForAttempt","pending","translation","$isActive","$translations","translate","activeAttempt","getActiveAttempt","answersKey","useMemo","map","a","_id","audioFileId","join","activeAudioFileId","undefined","hasActiveAudio","anyAttemptHasAudio","some","cachedEntry","getCachedTranscript","activeTranscript","text","hasTranscriptText","NO_AUDIO_BE_MESSAGE","isActiveTranscriptLoading","isSourceSameAsTarget","language","resolveGoogleLanguageCode","canTranslate","cachedTranslation","showTranslation","isTranslationLoading","displayText","answersRef","useRef","current","useEffect","reinitializePlayer","stopAudio","dropdown","setExpanded","resetPlayer","initializeWithAudios","$currentAttempt","getState","setCurrentAttempt","autoActivatedAttempts","Set","clear","has","add","setActive","attemptNumber","targetLanguage","doneData","watch","result","onPlayPress","useCallback","togglePlayPause","onTranslationToggle","toggle","display","isLoading","flags","actions","exports"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/hooks/useVoiceTranscriptionController.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_effectorReact","require","_react","_reactI18next","_constants","_helpers","_supportedLanguages","_i18n","useVoiceTranscriptionController","model","answers","attemptOffset","attemptsCount","problemId","t","useText","i18n","useTranslation","playerState","isLoadingTranscripts","isTranslationActive","translations","isTranslating","useUnit","$playerState","loader","loadTranscriptForAttempt","pending","translation","$isActive","$translations","translate","activeAttempt","getActiveAttempt","activeAudioFileId","audioFileId","undefined","hasActiveAudio","anyAttemptHasAudio","useMemo","some","a","cachedEntry","getCachedTranscript","activeTranscript","text","hasTranscriptText","NO_AUDIO_BE_MESSAGE","isActiveTranscriptLoading","isSourceSameAsTarget","language","resolveGoogleLanguageCode","canTranslate","cachedTranslation","showTranslation","isTranslationLoading","displayText","useEffect","dropdown","setExpanded","autoActivatedAttempts","useRef","Set","current","clear","has","add","setActive","attemptNumber","targetLanguage","doneData","watch","result","onPlayPress","useCallback","togglePlayPause","onTranslationToggle","toggle","display","isLoading","flags","actions","exports"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/hooks/useVoiceTranscriptionController.ts"],"mappings":"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","ignoreList":[]}
@@ -12,7 +12,18 @@ let PlayerState = exports.PlayerState = /*#__PURE__*/function (PlayerState) {
12
12
  PlayerState["LOADING"] = "loading";
13
13
  PlayerState["IDLE"] = "idle";
14
14
  return PlayerState;
15
- }({});
15
+ }({}); // audio.play() returns a promise that rejects with AbortError when a subsequent
16
+ // pause() interrupts it. That's expected during pause/resume cycles; suppress noise.
17
+ const safePlay = audio => {
18
+ const result = audio.play();
19
+ if (result && typeof result.catch === 'function') {
20
+ ;
21
+ result.catch(err => {
22
+ if (err?.name === 'AbortError') return;
23
+ throw err;
24
+ });
25
+ }
26
+ };
16
27
  class PlayerModel {
17
28
  player = (0, _expoAudio.createAudioPlayer)();
18
29
  stopped = false;
@@ -53,19 +64,15 @@ class PlayerModel {
53
64
  this.player.replace(uri);
54
65
  });
55
66
  seek = (0, _effector.createEffect)(async seconds => {
56
- if (!this.player) {
57
- console.warn('Cannot seek: audio player not initialized');
58
- return;
59
- }
60
- if (!this.player.isLoaded) {
61
- console.warn('Cannot seek: audio player not loaded');
62
- return;
63
- }
67
+ // Silently no-op when not loaded — the next play() effect's waitForLoad will
68
+ // pick up the desired offset implicitly via replace/load. Warning was noisy
69
+ // during pause→scrub→play cycles where isLoaded briefly flips false.
70
+ if (!this.player?.isLoaded) return;
64
71
  await this.player.seekTo(seconds);
65
72
  });
66
73
  resume = (0, _effector.createEffect)(() => {
67
74
  if (this.player) {
68
- this.player.play();
75
+ safePlay(this.player);
69
76
  this.setPlayerState(PlayerState.PLAYING);
70
77
  } else {
71
78
  console.warn('Cannot resume: audio player not initialized');
@@ -91,7 +98,7 @@ class PlayerModel {
91
98
  this.setPlayerState(PlayerState.IDLE);
92
99
  }
93
100
  });
94
- this.player.play();
101
+ safePlay(this.player);
95
102
  this.setPlayerState(PlayerState.PLAYING);
96
103
  } else {
97
104
  setTimeout(waitForLoad, 10);
@@ -1 +1 @@
1
- {"version":3,"names":["_effector","require","_expoAudio","PlayerState","exports","PlayerModel","player","createAudioPlayer","stopped","primedUri","reset","createEvent","setPlayerState","playbackFinished","$playerState","restore","IDLE","setupAudioMode","createEffect","setAudioModeAsync","playsInSilentMode","shouldPlayInBackground","interruptionMode","pause","PAUSED","console","warn","stop","replace","prime","uri","seek","seconds","isLoaded","seekTo","resume","play","PLAYING","waitForLoad","unsubscribe","addListener","status","didJustFinish","remove","setTimeout","reinitialize","release","error"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/model/Player.model.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_effector","require","_expoAudio","PlayerState","exports","safePlay","audio","result","play","catch","err","name","PlayerModel","player","createAudioPlayer","stopped","primedUri","reset","createEvent","setPlayerState","playbackFinished","$playerState","restore","IDLE","setupAudioMode","createEffect","setAudioModeAsync","playsInSilentMode","shouldPlayInBackground","interruptionMode","pause","PAUSED","console","warn","stop","replace","prime","uri","seek","seconds","isLoaded","seekTo","resume","PLAYING","waitForLoad","unsubscribe","addListener","status","didJustFinish","remove","setTimeout","reinitialize","release","error"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/model/Player.model.ts"],"mappings":"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","ignoreList":[]}
@@ -53,9 +53,21 @@ class VoicePlayerModel {
53
53
  this.translation.clearCache();
54
54
  };
55
55
  initializeWithAudios(answerAudio) {
56
+ // Skip clear+rebuild when content matches — re-init mid-playback drops audioUri and races with in-flight togglePlayPause.
57
+ if (this.collectionMatchesAudios(answerAudio)) return;
56
58
  this.collection.clear();
57
59
  this.initializeCollectionFromAudios(answerAudio);
58
60
  }
61
+ collectionMatchesAudios(audios) {
62
+ for (let i = 0; i < audios.length; i++) {
63
+ const audio = audios[i];
64
+ if (!audio.audioFileId) continue;
65
+ const attemptNumber = i + 1;
66
+ const existing = this.collection.get(attemptNumber);
67
+ if (!existing || existing.audioFileId !== audio.audioFileId) return false;
68
+ }
69
+ return true;
70
+ }
59
71
  isAudioLoading(attemptNumber) {
60
72
  return this.collection.get(attemptNumber)?.audioLoading || false;
61
73
  }
@@ -1 +1 @@
1
- {"version":3,"names":["_effector","require","_TranscriptionsCollection","_VoiceFileDownloaderModel","_DropdownModel","_TranslationModel","_PlayerModel","_TranscriptionsDownloaderModel","_PlaybackController","VoicePlayerModel","collection","TranscriptionsCollection","dropdown","DropdownModel","playerModel","PlayerModel","setCurrentAttempt","createEvent","reset","$currentAttempt","restore","$playerState","pauseAudio","pause","seekAudio","seek","constructor","params","api","downloader","VoiceFileDownloaderModel","loader","TranscriptionsDownloaderModel","translation","TranslationModel","playback","PlaybackController","player","togglePlayPause","audios","initializeCollectionFromAudios","setupAudioMode","stopAudio","halt","preloadAudio","attemptNumber","target","getState","resetPlayer","releaseResources","clear","clearCache","initializeWithAudios","answerAudio","isAudioLoading","get","audioLoading","getAllAttempts","getAll","reinitializePlayer","reinitialize","cleanup","release","console","warn","forEach","audio","index","audioFileId","add","_id","hasDrawing","drawing","exports"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/model/VoicePlayer.model.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_effector","require","_TranscriptionsCollection","_VoiceFileDownloaderModel","_DropdownModel","_TranslationModel","_PlayerModel","_TranscriptionsDownloaderModel","_PlaybackController","VoicePlayerModel","collection","TranscriptionsCollection","dropdown","DropdownModel","playerModel","PlayerModel","setCurrentAttempt","createEvent","reset","$currentAttempt","restore","$playerState","pauseAudio","pause","seekAudio","seek","constructor","params","api","downloader","VoiceFileDownloaderModel","loader","TranscriptionsDownloaderModel","translation","TranslationModel","playback","PlaybackController","player","togglePlayPause","audios","initializeCollectionFromAudios","setupAudioMode","stopAudio","halt","preloadAudio","attemptNumber","target","getState","resetPlayer","releaseResources","clear","clearCache","initializeWithAudios","answerAudio","collectionMatchesAudios","i","length","audio","audioFileId","existing","get","isAudioLoading","audioLoading","getAllAttempts","getAll","reinitializePlayer","reinitialize","cleanup","release","console","warn","forEach","index","add","_id","hasDrawing","drawing","exports"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/model/VoicePlayer.model.ts"],"mappings":"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","ignoreList":[]}
@@ -6,6 +6,7 @@ export * from "./recording/modal/VoiceRecordDeleteModal.js";
6
6
  export * from "./recording/modal/VoiceRecordUndoModal.js";
7
7
  export * from "./playing/model/VoicePlayer.model.js";
8
8
  export * from "./playing/components/VoiceTranscription.js";
9
+ export * from "./playing/hooks/useVoicePlayerLifecycle.js";
9
10
  export * from "./playing/components/VoiceIcon.js";
10
11
  export * from "./constants.js";
11
12
  export * from "./types.js";
@@ -1 +1 @@
1
- {"version":3,"names":[],"sourceRoot":"../../../../src","sources":["features/voice/index.ts"],"mappings":";;AAAA,cAAc,uCAAoC;AAClD,cAAc,wCAAqC;AACnD,cAAc,6CAA0C;AACxD,cAAc,2CAAwC;AAEtD,cAAc,sCAAmC;AACjD,cAAc,4CAAyC;AAEvD,cAAc,mCAAgC;AAC9C,cAAc,gBAAa;AAC3B,cAAc,YAAS","ignoreList":[]}
1
+ {"version":3,"names":[],"sourceRoot":"../../../../src","sources":["features/voice/index.ts"],"mappings":";;AAAA,cAAc,uCAAoC;AAClD,cAAc,wCAAqC;AACnD,cAAc,6CAA0C;AACxD,cAAc,2CAAwC;AAEtD,cAAc,sCAAmC;AACjD,cAAc,4CAAyC;AACvD,cAAc,4CAAyC;AAEvD,cAAc,mCAAgC;AAC9C,cAAc,gBAAa;AAC3B,cAAc,YAAS","ignoreList":[]}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ import { useEffect, useMemo, useRef } from 'react';
4
+ import { getActiveAttempt } from "../../helpers.js";
5
+ // Owns playback engine mutations (init/reset/setCurrentAttempt/stopAudio).
6
+ // VoiceTranscription stays read-only; consumers call this once per page.
7
+ export const useVoicePlayerLifecycle = ({
8
+ model,
9
+ answers,
10
+ attemptOffset,
11
+ attemptsCount,
12
+ problemId
13
+ }) => {
14
+ const activeAttempt = getActiveAttempt(attemptOffset, attemptsCount);
15
+ const answersKey = useMemo(() => answers.map(a => `${a._id}:${a.audioFileId ?? ''}`).join(','), [answers]);
16
+ const hasAnyAudio = useMemo(() => answers.some(a => !!a.audioFileId), [answers]);
17
+ const answersRef = useRef(answers);
18
+ answersRef.current = answers;
19
+ useEffect(() => {
20
+ model.reinitializePlayer();
21
+ return () => {
22
+ model.stopAudio();
23
+ };
24
+ }, [model]);
25
+ useEffect(() => {
26
+ model.resetPlayer();
27
+ }, [problemId]);
28
+ useEffect(() => {
29
+ if (answersRef.current.some(a => a.audioFileId)) {
30
+ model.initializeWithAudios(answersRef.current);
31
+ }
32
+ }, [model, answersKey]);
33
+ useEffect(() => {
34
+ // Skip stopAudio if VoiceSource has already queued playback for activeAttempt (timeline auto-progress).
35
+ if (model.$currentAttempt.getState() !== activeAttempt) {
36
+ model.stopAudio();
37
+ }
38
+ model.setCurrentAttempt(activeAttempt);
39
+ if (activeAttempt !== null) {
40
+ model.loader.loadTranscriptForAttempt(activeAttempt);
41
+ }
42
+ }, [model, activeAttempt, answersKey]);
43
+ return {
44
+ activeAttempt,
45
+ hasAnyAudio
46
+ };
47
+ };
48
+ //# sourceMappingURL=useVoicePlayerLifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useEffect","useMemo","useRef","getActiveAttempt","useVoicePlayerLifecycle","model","answers","attemptOffset","attemptsCount","problemId","activeAttempt","answersKey","map","a","_id","audioFileId","join","hasAnyAudio","some","answersRef","current","reinitializePlayer","stopAudio","resetPlayer","initializeWithAudios","$currentAttempt","getState","setCurrentAttempt","loader","loadTranscriptForAttempt"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/hooks/useVoicePlayerLifecycle.ts"],"mappings":";;AAAA,SAASA,SAAS,EAAEC,OAAO,EAAEC,MAAM,QAAQ,OAAO;AAClD,SAASC,gBAAgB,QAAQ,kBAAe;AAYhD;AACA;AACA,OAAO,MAAMC,uBAAuB,GAAGA,CAAC;EACtCC,KAAK;EACLC,OAAO;EACPC,aAAa;EACbC,aAAa;EACbC;AACM,CAAC,KAAK;EACZ,MAAMC,aAAa,GAAGP,gBAAgB,CAACI,aAAa,EAAEC,aAAa,CAAC;EAEpE,MAAMG,UAAU,GAAGV,OAAO,CACxB,MAAMK,OAAO,CAACM,GAAG,CAAEC,CAAC,IAAK,GAAGA,CAAC,CAACC,GAAG,IAAID,CAAC,CAACE,WAAW,IAAI,EAAE,EAAE,CAAC,CAACC,IAAI,CAAC,GAAG,CAAC,EACrE,CAACV,OAAO,CACV,CAAC;EAED,MAAMW,WAAW,GAAGhB,OAAO,CAAC,MAAMK,OAAO,CAACY,IAAI,CAAEL,CAAC,IAAK,CAAC,CAACA,CAAC,CAACE,WAAW,CAAC,EAAE,CAACT,OAAO,CAAC,CAAC;EAElF,MAAMa,UAAU,GAAGjB,MAAM,CAACI,OAAO,CAAC;EAClCa,UAAU,CAACC,OAAO,GAAGd,OAAO;EAE5BN,SAAS,CAAC,MAAM;IACdK,KAAK,CAACgB,kBAAkB,CAAC,CAAC;IAC1B,OAAO,MAAM;MACXhB,KAAK,CAACiB,SAAS,CAAC,CAAC;IACnB,CAAC;EACH,CAAC,EAAE,CAACjB,KAAK,CAAC,CAAC;EAEXL,SAAS,CAAC,MAAM;IACdK,KAAK,CAACkB,WAAW,CAAC,CAAC;EACrB,CAAC,EAAE,CAACd,SAAS,CAAC,CAAC;EAEfT,SAAS,CAAC,MAAM;IACd,IAAImB,UAAU,CAACC,OAAO,CAACF,IAAI,CAAEL,CAAC,IAAKA,CAAC,CAACE,WAAW,CAAC,EAAE;MACjDV,KAAK,CAACmB,oBAAoB,CAACL,UAAU,CAACC,OAAO,CAAC;IAChD;EACF,CAAC,EAAE,CAACf,KAAK,EAAEM,UAAU,CAAC,CAAC;EAEvBX,SAAS,CAAC,MAAM;IACd;IACA,IAAIK,KAAK,CAACoB,eAAe,CAACC,QAAQ,CAAC,CAAC,KAAKhB,aAAa,EAAE;MACtDL,KAAK,CAACiB,SAAS,CAAC,CAAC;IACnB;IACAjB,KAAK,CAACsB,iBAAiB,CAACjB,aAAa,CAAC;IACtC,IAAIA,aAAa,KAAK,IAAI,EAAE;MAC1BL,KAAK,CAACuB,MAAM,CAACC,wBAAwB,CAACnB,aAAa,CAAC;IACtD;EACF,CAAC,EAAE,CAACL,KAAK,EAAEK,aAAa,EAAEC,UAAU,CAAC,CAAC;EAEtC,OAAO;IAAED,aAAa;IAAEO;EAAY,CAAC;AACvC,CAAC","ignoreList":[]}
@@ -20,7 +20,6 @@ export const useVoiceTranscriptionController = ({
20
20
  } = useTranslation();
21
21
  const [playerState, isLoadingTranscripts, isTranslationActive, translations, isTranslating] = useUnit([model.$playerState, model.loader.loadTranscriptForAttempt.pending, model.translation.$isActive, model.translation.$translations, model.translation.translate.pending]);
22
22
  const activeAttempt = getActiveAttempt(attemptOffset, attemptsCount);
23
- const answersKey = useMemo(() => answers.map(a => `${a._id}:${a.audioFileId ?? ''}`).join(','), [answers]);
24
23
  const activeAudioFileId = activeAttempt !== null ? answers?.[activeAttempt - 1]?.audioFileId : undefined;
25
24
  const hasActiveAudio = activeAudioFileId !== undefined;
26
25
  const anyAttemptHasAudio = useMemo(() => answers.some(a => !!a.audioFileId), [answers]);
@@ -35,39 +34,17 @@ export const useVoiceTranscriptionController = ({
35
34
  const isTranslationLoading = showTranslation && !cachedTranslation && isTranslating;
36
35
  const displayText = showTranslation ? cachedTranslation ?? activeTranscript : hasTranscriptText ? activeTranscript : t('voice.transcriptNotAvailable');
37
36
 
38
- // Lifecycle effects
39
- const answersRef = useRef(answers);
40
- answersRef.current = answers;
37
+ // UI-only lifecycle: collapse the dropdown on mount/unmount and on problem
38
+ // change. Playback engine mutations (init/reset/setCurrentAttempt/stopAudio)
39
+ // are owned by useVoicePlayerLifecycle, called by the page-level consumer.
41
40
  useEffect(() => {
42
- model.reinitializePlayer();
43
41
  return () => {
44
- model.stopAudio();
45
42
  model.dropdown.setExpanded(false);
46
43
  };
47
44
  }, [model]);
48
45
  useEffect(() => {
49
46
  model.dropdown.setExpanded(false);
50
- model.resetPlayer();
51
47
  }, [problemId]);
52
- useEffect(() => {
53
- if (answersRef.current.some(a => a.audioFileId)) {
54
- model.initializeWithAudios(answersRef.current);
55
- }
56
- }, [model, answersKey]);
57
- useEffect(() => {
58
- // Skip stopAudio when the audio is already targeting activeAttempt — that's
59
- // the case when the timeline scrubber auto-progressed to this attempt and
60
- // VoiceSource just activated playback for it. Stopping here would kill the
61
- // freshly-started audio (race: activation runs synchronously inside the
62
- // timeline tick, this effect fires after React commits).
63
- if (model.$currentAttempt.getState() !== activeAttempt) {
64
- model.stopAudio();
65
- }
66
- model.setCurrentAttempt(activeAttempt);
67
- if (activeAttempt !== null) {
68
- model.loader.loadTranscriptForAttempt(activeAttempt);
69
- }
70
- }, [model, activeAttempt, answersKey]);
71
48
 
72
49
  // Auto-activate translation once per (problemId, activeAttempt) when translatable
73
50
  const autoActivatedAttempts = useRef(new Set());
@@ -1 +1 @@
1
- {"version":3,"names":["useUnit","useCallback","useEffect","useMemo","useRef","useTranslation","NO_AUDIO_BE_MESSAGE","getActiveAttempt","resolveGoogleLanguageCode","useText","useVoiceTranscriptionController","model","answers","attemptOffset","attemptsCount","problemId","t","i18n","playerState","isLoadingTranscripts","isTranslationActive","translations","isTranslating","$playerState","loader","loadTranscriptForAttempt","pending","translation","$isActive","$translations","translate","activeAttempt","answersKey","map","a","_id","audioFileId","join","activeAudioFileId","undefined","hasActiveAudio","anyAttemptHasAudio","some","cachedEntry","getCachedTranscript","activeTranscript","text","hasTranscriptText","isActiveTranscriptLoading","isSourceSameAsTarget","language","canTranslate","cachedTranslation","showTranslation","isTranslationLoading","displayText","answersRef","current","reinitializePlayer","stopAudio","dropdown","setExpanded","resetPlayer","initializeWithAudios","$currentAttempt","getState","setCurrentAttempt","autoActivatedAttempts","Set","clear","has","add","setActive","attemptNumber","targetLanguage","doneData","watch","result","onPlayPress","togglePlayPause","onTranslationToggle","toggle","display","isLoading","flags","actions"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/hooks/useVoiceTranscriptionController.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useUnit","useCallback","useEffect","useMemo","useRef","useTranslation","NO_AUDIO_BE_MESSAGE","getActiveAttempt","resolveGoogleLanguageCode","useText","useVoiceTranscriptionController","model","answers","attemptOffset","attemptsCount","problemId","t","i18n","playerState","isLoadingTranscripts","isTranslationActive","translations","isTranslating","$playerState","loader","loadTranscriptForAttempt","pending","translation","$isActive","$translations","translate","activeAttempt","activeAudioFileId","audioFileId","undefined","hasActiveAudio","anyAttemptHasAudio","some","a","cachedEntry","getCachedTranscript","activeTranscript","text","hasTranscriptText","isActiveTranscriptLoading","isSourceSameAsTarget","language","canTranslate","cachedTranslation","showTranslation","isTranslationLoading","displayText","dropdown","setExpanded","autoActivatedAttempts","Set","current","clear","has","add","setActive","attemptNumber","targetLanguage","doneData","watch","result","onPlayPress","togglePlayPause","onTranslationToggle","toggle","display","isLoading","flags","actions"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/hooks/useVoiceTranscriptionController.ts"],"mappings":"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","ignoreList":[]}
@@ -9,6 +9,19 @@ export let PlayerState = /*#__PURE__*/function (PlayerState) {
9
9
  PlayerState["IDLE"] = "idle";
10
10
  return PlayerState;
11
11
  }({});
12
+
13
+ // audio.play() returns a promise that rejects with AbortError when a subsequent
14
+ // pause() interrupts it. That's expected during pause/resume cycles; suppress noise.
15
+ const safePlay = audio => {
16
+ const result = audio.play();
17
+ if (result && typeof result.catch === 'function') {
18
+ ;
19
+ result.catch(err => {
20
+ if (err?.name === 'AbortError') return;
21
+ throw err;
22
+ });
23
+ }
24
+ };
12
25
  export class PlayerModel {
13
26
  player = createAudioPlayer();
14
27
  stopped = false;
@@ -49,19 +62,15 @@ export class PlayerModel {
49
62
  this.player.replace(uri);
50
63
  });
51
64
  seek = createEffect(async seconds => {
52
- if (!this.player) {
53
- console.warn('Cannot seek: audio player not initialized');
54
- return;
55
- }
56
- if (!this.player.isLoaded) {
57
- console.warn('Cannot seek: audio player not loaded');
58
- return;
59
- }
65
+ // Silently no-op when not loaded — the next play() effect's waitForLoad will
66
+ // pick up the desired offset implicitly via replace/load. Warning was noisy
67
+ // during pause→scrub→play cycles where isLoaded briefly flips false.
68
+ if (!this.player?.isLoaded) return;
60
69
  await this.player.seekTo(seconds);
61
70
  });
62
71
  resume = createEffect(() => {
63
72
  if (this.player) {
64
- this.player.play();
73
+ safePlay(this.player);
65
74
  this.setPlayerState(PlayerState.PLAYING);
66
75
  } else {
67
76
  console.warn('Cannot resume: audio player not initialized');
@@ -87,7 +96,7 @@ export class PlayerModel {
87
96
  this.setPlayerState(PlayerState.IDLE);
88
97
  }
89
98
  });
90
- this.player.play();
99
+ safePlay(this.player);
91
100
  this.setPlayerState(PlayerState.PLAYING);
92
101
  } else {
93
102
  setTimeout(waitForLoad, 10);
@@ -1 +1 @@
1
- {"version":3,"names":["createEffect","createEvent","restore","createAudioPlayer","setAudioModeAsync","PlayerState","PlayerModel","player","stopped","primedUri","reset","setPlayerState","playbackFinished","$playerState","IDLE","setupAudioMode","playsInSilentMode","shouldPlayInBackground","interruptionMode","pause","PAUSED","console","warn","stop","replace","prime","uri","seek","seconds","isLoaded","seekTo","resume","play","PLAYING","waitForLoad","unsubscribe","addListener","status","didJustFinish","remove","setTimeout","reinitialize","release","error"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/model/Player.model.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["createEffect","createEvent","restore","createAudioPlayer","setAudioModeAsync","PlayerState","safePlay","audio","result","play","catch","err","name","PlayerModel","player","stopped","primedUri","reset","setPlayerState","playbackFinished","$playerState","IDLE","setupAudioMode","playsInSilentMode","shouldPlayInBackground","interruptionMode","pause","PAUSED","console","warn","stop","replace","prime","uri","seek","seconds","isLoaded","seekTo","resume","PLAYING","waitForLoad","unsubscribe","addListener","status","didJustFinish","remove","setTimeout","reinitialize","release","error"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/model/Player.model.ts"],"mappings":"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","ignoreList":[]}
@@ -49,9 +49,21 @@ export class VoicePlayerModel {
49
49
  this.translation.clearCache();
50
50
  };
51
51
  initializeWithAudios(answerAudio) {
52
+ // Skip clear+rebuild when content matches — re-init mid-playback drops audioUri and races with in-flight togglePlayPause.
53
+ if (this.collectionMatchesAudios(answerAudio)) return;
52
54
  this.collection.clear();
53
55
  this.initializeCollectionFromAudios(answerAudio);
54
56
  }
57
+ collectionMatchesAudios(audios) {
58
+ for (let i = 0; i < audios.length; i++) {
59
+ const audio = audios[i];
60
+ if (!audio.audioFileId) continue;
61
+ const attemptNumber = i + 1;
62
+ const existing = this.collection.get(attemptNumber);
63
+ if (!existing || existing.audioFileId !== audio.audioFileId) return false;
64
+ }
65
+ return true;
66
+ }
55
67
  isAudioLoading(attemptNumber) {
56
68
  return this.collection.get(attemptNumber)?.audioLoading || false;
57
69
  }
@@ -1 +1 @@
1
- {"version":3,"names":["createEvent","restore","TranscriptionsCollection","VoiceFileDownloaderModel","DropdownModel","TranslationModel","PlayerModel","TranscriptionsDownloaderModel","PlaybackController","VoicePlayerModel","collection","dropdown","playerModel","setCurrentAttempt","reset","$currentAttempt","$playerState","pauseAudio","pause","seekAudio","seek","constructor","params","api","downloader","loader","translation","playback","player","togglePlayPause","audios","initializeCollectionFromAudios","setupAudioMode","stopAudio","halt","preloadAudio","attemptNumber","target","getState","resetPlayer","releaseResources","clear","clearCache","initializeWithAudios","answerAudio","isAudioLoading","get","audioLoading","getAllAttempts","getAll","reinitializePlayer","reinitialize","cleanup","release","console","warn","forEach","audio","index","audioFileId","add","_id","hasDrawing","drawing"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/model/VoicePlayer.model.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["createEvent","restore","TranscriptionsCollection","VoiceFileDownloaderModel","DropdownModel","TranslationModel","PlayerModel","TranscriptionsDownloaderModel","PlaybackController","VoicePlayerModel","collection","dropdown","playerModel","setCurrentAttempt","reset","$currentAttempt","$playerState","pauseAudio","pause","seekAudio","seek","constructor","params","api","downloader","loader","translation","playback","player","togglePlayPause","audios","initializeCollectionFromAudios","setupAudioMode","stopAudio","halt","preloadAudio","attemptNumber","target","getState","resetPlayer","releaseResources","clear","clearCache","initializeWithAudios","answerAudio","collectionMatchesAudios","i","length","audio","audioFileId","existing","get","isAudioLoading","audioLoading","getAllAttempts","getAll","reinitializePlayer","reinitialize","cleanup","release","console","warn","forEach","index","add","_id","hasDrawing","drawing"],"sourceRoot":"../../../../../../src","sources":["features/voice/playing/model/VoicePlayer.model.ts"],"mappings":"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","ignoreList":[]}
@@ -4,6 +4,7 @@ export * from './recording/modal/VoiceRecordDeleteModal';
4
4
  export * from './recording/modal/VoiceRecordUndoModal';
5
5
  export * from './playing/model/VoicePlayer.model';
6
6
  export * from './playing/components/VoiceTranscription';
7
+ export * from './playing/hooks/useVoicePlayerLifecycle';
7
8
  export * from './playing/components/VoiceIcon';
8
9
  export * from './constants';
9
10
  export * from './types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/voice/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAA;AAClD,cAAc,qCAAqC,CAAA;AACnD,cAAc,0CAA0C,CAAA;AACxD,cAAc,wCAAwC,CAAA;AAEtD,cAAc,mCAAmC,CAAA;AACjD,cAAc,yCAAyC,CAAA;AAEvD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,YAAY,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/voice/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAA;AAClD,cAAc,qCAAqC,CAAA;AACnD,cAAc,0CAA0C,CAAA;AACxD,cAAc,wCAAwC,CAAA;AAEtD,cAAc,mCAAmC,CAAA;AACjD,cAAc,yCAAyC,CAAA;AACvD,cAAc,yCAAyC,CAAA;AAEvD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,YAAY,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,15 @@
1
+ import { AnswerAudio } from '../../types';
2
+ import { VoicePlayerModel } from '../model';
3
+ type Params = {
4
+ model: VoicePlayerModel;
5
+ answers: AnswerAudio[];
6
+ attemptOffset: number;
7
+ attemptsCount: number;
8
+ problemId: string;
9
+ };
10
+ export declare const useVoicePlayerLifecycle: ({ model, answers, attemptOffset, attemptsCount, problemId, }: Params) => {
11
+ activeAttempt: number | null;
12
+ hasAnyAudio: boolean;
13
+ };
14
+ export {};
15
+ //# sourceMappingURL=useVoicePlayerLifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVoicePlayerLifecycle.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/hooks/useVoicePlayerLifecycle.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAE3C,KAAK,MAAM,GAAG;IACZ,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAID,eAAO,MAAM,uBAAuB,iEAMjC,MAAM;;;CA0CR,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceTranscriptionController.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/hooks/useVoiceTranscriptionController.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD,KAAK,MAAM,GAAG;IACZ,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG,UAAU,CAAC,OAAO,+BAA+B,CAAC,CAAA;AAE7F,eAAO,MAAM,+BAA+B,iEAMzC,MAAM;;;;;;qBA2IyB,WAAW;;;;;;;;;;CAW5C,CAAA"}
1
+ {"version":3,"file":"useVoiceTranscriptionController.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/hooks/useVoiceTranscriptionController.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD,KAAK,MAAM,GAAG;IACZ,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG,UAAU,CAAC,OAAO,+BAA+B,CAAC,CAAA;AAE7F,eAAO,MAAM,+BAA+B,iEAMzC,MAAM;;;;;;qBA6GyB,WAAW;;;;;;;;;;CAW5C,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Player.model.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/model/Player.model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAwC,MAAM,YAAY,CAAA;AAE9E,0BAAkB,WAAW;IAC3B,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,IAAI,SAAS;CACd;AAED,qBAAa,WAAW;IACf,MAAM,EAAE,WAAW,GAAG,IAAI,CAAsB;IACvD,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,SAAS,CAAsB;IAEvC,SAAgB,KAAK,yCAAgB;IACrC,SAAgB,cAAc,gDAA6B;IAC3D,SAAgB,gBAAgB,yCAAgB;IAEhD,SAAgB,YAAY,gDAAmE;IAE/F,SAAgB,cAAc,+CAM5B;IAEF,SAAgB,KAAK,+CAOnB;IAEF,SAAgB,IAAI,+CASlB;IAEF,SAAgB,KAAK,iDAKnB;IAEF,SAAgB,IAAI,iDAUlB;IAEF,SAAgB,MAAM,+CAOpB;IAEF,SAAgB,IAAI,iDA+BlB;IAEK,YAAY;IAMZ,OAAO;CAYf"}
1
+ {"version":3,"file":"Player.model.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/model/Player.model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAwC,MAAM,YAAY,CAAA;AAE9E,0BAAkB,WAAW;IAC3B,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,IAAI,SAAS;CACd;AAcD,qBAAa,WAAW;IACf,MAAM,EAAE,WAAW,GAAG,IAAI,CAAsB;IACvD,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,SAAS,CAAsB;IAEvC,SAAgB,KAAK,yCAAgB;IACrC,SAAgB,cAAc,gDAA6B;IAC3D,SAAgB,gBAAgB,yCAAgB;IAEhD,SAAgB,YAAY,gDAAmE;IAE/F,SAAgB,cAAc,+CAM5B;IAEF,SAAgB,KAAK,+CAOnB;IAEF,SAAgB,IAAI,+CASlB;IAEF,SAAgB,KAAK,iDAKnB;IAEF,SAAgB,IAAI,iDAMlB;IAEF,SAAgB,MAAM,+CAOpB;IAEF,SAAgB,IAAI,iDA+BlB;IAEK,YAAY;IAMZ,OAAO;CAYf"}
@@ -31,6 +31,7 @@ export declare class VoicePlayerModel {
31
31
  readonly preloadAudio: (attemptNumber?: number) => Promise<void> | undefined;
32
32
  readonly resetPlayer: () => void;
33
33
  initializeWithAudios(answerAudio: AnswerAudio[]): void;
34
+ private collectionMatchesAudios;
34
35
  isAudioLoading(attemptNumber: number): boolean;
35
36
  getAllAttempts(): VoiceTranscriptionItem[];
36
37
  reinitializePlayer(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"VoicePlayer.model.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/model/VoicePlayer.model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAA;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,6BAA6B,EAAE,MAAM,kCAAkC,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAEzD,KAAK,sBAAsB,GAAG;IAC5B,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAA;CACvB,CAAA;AAED,qBAAa,gBAAgB;IAC3B,SAAgB,UAAU,2BAAiC;IAC3D,SAAgB,QAAQ,gBAAsB;IAC9C,SAAgB,WAAW,cAAoB;IAC/C,SAAgB,UAAU,EAAE,wBAAwB,CAAA;IACpD,SAAgB,WAAW,EAAE,gBAAgB,CAAA;IAC7C,SAAgB,MAAM,EAAE,6BAA6B,CAAA;IACrD,SAAgB,GAAG,EAAE,cAAc,CAAA;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAE7C,SAAgB,iBAAiB,kDAA+B;IAChE,SAAgB,KAAK,yCAAgB;IAErC,SAAgB,eAAe,kDAA0D;IACzF,SAAgB,YAAY,yEAAgC;IAE5D,SAAgB,UAAU,+CAAyB;IACnD,SAAgB,SAAS,iDAAwB;IAEjD,SAAgB,eAAe,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,CAAA;gBAE1D,MAAM,EAAE,sBAAsB;IAmB1C,SAAgB,SAAS,aAExB;IAED,SAAgB,YAAY,mBAAoB,MAAM,+BAIrD;IAED,SAAgB,WAAW,aAK1B;IAEM,oBAAoB,CAAC,WAAW,EAAE,WAAW,EAAE;IAK/C,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IAI9C,cAAc,IAAI,sBAAsB,EAAE;IAI1C,kBAAkB;IAIlB,OAAO;IASd,OAAO,CAAC,8BAA8B;CAmBvC"}
1
+ {"version":3,"file":"VoicePlayer.model.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/model/VoicePlayer.model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAA;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,6BAA6B,EAAE,MAAM,kCAAkC,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAEzD,KAAK,sBAAsB,GAAG;IAC5B,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAA;CACvB,CAAA;AAED,qBAAa,gBAAgB;IAC3B,SAAgB,UAAU,2BAAiC;IAC3D,SAAgB,QAAQ,gBAAsB;IAC9C,SAAgB,WAAW,cAAoB;IAC/C,SAAgB,UAAU,EAAE,wBAAwB,CAAA;IACpD,SAAgB,WAAW,EAAE,gBAAgB,CAAA;IAC7C,SAAgB,MAAM,EAAE,6BAA6B,CAAA;IACrD,SAAgB,GAAG,EAAE,cAAc,CAAA;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAE7C,SAAgB,iBAAiB,kDAA+B;IAChE,SAAgB,KAAK,yCAAgB;IAErC,SAAgB,eAAe,kDAA0D;IACzF,SAAgB,YAAY,yEAAgC;IAE5D,SAAgB,UAAU,+CAAyB;IACnD,SAAgB,SAAS,iDAAwB;IAEjD,SAAgB,eAAe,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,CAAA;gBAE1D,MAAM,EAAE,sBAAsB;IAmB1C,SAAgB,SAAS,aAExB;IAED,SAAgB,YAAY,mBAAoB,MAAM,+BAIrD;IAED,SAAgB,WAAW,aAK1B;IAEM,oBAAoB,CAAC,WAAW,EAAE,WAAW,EAAE;IAOtD,OAAO,CAAC,uBAAuB;IAWxB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IAI9C,cAAc,IAAI,sBAAsB,EAAE;IAI1C,kBAAkB;IAIlB,OAAO;IASd,OAAO,CAAC,8BAA8B;CAmBvC"}
@@ -4,6 +4,7 @@ export * from './recording/modal/VoiceRecordDeleteModal';
4
4
  export * from './recording/modal/VoiceRecordUndoModal';
5
5
  export * from './playing/model/VoicePlayer.model';
6
6
  export * from './playing/components/VoiceTranscription';
7
+ export * from './playing/hooks/useVoicePlayerLifecycle';
7
8
  export * from './playing/components/VoiceIcon';
8
9
  export * from './constants';
9
10
  export * from './types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/voice/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAA;AAClD,cAAc,qCAAqC,CAAA;AACnD,cAAc,0CAA0C,CAAA;AACxD,cAAc,wCAAwC,CAAA;AAEtD,cAAc,mCAAmC,CAAA;AACjD,cAAc,yCAAyC,CAAA;AAEvD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,YAAY,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/voice/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAA;AAClD,cAAc,qCAAqC,CAAA;AACnD,cAAc,0CAA0C,CAAA;AACxD,cAAc,wCAAwC,CAAA;AAEtD,cAAc,mCAAmC,CAAA;AACjD,cAAc,yCAAyC,CAAA;AACvD,cAAc,yCAAyC,CAAA;AAEvD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,YAAY,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,15 @@
1
+ import { AnswerAudio } from '../../types';
2
+ import { VoicePlayerModel } from '../model';
3
+ type Params = {
4
+ model: VoicePlayerModel;
5
+ answers: AnswerAudio[];
6
+ attemptOffset: number;
7
+ attemptsCount: number;
8
+ problemId: string;
9
+ };
10
+ export declare const useVoicePlayerLifecycle: ({ model, answers, attemptOffset, attemptsCount, problemId, }: Params) => {
11
+ activeAttempt: number | null;
12
+ hasAnyAudio: boolean;
13
+ };
14
+ export {};
15
+ //# sourceMappingURL=useVoicePlayerLifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVoicePlayerLifecycle.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/hooks/useVoicePlayerLifecycle.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAE3C,KAAK,MAAM,GAAG;IACZ,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAID,eAAO,MAAM,uBAAuB,iEAMjC,MAAM;;;CA0CR,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceTranscriptionController.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/hooks/useVoiceTranscriptionController.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD,KAAK,MAAM,GAAG;IACZ,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG,UAAU,CAAC,OAAO,+BAA+B,CAAC,CAAA;AAE7F,eAAO,MAAM,+BAA+B,iEAMzC,MAAM;;;;;;qBA2IyB,WAAW;;;;;;;;;;CAW5C,CAAA"}
1
+ {"version":3,"file":"useVoiceTranscriptionController.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/hooks/useVoiceTranscriptionController.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD,KAAK,MAAM,GAAG;IACZ,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG,UAAU,CAAC,OAAO,+BAA+B,CAAC,CAAA;AAE7F,eAAO,MAAM,+BAA+B,iEAMzC,MAAM;;;;;;qBA6GyB,WAAW;;;;;;;;;;CAW5C,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Player.model.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/model/Player.model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAwC,MAAM,YAAY,CAAA;AAE9E,0BAAkB,WAAW;IAC3B,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,IAAI,SAAS;CACd;AAED,qBAAa,WAAW;IACf,MAAM,EAAE,WAAW,GAAG,IAAI,CAAsB;IACvD,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,SAAS,CAAsB;IAEvC,SAAgB,KAAK,yCAAgB;IACrC,SAAgB,cAAc,gDAA6B;IAC3D,SAAgB,gBAAgB,yCAAgB;IAEhD,SAAgB,YAAY,gDAAmE;IAE/F,SAAgB,cAAc,+CAM5B;IAEF,SAAgB,KAAK,+CAOnB;IAEF,SAAgB,IAAI,+CASlB;IAEF,SAAgB,KAAK,iDAKnB;IAEF,SAAgB,IAAI,iDAUlB;IAEF,SAAgB,MAAM,+CAOpB;IAEF,SAAgB,IAAI,iDA+BlB;IAEK,YAAY;IAMZ,OAAO;CAYf"}
1
+ {"version":3,"file":"Player.model.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/model/Player.model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAwC,MAAM,YAAY,CAAA;AAE9E,0BAAkB,WAAW;IAC3B,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,IAAI,SAAS;CACd;AAcD,qBAAa,WAAW;IACf,MAAM,EAAE,WAAW,GAAG,IAAI,CAAsB;IACvD,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,SAAS,CAAsB;IAEvC,SAAgB,KAAK,yCAAgB;IACrC,SAAgB,cAAc,gDAA6B;IAC3D,SAAgB,gBAAgB,yCAAgB;IAEhD,SAAgB,YAAY,gDAAmE;IAE/F,SAAgB,cAAc,+CAM5B;IAEF,SAAgB,KAAK,+CAOnB;IAEF,SAAgB,IAAI,+CASlB;IAEF,SAAgB,KAAK,iDAKnB;IAEF,SAAgB,IAAI,iDAMlB;IAEF,SAAgB,MAAM,+CAOpB;IAEF,SAAgB,IAAI,iDA+BlB;IAEK,YAAY;IAMZ,OAAO;CAYf"}
@@ -31,6 +31,7 @@ export declare class VoicePlayerModel {
31
31
  readonly preloadAudio: (attemptNumber?: number) => Promise<void> | undefined;
32
32
  readonly resetPlayer: () => void;
33
33
  initializeWithAudios(answerAudio: AnswerAudio[]): void;
34
+ private collectionMatchesAudios;
34
35
  isAudioLoading(attemptNumber: number): boolean;
35
36
  getAllAttempts(): VoiceTranscriptionItem[];
36
37
  reinitializePlayer(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"VoicePlayer.model.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/model/VoicePlayer.model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAA;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,6BAA6B,EAAE,MAAM,kCAAkC,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAEzD,KAAK,sBAAsB,GAAG;IAC5B,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAA;CACvB,CAAA;AAED,qBAAa,gBAAgB;IAC3B,SAAgB,UAAU,2BAAiC;IAC3D,SAAgB,QAAQ,gBAAsB;IAC9C,SAAgB,WAAW,cAAoB;IAC/C,SAAgB,UAAU,EAAE,wBAAwB,CAAA;IACpD,SAAgB,WAAW,EAAE,gBAAgB,CAAA;IAC7C,SAAgB,MAAM,EAAE,6BAA6B,CAAA;IACrD,SAAgB,GAAG,EAAE,cAAc,CAAA;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAE7C,SAAgB,iBAAiB,kDAA+B;IAChE,SAAgB,KAAK,yCAAgB;IAErC,SAAgB,eAAe,kDAA0D;IACzF,SAAgB,YAAY,yEAAgC;IAE5D,SAAgB,UAAU,+CAAyB;IACnD,SAAgB,SAAS,iDAAwB;IAEjD,SAAgB,eAAe,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,CAAA;gBAE1D,MAAM,EAAE,sBAAsB;IAmB1C,SAAgB,SAAS,aAExB;IAED,SAAgB,YAAY,mBAAoB,MAAM,+BAIrD;IAED,SAAgB,WAAW,aAK1B;IAEM,oBAAoB,CAAC,WAAW,EAAE,WAAW,EAAE;IAK/C,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IAI9C,cAAc,IAAI,sBAAsB,EAAE;IAI1C,kBAAkB;IAIlB,OAAO;IASd,OAAO,CAAC,8BAA8B;CAmBvC"}
1
+ {"version":3,"file":"VoicePlayer.model.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/voice/playing/model/VoicePlayer.model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAA;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,6BAA6B,EAAE,MAAM,kCAAkC,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAEzD,KAAK,sBAAsB,GAAG;IAC5B,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAA;CACvB,CAAA;AAED,qBAAa,gBAAgB;IAC3B,SAAgB,UAAU,2BAAiC;IAC3D,SAAgB,QAAQ,gBAAsB;IAC9C,SAAgB,WAAW,cAAoB;IAC/C,SAAgB,UAAU,EAAE,wBAAwB,CAAA;IACpD,SAAgB,WAAW,EAAE,gBAAgB,CAAA;IAC7C,SAAgB,MAAM,EAAE,6BAA6B,CAAA;IACrD,SAAgB,GAAG,EAAE,cAAc,CAAA;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAE7C,SAAgB,iBAAiB,kDAA+B;IAChE,SAAgB,KAAK,yCAAgB;IAErC,SAAgB,eAAe,kDAA0D;IACzF,SAAgB,YAAY,yEAAgC;IAE5D,SAAgB,UAAU,+CAAyB;IACnD,SAAgB,SAAS,iDAAwB;IAEjD,SAAgB,eAAe,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,CAAA;gBAE1D,MAAM,EAAE,sBAAsB;IAmB1C,SAAgB,SAAS,aAExB;IAED,SAAgB,YAAY,mBAAoB,MAAM,+BAIrD;IAED,SAAgB,WAAW,aAK1B;IAEM,oBAAoB,CAAC,WAAW,EAAE,WAAW,EAAE;IAOtD,OAAO,CAAC,uBAAuB;IAWxB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IAI9C,cAAc,IAAI,sBAAsB,EAAE;IAI1C,kBAAkB;IAIlB,OAAO;IASd,OAAO,CAAC,8BAA8B;CAmBvC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magmamath/students-features",
3
- "version": "1.3.23-rc.44",
3
+ "version": "1.3.23-rc.46",
4
4
  "description": "Magmamath features library",
5
5
  "source": "src/index.ts",
6
6
  "main": "src/index.ts",
@@ -5,6 +5,7 @@ export * from './recording/modal/VoiceRecordUndoModal'
5
5
 
6
6
  export * from './playing/model/VoicePlayer.model'
7
7
  export * from './playing/components/VoiceTranscription'
8
+ export * from './playing/hooks/useVoicePlayerLifecycle'
8
9
 
9
10
  export * from './playing/components/VoiceIcon'
10
11
  export * from './constants'
@@ -0,0 +1,64 @@
1
+ import { useEffect, useMemo, useRef } from 'react'
2
+ import { getActiveAttempt } from '../../helpers'
3
+ import { AnswerAudio } from '../../types'
4
+ import { VoicePlayerModel } from '../model'
5
+
6
+ type Params = {
7
+ model: VoicePlayerModel
8
+ answers: AnswerAudio[]
9
+ attemptOffset: number
10
+ attemptsCount: number
11
+ problemId: string
12
+ }
13
+
14
+ // Owns playback engine mutations (init/reset/setCurrentAttempt/stopAudio).
15
+ // VoiceTranscription stays read-only; consumers call this once per page.
16
+ export const useVoicePlayerLifecycle = ({
17
+ model,
18
+ answers,
19
+ attemptOffset,
20
+ attemptsCount,
21
+ problemId,
22
+ }: Params) => {
23
+ const activeAttempt = getActiveAttempt(attemptOffset, attemptsCount)
24
+
25
+ const answersKey = useMemo(
26
+ () => answers.map((a) => `${a._id}:${a.audioFileId ?? ''}`).join(','),
27
+ [answers],
28
+ )
29
+
30
+ const hasAnyAudio = useMemo(() => answers.some((a) => !!a.audioFileId), [answers])
31
+
32
+ const answersRef = useRef(answers)
33
+ answersRef.current = answers
34
+
35
+ useEffect(() => {
36
+ model.reinitializePlayer()
37
+ return () => {
38
+ model.stopAudio()
39
+ }
40
+ }, [model])
41
+
42
+ useEffect(() => {
43
+ model.resetPlayer()
44
+ }, [problemId])
45
+
46
+ useEffect(() => {
47
+ if (answersRef.current.some((a) => a.audioFileId)) {
48
+ model.initializeWithAudios(answersRef.current)
49
+ }
50
+ }, [model, answersKey])
51
+
52
+ useEffect(() => {
53
+ // Skip stopAudio if VoiceSource has already queued playback for activeAttempt (timeline auto-progress).
54
+ if (model.$currentAttempt.getState() !== activeAttempt) {
55
+ model.stopAudio()
56
+ }
57
+ model.setCurrentAttempt(activeAttempt)
58
+ if (activeAttempt !== null) {
59
+ model.loader.loadTranscriptForAttempt(activeAttempt)
60
+ }
61
+ }, [model, activeAttempt, answersKey])
62
+
63
+ return { activeAttempt, hasAnyAudio }
64
+ }
@@ -40,11 +40,6 @@ export const useVoiceTranscriptionController = ({
40
40
 
41
41
  const activeAttempt = getActiveAttempt(attemptOffset, attemptsCount)
42
42
 
43
- const answersKey = useMemo(
44
- () => answers.map((a) => `${a._id}:${a.audioFileId ?? ''}`).join(','),
45
- [answers],
46
- )
47
-
48
43
  const activeAudioFileId =
49
44
  activeAttempt !== null ? answers?.[activeAttempt - 1]?.audioFileId : undefined
50
45
  const hasActiveAudio = activeAudioFileId !== undefined
@@ -73,44 +68,19 @@ export const useVoiceTranscriptionController = ({
73
68
  ? activeTranscript!
74
69
  : t('voice.transcriptNotAvailable')
75
70
 
76
- // Lifecycle effects
77
- const answersRef = useRef(answers)
78
- answersRef.current = answers
79
-
71
+ // UI-only lifecycle: collapse the dropdown on mount/unmount and on problem
72
+ // change. Playback engine mutations (init/reset/setCurrentAttempt/stopAudio)
73
+ // are owned by useVoicePlayerLifecycle, called by the page-level consumer.
80
74
  useEffect(() => {
81
- model.reinitializePlayer()
82
75
  return () => {
83
- model.stopAudio()
84
76
  model.dropdown.setExpanded(false)
85
77
  }
86
78
  }, [model])
87
79
 
88
80
  useEffect(() => {
89
81
  model.dropdown.setExpanded(false)
90
- model.resetPlayer()
91
82
  }, [problemId])
92
83
 
93
- useEffect(() => {
94
- if (answersRef.current.some((a) => a.audioFileId)) {
95
- model.initializeWithAudios(answersRef.current)
96
- }
97
- }, [model, answersKey])
98
-
99
- useEffect(() => {
100
- // Skip stopAudio when the audio is already targeting activeAttempt — that's
101
- // the case when the timeline scrubber auto-progressed to this attempt and
102
- // VoiceSource just activated playback for it. Stopping here would kill the
103
- // freshly-started audio (race: activation runs synchronously inside the
104
- // timeline tick, this effect fires after React commits).
105
- if (model.$currentAttempt.getState() !== activeAttempt) {
106
- model.stopAudio()
107
- }
108
- model.setCurrentAttempt(activeAttempt)
109
- if (activeAttempt !== null) {
110
- model.loader.loadTranscriptForAttempt(activeAttempt)
111
- }
112
- }, [model, activeAttempt, answersKey])
113
-
114
84
  // Auto-activate translation once per (problemId, activeAttempt) when translatable
115
85
  const autoActivatedAttempts = useRef(new Set<number>())
116
86
  useEffect(() => {
@@ -8,6 +8,18 @@ export const enum PlayerState {
8
8
  IDLE = 'idle',
9
9
  }
10
10
 
11
+ // audio.play() returns a promise that rejects with AbortError when a subsequent
12
+ // pause() interrupts it. That's expected during pause/resume cycles; suppress noise.
13
+ const safePlay = (audio: AudioPlayer) => {
14
+ const result = audio.play() as unknown
15
+ if (result && typeof (result as Promise<unknown>).catch === 'function') {
16
+ ;(result as Promise<unknown>).catch((err: unknown) => {
17
+ if ((err as { name?: string })?.name === 'AbortError') return
18
+ throw err
19
+ })
20
+ }
21
+ }
22
+
11
23
  export class PlayerModel {
12
24
  public player: AudioPlayer | null = createAudioPlayer()
13
25
  private stopped = false
@@ -55,20 +67,16 @@ export class PlayerModel {
55
67
  })
56
68
 
57
69
  public readonly seek = createEffect(async (seconds: number) => {
58
- if (!this.player) {
59
- console.warn('Cannot seek: audio player not initialized')
60
- return
61
- }
62
- if (!this.player.isLoaded) {
63
- console.warn('Cannot seek: audio player not loaded')
64
- return
65
- }
70
+ // Silently no-op when not loaded — the next play() effect's waitForLoad will
71
+ // pick up the desired offset implicitly via replace/load. Warning was noisy
72
+ // during pause→scrub→play cycles where isLoaded briefly flips false.
73
+ if (!this.player?.isLoaded) return
66
74
  await this.player.seekTo(seconds)
67
75
  })
68
76
 
69
77
  public readonly resume = createEffect(() => {
70
78
  if (this.player) {
71
- this.player.play()
79
+ safePlay(this.player)
72
80
  this.setPlayerState(PlayerState.PLAYING)
73
81
  } else {
74
82
  console.warn('Cannot resume: audio player not initialized')
@@ -98,7 +106,7 @@ export class PlayerModel {
98
106
  }
99
107
  })
100
108
 
101
- this.player.play()
109
+ safePlay(this.player)
102
110
  this.setPlayerState(PlayerState.PLAYING)
103
111
  } else {
104
112
  setTimeout(waitForLoad, 10)
@@ -71,10 +71,23 @@ export class VoicePlayerModel {
71
71
  }
72
72
 
73
73
  public initializeWithAudios(answerAudio: AnswerAudio[]) {
74
+ // Skip clear+rebuild when content matches — re-init mid-playback drops audioUri and races with in-flight togglePlayPause.
75
+ if (this.collectionMatchesAudios(answerAudio)) return
74
76
  this.collection.clear()
75
77
  this.initializeCollectionFromAudios(answerAudio)
76
78
  }
77
79
 
80
+ private collectionMatchesAudios(audios: AnswerAudio[]): boolean {
81
+ for (let i = 0; i < audios.length; i++) {
82
+ const audio = audios[i]
83
+ if (!audio.audioFileId) continue
84
+ const attemptNumber = i + 1
85
+ const existing = this.collection.get(attemptNumber)
86
+ if (!existing || existing.audioFileId !== audio.audioFileId) return false
87
+ }
88
+ return true
89
+ }
90
+
78
91
  public isAudioLoading(attemptNumber: number): boolean {
79
92
  return this.collection.get(attemptNumber)?.audioLoading || false
80
93
  }