-
Notifications
You must be signed in to change notification settings - Fork 5
Fix audio preview #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
3abf397
5c64b96
035b800
e02a086
7945e9a
0c654b3
aacb42c
2aabac0
90f1590
c2b2ee5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,28 +1,26 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ScribeFileType } from "@/types"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Dispatch, SetStateAction } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { API } from "./api"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function handleUploadPercentage( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event: ProgressEvent, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setUploadPercent: Dispatch<SetStateAction<number>>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (event.lengthComputable) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const percentComplete = Math.round((event.loaded / event.total) * 100); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setUploadPercent(percentComplete); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const isRecord = (value: unknown): value is Record<string, unknown> => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value !== null && typeof value === "object" && !Array.isArray(value); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const safeParseJson = (value: string): unknown => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return JSON.parse(value); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const uploadFile = ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| url: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file: File | FormData, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reqMethod: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers: object, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers: Record<string, string>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onLoad: (xhr: XMLHttpRequest) => void, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setUploadPercent: Dispatch<SetStateAction<number>> | null, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onError: () => void, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onError: (error?: string) => void, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const xhr = new XMLHttpRequest(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| xhr.open(reqMethod, url); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| xhr.open("PUT", url); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Object.entries(headers).forEach(([key, value]) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| xhr.setRequestHeader(key, value); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -31,23 +29,17 @@ const uploadFile = ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| xhr.onload = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onLoad(xhr); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (400 <= xhr.status && xhr.status <= 499) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const error = JSON.parse(xhr.responseText); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof error === "object" && !Array.isArray(error)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const error = safeParseJson(xhr.responseText ?? ""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (isRecord(error)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Object.values(error).forEach((msg) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| window.alert(msg || "Something went wrong!"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onError(typeof msg === "string" ? msg : "An error occurred."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| window.alert(error || "Something went wrong!"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onError(typeof error === "string" ? error : "An error occurred"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (setUploadPercent != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| xhr.upload.onprogress = (event: ProgressEvent) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handleUploadPercentage(event, setUploadPercent); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| xhr.onerror = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| window.alert("Network Failure. Please check your internet connectivity."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onError(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -64,16 +56,27 @@ export const uploadScribeFile = async ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: ScribeFileType, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const category = type === ScribeFileType.AUDIO ? "AUDIO" : "UNSPECIFIED"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const extension = blob?.type?.split("/")?.[1].split(";")?.[0]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const name = "file" + (extension ? `.${extension}` : ""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const extension = blob.type.split("/")[1]?.split(";")?.[0]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!extension) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Could not determine file extension. Got mime type: " + blob.type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const name = `file.${extension}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+59
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n src/utils/upload-utils.ts | head -100Repository: ohcnetwork/care_scribe_fe Length of output: 3488 🏁 Script executed: rg -nP --type=ts -C3 'createFileUpload'Repository: ohcnetwork/care_scribe_fe Length of output: 902 🏁 Script executed: rg -nP --type=ts 'CreateFileRequest' -A10 -B2Repository: ohcnetwork/care_scribe_fe Length of output: 1820 🏁 Script executed: rg -nP --type=ts 'mime_type' src/Repository: ohcnetwork/care_scribe_fe Length of output: 300 Derive The ♻️ Suggested refactor- const extension = blob.type.split("/")[1]?.split(";")?.[0];
+ const mimeType: string = blob.type.split(";")[0];
+ const extension = mimeType.split("/")[1];
@@
- mime_type: blob.type?.split(";")?.[0],
+ mime_type: mimeType,Also applies to: 82–89 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const filename = Date.now().toString(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let length = undefined; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let length: number | undefined; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (type === ScribeFileType.AUDIO) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const arrayBuffer = await blob.arrayBuffer(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const audioContext = new AudioContext(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| length = Number(audioBuffer.duration.toFixed(2)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| length = Number(audioBuffer.duration.toFixed(2)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } finally { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await audioContext.close(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const data = await API.scribe.createFileUpload({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -82,32 +85,30 @@ export const uploadScribeFile = async ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: filename, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| associating_id: scribeInstanceId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file_category: category, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mime_type: blob?.type?.split(";")?.[0], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mime_type: blob.type?.split(";")?.[0], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| length, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await new Promise<void>((resolve, reject) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const url = data?.signed_url; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const internal_name = data?.internal_name; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const f = blob; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (f === undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reject(Error("No file to upload")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const url = data.signed_url; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const internalName = data.internal_name; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!url || !internalName) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reject(Error("Missing upload metadata")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const newFile = new File([f], `${internal_name}`, { type: f.type }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const newFile = new File([blob], internalName, { type: blob.type }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const headers = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Content-type": newFile?.type?.split(";")?.[0], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Content-type": newFile.type.split(";")[0], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Content-disposition": "inline", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uploadFile( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| url || "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| url, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newFile, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "PUT", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (xhr: XMLHttpRequest) => (xhr.status === 200 ? resolve() : reject()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| null, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reject, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (e) => reject(Error(e)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
101
to
112
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # Check if the file exists and view the specific lines
wc -l src/utils/upload-utils.tsRepository: ohcnetwork/care_scribe_fe Length of output: 98 🏁 Script executed: # Read the relevant section of the file
sed -n '90,120p' src/utils/upload-utils.tsRepository: ohcnetwork/care_scribe_fe Length of output: 860 🏁 Script executed: # Find the uploadFile function definition to understand the callback signatures
rg -A 10 "function uploadFile|const uploadFile|export.*uploadFile" src/utils/upload-utils.tsRepository: ohcnetwork/care_scribe_fe Length of output: 715 Add explicit header typing and handle undefined error parameter. The Suggested fix- const headers = {
+ const headers: Record<string, string> = {
"Content-type": newFile.type.split(";")[0],
"Content-disposition": "inline",
};
@@
- (e) => reject(Error(e)),
+ (e) => reject(new Error(e ?? "Upload failed")),📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
shivankacker marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# Find and examine the upload-utils file fd -t f upload-utils.tsRepository: ohcnetwork/care_scribe_fe
Length of output: 94
🏁 Script executed:
# View the full file to understand the context cat -n src/utils/upload-utils.tsRepository: ohcnetwork/care_scribe_fe
Length of output: 4121
🏁 Script executed:
Repository: ohcnetwork/care_scribe_fe
Length of output: 96
🏁 Script executed:
Repository: ohcnetwork/care_scribe_fe
Length of output: 1056
🏁 Script executed:
Repository: ohcnetwork/care_scribe_fe
Length of output: 1056
🏁 Script executed:
Repository: ohcnetwork/care_scribe_fe
Length of output: 774
🏁 Script executed:
Repository: ohcnetwork/care_scribe_fe
Length of output: 681
Move error status checks before
onLoadcall to prevent double-callback invocation.The
xhr.onloadhandler currently callsonLoad(xhr)unconditionally (line 30), then checks for 4xx errors and invokesonErrorafterward. When a 4xx response occurs, both callbacks fire: the caller'sonLoadhandler (line 110) rejects the Promise on non-2xx status, thenonErrorattempts to reject again. While a Promise only uses the first rejection, this pattern is semantically incorrect and confusing.The fix should check error status codes first and only invoke
onLoadon success (2xx). Additionally, handle 5xx server errors gracefully rather than waiting for network failure.🔧 Proposed fix
🤖 Prompt for AI Agents