2024-08-13 06:57:58 +00:00
window . generateDiff = function ( text1 , text2 , divDiff , divLegend ) {
let wikEdDiff = new WikEdDiff ( ) ;
let targetDiv = document . getElementById ( divDiff )
targetDiv . innerHTML = wikEdDiff . diff ( text1 , text2 ) ;
2024-09-15 20:21:33 +00:00
targetDiv . classList . add ( 'mud-typography-body1' , 'improvedDiff' ) ;
2024-08-13 06:57:58 +00:00
let legend = document . getElementById ( divLegend ) ;
legend . innerHTML = `
< div class = "legend mt-2" >
< h3 > Legend < / h 3 >
< ul class = "mt-2" >
< li > < span class = "wikEdDiffMarkRight" title = "Moved block" id = "wikEdDiffMark999" onmouseover = "wikEdDiffBlockHandler(undefined, this, 'mouseover');" > < / s p a n > O r i g i n a l b l o c k p o s i t i o n < / l i >
< li > < span title = "+" class = "wikEdDiffInsert" > Inserted < span class = "wikEdDiffSpace" > < span class = "wikEdDiffSpaceSymbol" > < / s p a n > < / s p a n > t e x t < s p a n c l a s s = " w i k E d D i f f N e w l i n e " > < / s p a n > < / s p a n > < / l i >
< li > < span title = "− " class = "wikEdDiffDelete" > Deleted < span class = "wikEdDiffSpace" > < span class = "wikEdDiffSpaceSymbol" > < / s p a n > < / s p a n > t e x t < s p a n c l a s s = " w i k E d D i f f N e w l i n e " > < / s p a n > < / s p a n > < / l i >
< li > < span class = "wikEdDiffBlockLeft" title = "◀" id = "wikEdDiffBlock999" onmouseover = "wikEdDiffBlockHandler(undefined, this, 'mouseover');" > Moved < span class = "wikEdDiffSpace" > < span class = "wikEdDiffSpaceSymbol" > < / s p a n > < / s p a n > b l o c k < s p a n c l a s s = " w i k E d D i f f N e w l i n e " > < / s p a n > < / s p a n > < / l i >
< / u l >
< / d i v >
` ;
2024-08-18 19:48:35 +00:00
}
window . clearDiv = function ( divName ) {
let targetDiv = document . getElementById ( divName ) ;
targetDiv . innerHTML = '' ;
2024-08-23 08:32:27 +00:00
}
window . scrollToBottom = function ( element ) {
2024-09-05 17:37:54 +00:00
element . scrollIntoView ( { behavior : 'smooth' , block : 'end' , inline : 'nearest' } ) ;
2026-01-01 16:55:05 +00:00
}
let mediaRecorder ;
let audioChunks = [ ] ;
2026-01-06 09:25:58 +00:00
let actualRecordingMimeType ;
let changedMimeType = false ;
2026-01-01 16:55:05 +00:00
window . audioRecorder = {
2026-01-06 09:25:58 +00:00
start : async function ( desiredMimeTypes = [ ] ) {
2026-01-01 16:55:05 +00:00
const stream = await navigator . mediaDevices . getUserMedia ( { audio : true } ) ;
2026-01-06 09:25:58 +00:00
// When only one mime type is provided as a string, convert it to an array:
if ( typeof desiredMimeTypes === 'string' ) {
desiredMimeTypes = [ desiredMimeTypes ] ;
}
// Log sent mime types for debugging:
console . log ( 'Requested mime types:' , desiredMimeTypes ) ;
let mimeTypes = desiredMimeTypes . filter ( type => typeof type === 'string' && type . trim ( ) !== '' ) ;
// Next, we have to ensure that we have some default mime types to check as well.
// In case the provided list does not contain these, we append them:
// Use provided mime types or fallback to a default list:
const defaultMimeTypes = [
'audio/webm' ,
'audio/ogg' ,
'audio/mp4' ,
'audio/mpeg' ,
'' // Fallback to browser default
] ;
defaultMimeTypes . forEach ( type => {
if ( ! mimeTypes . includes ( type ) ) {
mimeTypes . push ( type ) ;
}
} ) ;
console . log ( 'Final mime types to check (included defaults):' , mimeTypes ) ;
// Find the first supported mime type:
actualRecordingMimeType = mimeTypes . find ( type =>
type === '' || MediaRecorder . isTypeSupported ( type )
) || '' ;
console . log ( 'Selected mime type for recording:' , actualRecordingMimeType ) ;
const options = actualRecordingMimeType ? { mimeType : actualRecordingMimeType } : { } ;
mediaRecorder = new MediaRecorder ( stream , options ) ;
// In case the browser changed the mime type:
actualRecordingMimeType = mediaRecorder . mimeType ;
// Check the list of desired mime types against the actual one:
if ( ! desiredMimeTypes . includes ( actualRecordingMimeType ) ) {
changedMimeType = true ;
console . warn ( ` Requested mime types (' ${ desiredMimeTypes . join ( ', ' ) } ') do not include the actual mime type used by MediaRecorder (' ${ actualRecordingMimeType } '). ` ) ;
} else {
changedMimeType = false ;
}
console . log ( 'Actual mime type used by MediaRecorder:' , actualRecordingMimeType ) ;
2026-01-01 16:55:05 +00:00
audioChunks = [ ] ;
mediaRecorder . ondataavailable = ( event ) => {
if ( event . data . size > 0 ) {
audioChunks . push ( event . data ) ;
}
} ;
mediaRecorder . start ( ) ;
2026-01-06 09:25:58 +00:00
return actualRecordingMimeType ;
2026-01-01 16:55:05 +00:00
} ,
stop : async function ( ) {
return new Promise ( ( resolve ) => {
mediaRecorder . onstop = async ( ) => {
2026-01-06 09:25:58 +00:00
const blob = new Blob ( audioChunks , { type : actualRecordingMimeType } ) ;
2026-01-01 16:55:05 +00:00
const arrayBuffer = await blob . arrayBuffer ( ) ;
const base64 = btoa (
new Uint8Array ( arrayBuffer ) . reduce ( ( data , byte ) => data + String . fromCharCode ( byte ) , '' )
) ;
mediaRecorder . stream . getTracks ( ) . forEach ( track => track . stop ( ) ) ;
2026-01-06 09:25:58 +00:00
resolve ( {
data : base64 ,
mimeType : actualRecordingMimeType ,
changedMimeType : changedMimeType ,
} ) ;
2026-01-01 16:55:05 +00:00
} ;
mediaRecorder . stop ( ) ;
} ) ;
}
} ;