11import { buttonsStatesSave , deleteFiles , getCurrentDateString , showModalNotify , saveBlobToFile } from "./common.js" ;
22import { logClientAction , checkAndCleanLogs , clearLogs , prepareLogs } from "./logger.js" ;
33
4+ import settings from '../settings.json' with { type : "json" } ;
5+
6+ const session_settings = settings . session_settings ;
7+
48const noPatronymicCheckbox = document . querySelector ( '#no_patronymic_checkbox' ) ;
59const permissionsStatus = document . querySelector ( '#permissions-status' ) ;
610const startDate = document . querySelector ( '#start-date' ) ;
711const recordTime = document . querySelector ( '#record-time' )
812
913let timerInterval = null ;
1014let startTime = null ;
11- let server_connection = true ;
12- chrome . storage . local . set ( { 'server_connection' : server_connection } ) ;
1315let invalidStop = ( chrome . storage . local . get ( 'invalidStop' ) ) [ 'invalidStop' ] || false ;
1416
15- const updateInvalidStopValue = ( flag ) => {
17+ async function updateInvalidStopValue ( flag ) {
1618 invalidStop = flag ;
17- chrome . storage . local . set ( { 'invalidStop' : flag } ) ;
19+ await chrome . storage . local . set ( { 'invalidStop' : flag } ) ;
1820}
1921
2022const inputElements = {
@@ -33,7 +35,8 @@ const buttonElements = {
3335 help : document . querySelector ( '.help-button' ) ,
3436} ;
3537
36- if ( ! server_connection ) {
38+ if ( ! session_settings . server_connection && ! session_settings . local_video_saving ) {
39+ // TODO: менять кнопки в зависимости от session_settings.server_connection и session_settings.local_video_saving
3740 buttonElements . upload . style . display = 'None' ;
3841 buttonElements . permissions . style . width = '368px' ;
3942}
@@ -154,8 +157,8 @@ function handleBlur(event) {
154157 }
155158}
156159
157- function saveInputValues ( ) {
158- chrome . storage . local . set ( {
160+ async function saveInputValues ( ) {
161+ await chrome . storage . local . set ( {
159162 'inputElementsValue' : {
160163 group : inputElements . group . value ,
161164 name : inputElements . name . value ,
@@ -400,15 +403,12 @@ buttonElements.permissions.addEventListener('click', async () => {
400403buttonElements . upload . addEventListener ( 'click' , async ( ) => {
401404 logClientAction ( { action : "Click upload button" } ) ;
402405
403- if ( ! server_connection ) return ;
404-
405406 const files = ( await chrome . storage . local . get ( 'tempFiles' ) ) [ 'tempFiles' ] ;
406407
407408 if ( ! files ) {
408409 logClientAction ( { action : "No files have found to upload" } ) ;
409410 buttonsStatesSave ( 'needPermissions' ) ;
410411 updateButtonsStates ( ) ;
411-
412412 } else {
413413 logClientAction ( { action : "Start uploading video" } ) ;
414414 uploadVideo ( files )
@@ -521,13 +521,6 @@ async function stopRecCallback() {
521521 }
522522 else {
523523 updateInvalidStopValue ( false ) ;
524- if ( ! server_connection ) {
525- inputElements . link . value = "" ;
526- inputElements . link . classList . remove ( 'input-valid' ) ;
527- saveInputValues ( ) ;
528- logClientAction ( "Clear link field" ) ;
529- chrome . storage . local . set ( { 'sessionId' : null } ) ;
530- }
531524 }
532525 } ) ;
533526
@@ -555,6 +548,119 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
555548 }
556549} ) ;
557550
551+ async function getSessionFormData ( files , sessionId , extension_logs ) {
552+ const formData = new FormData ( ) ;
553+ const rootDirectory = await navigator . storage . getDirectory ( ) ;
554+
555+ for ( const filename of files ) {
556+ const blob = await ( await rootDirectory . getFileHandle ( filename , { create : false } ) ) . getFile ( ) ;
557+
558+ if ( filename . includes ( 'screen' ) ) {
559+ formData . append ( 'screen_video' , blob , filename ) ;
560+ } else {
561+ formData . append ( 'camera_video' , blob , filename ) ;
562+ }
563+ }
564+
565+ formData . append ( "id" , sessionId ) ;
566+ const metadata = ( await chrome . storage . local . get ( 'metadata' ) ) [ 'metadata' ] || { } ;
567+ formData . append ( "metadata" , JSON . stringify ( metadata ) ) ;
568+
569+ // logClientAction({ action: "Prepare upload payload", sessionId: sessionId, fileNames: [combinedFileName, cameraFileName] });
570+
571+ if ( extension_logs ) {
572+ let logs = prepareLogs ( extension_logs ) ;
573+ const logsBlob = new Blob ( [ JSON . stringify ( logs , null , 2 ) ] , { type : 'application/json' } ) ;
574+ formData . append ( "logs" , logsBlob , "extension_logs.json" ) ;
575+ }
576+
577+ return formData ;
578+ }
579+
580+ async function saveFormDataFilesLocally ( formData , sessionId ) {
581+ for ( const [ key , value ] of formData . entries ( ) ) {
582+
583+ if ( ! ( value instanceof Blob ) ) continue ;
584+
585+ let filename = null ;
586+
587+ if ( key === "screen_video" || key === "camera_video" ) {
588+ filename = value . name ;
589+ }
590+
591+ else if ( key === "logs" ) {
592+ filename = `extension_logs_${ sessionId } _${ getCurrentDateString ( new Date ( ) ) } .json` ;
593+ }
594+
595+ if ( ! filename ) {
596+ filename = value . name || `${ key } _${ Date . now ( ) } ` ;
597+ }
598+
599+ await saveBlobToFile ( value , filename ) ;
600+ console . log ( `Saved FormData file locally: ${ filename } ` ) ;
601+ }
602+ }
603+
604+ async function uploadFormDataToServer ( formData , sessionId ) {
605+ logClientAction ( { action : "Send upload request" , sessionId : sessionId , messageType : "upload_video" } ) ;
606+
607+ const eventSource = new EventSource ( `http://127.0.0.1:5000/progress/${ sessionId } ` ) ;
608+
609+ const steps = 7 ;
610+
611+ eventSource . onmessage = async ( event ) => {
612+ const data = JSON . parse ( event . data ) ;
613+ if ( data . step == steps ) {
614+ logClientAction ( { action : "Data transfer completed" } ) ;
615+ eventSource . close ( ) ;
616+ // TODO Fix notify showing #142, ибо если закрыть popup здесь ничего не произойдет
617+ await showModalNotify ( [ `Статус: ${ data . message } ` ,
618+ `Отправка завершена на 100 %` ] , "Записи успешно отправлены" , true , true ) ;
619+ } else {
620+ await showModalNotify ( [ `Статус: ${ data . message } ` ,
621+ `Отправка завершена на ${ data . step * Math . floor ( 100 / steps ) } %` ] , "Идёт отправка..." , true , true ) ;
622+ }
623+ } ;
624+
625+ // Срабатывает когда не удаётся установить соединение с источником событий
626+ // TODO Наполнить err полезной информацией
627+ eventSource . onerror = async ( err ) => {
628+ logClientAction ( { action : `An error occurred while trying to connect to the server: ${ JSON . stringify ( err ) } ` } ) ;
629+ eventSource . close ( ) ;
630+ await showModalNotify ( [ `Произошла ошибка при попытке соединения с сервером!` ,
631+ "Попробуйте отправить запись ещё раз!" ,
632+ "Свяжитесь с преподавателем, если не удалось отправить три раза!" ,
633+ ] , 'Ошибка при соединении' , true , true ) ;
634+ } ;
635+
636+ try {
637+ const response = await fetch ( 'http://127.0.0.1:5000/upload_video' , {
638+ method : "POST" ,
639+ body : formData ,
640+ } ) ;
641+
642+ if ( ! response . ok ) {
643+ throw new Error ( `Ошибка при загрузке видео: ${ response . status } ` ) ;
644+ }
645+
646+ const result = await response . json ( ) ;
647+ console . log ( "Видео успешно отправлено:" , result ) ;
648+
649+ logClientAction ( { action : "Upload video succeeds" , sessionId } ) ;
650+
651+ return true ;
652+ } catch ( error ) {
653+ console . error ( "Ошибка при отправке видео:" , error ) ;
654+
655+ buttonsStatesSave ( 'failedUpload' ) ;
656+ updateButtonsStates ( ) ;
657+
658+ logClientAction ( { action : "Upload video fails" , error : error . message , sessionId } ) ;
659+
660+ return false ;
661+ }
662+ }
663+
558664async function uploadVideo ( files ) {
559665 chrome . storage . local . get ( [ 'sessionId' , 'extension_logs' ] , async ( { sessionId, extension_logs } ) => {
560666 if ( ! sessionId ) {
@@ -569,103 +675,34 @@ async function uploadVideo(files) {
569675 throw new Error ( `Ошибка при поиске записей` ) ;
570676 }
571677
572- const formData = new FormData ( ) ;
573- const rootDirectory = await navigator . storage . getDirectory ( ) ;
678+ const formData = await getSessionFormData ( files , sessionId , extension_logs ) ;
574679
575- for ( const filename of files ) {
576- const blob = await ( await rootDirectory . getFileHandle ( filename , { create : false } ) ) . getFile ( ) ;
680+ let success = true ;
577681
578- if ( filename . includes ( 'screen' ) ) {
579- formData . append ( 'screen_video' , blob , filename ) ;
580- } else {
581- formData . append ( 'camera_video' , blob , filename ) ;
582- }
583-
584- logClientAction ( `File ${ filename } saved localy` ) ;
682+ if ( session_settings . local_video_saving ) {
683+ await saveFormDataFilesLocally ( formData , sessionId ) ;
684+ }
585685
586- await saveBlobToFile ( blob , filename ) ;
686+ if ( session_settings . server_connection ) {
687+ let res = await uploadFormDataToServer ( formData , sessionId ) ;
688+ success &= res ;
587689 }
588690
589- formData . append ( "id" , sessionId ) ;
590- const metadata = ( await chrome . storage . local . get ( 'metadata' ) ) [ 'metadata' ] || { } ;
591- formData . append ( "metadata" , JSON . stringify ( metadata ) ) ;
592-
593- //logClientAction({ action: "Prepare upload payload", sessionId: sessionId, fileNames: [combinedFileName, cameraFileName] });
691+ if ( success ) {
692+ await updateInvalidStopValue ( false ) ;
693+ await chrome . storage . local . set ( { 'sessionId' : null } ) ;
594694
595- if ( extension_logs ) {
596- let logs = prepareLogs ( extension_logs ) ;
597- const logsBlob = new Blob ( [ JSON . stringify ( logs , null , 2 ) ] , { type : 'application/json' } ) ;
598- formData . append ( "logs" , logsBlob , "extension_logs.json" ) ;
695+ await deleteFiles ( ) ;
696+ await clearLogs ( ) ;
697+ logClientAction ( { action : "Clear logs after upload video" } ) ;
599698
600- const logsFileName = `extension_logs_ ${ sessionId } _ ${ getCurrentDateString ( new Date ( ) ) } .json` ;
601- await saveBlobToFile ( logsBlob , logsFileName ) ;
699+ await chrome . storage . local . remove ( "metadata" ) ;
700+ await chrome . storage . local . set ( { "session_status" : "need_init" } ) ;
602701
603- logClientAction ( { action : "Download logs file" , fileName : logsFileName } ) ;
702+ inputElements . link . value = "" ;
703+ inputElements . link . classList . remove ( 'input-valid' , 'input-invalid' ) ;
704+ await saveInputValues ( ) ;
705+ logClientAction ( "Clear link field" ) ;
604706 }
605-
606- logClientAction ( { action : "Send upload request" , sessionId : sessionId , messageType : "upload_video" } ) ;
607-
608- const eventSource = new EventSource ( `http://127.0.0.1:5000/progress/${ sessionId } ` ) ;
609-
610- const steps = 7 ;
611-
612- eventSource . onmessage = async ( event ) => {
613- const data = JSON . parse ( event . data ) ;
614- if ( data . step == steps ) {
615- logClientAction ( { action : "Data transfer completed" } ) ;
616- eventSource . close ( ) ;
617- // TODO Fix notify showing #142, ибо если закрыть popup здесь ничего не произойдет
618- await showModalNotify ( [ `Статус: ${ data . message } ` ,
619- `Отправка завершена на 100 %` ] , "Записи успешно отправлены" , true , true ) ;
620-
621- await chrome . storage . local . remove ( "metadata" ) ;
622- await chrome . storage . local . set ( { "session_status" : "need_init" } ) ;
623-
624- inputElements . link . value = "" ;
625- inputElements . link . classList . remove ( 'input-valid' , 'input-invalid' ) ;
626- saveInputValues ( ) ;
627- logClientAction ( "Clear link field" ) ;
628- } else {
629- await showModalNotify ( [ `Статус: ${ data . message } ` ,
630- `Отправка завершена на ${ data . step * Math . floor ( 100 / steps ) } %` ] , "Идёт отправка..." , true , true ) ;
631- }
632- } ;
633-
634- // Срабатывает когда не удаётся установить соединение с источником событий
635- // TODO Наполнить err полезной информацией
636- eventSource . onerror = async ( err ) => {
637- logClientAction ( { action : `An error occurred while trying to connect to the server: ${ JSON . stringify ( err ) } ` } ) ;
638- eventSource . close ( ) ;
639- await showModalNotify ( [ `Произошла ошибка при попытке соединения с сервером!` ,
640- "Попробуйте отправить запись ещё раз!" ,
641- "Свяжитесь с преподавателем, если не удалось отправить три раза!" ,
642- ] , 'Ошибка при соединении' , true , true ) ;
643- } ;
644-
645- fetch ( 'http://127.0.0.1:5000/upload_video' , {
646- method : "POST" ,
647- body : formData ,
648- } )
649- . then ( async ( response ) => {
650- if ( ! response . ok ) {
651- throw new Error ( `Ошибка при загрузке видео: ${ response . status } ` ) ;
652- }
653- const result = await response . json ( ) ;
654- console . log ( "Видео успешно отправлено:" , result ) ;
655- logClientAction ( { action : "Upload video succeeds" , sessionId : sessionId } ) ;
656- updateInvalidStopValue ( false ) ;
657- chrome . storage . local . set ( { 'sessionId' : null } ) ;
658- } )
659- . then ( async ( ) => {
660- await deleteFiles ( ) ;
661- await clearLogs ( ) ;
662- logClientAction ( { action : "Clear logs after upload video" } ) ;
663- } )
664- . catch ( error => {
665- console . error ( "Ошибка при отправке видео на сервер:" , error ) ;
666- buttonsStatesSave ( 'failedUpload' ) ;
667- updateButtonsStates ( ) ;
668- logClientAction ( { action : "Upload video fails" , error : error . message , sessionId : sessionId } ) ;
669- } ) ;
670707 } ) ;
671708}
0 commit comments