@@ -7,6 +7,8 @@ import {createPresentationView, createShowCreatorView, createPresenterView} from
77import WorkingFile from './workingFile'
88import log from 'electron-log/main' ;
99
10+ let VidFilestream ;
11+
1012
1113if ( app . isPackaged ) {
1214 log . initialize ( { spyRendererConsole : true } ) ;
@@ -27,13 +29,105 @@ if (require('electron-squirrel-startup')) {
2729 app . quit ( ) ;
2830}
2931
32+ protocol . registerSchemesAsPrivileged ( [
33+ {
34+ scheme : "media" ,
35+ privileges : {
36+ // secure: true,
37+ bypassCSP : true ,
38+ stream : true ,
39+ } ,
40+ } ,
41+ ] )
3042
3143app . disableHardwareAcceleration ( )
3244
45+ function parseRangeRequests ( text , size ) {
46+ const token = text . split ( "=" ) ;
47+ if ( token . length !== 2 || token [ 0 ] !== "bytes" ) {
48+ return [ ] ;
49+ }
50+
51+ return token [ 1 ]
52+ . split ( "," )
53+ . map ( ( v ) => parseRange ( v , size ) )
54+ . filter ( ( [ start , end ] ) => ! isNaN ( start ) && ! isNaN ( end ) && start <= end ) ;
55+ }
56+
57+ const NAN_ARRAY = [ NaN , NaN ] ;
58+
59+ function parseRange ( text , size ) {
60+ const token = text . split ( "-" ) ;
61+ if ( token . length !== 2 ) {
62+ return NAN_ARRAY ;
63+ }
64+
65+ const startText = token [ 0 ] . trim ( ) ;
66+ const endText = token [ 1 ] . trim ( ) ;
67+
68+ if ( startText === "" ) {
69+ if ( endText === "" ) {
70+ return NAN_ARRAY ;
71+ } else {
72+ let start = size - Number ( endText ) ;
73+ if ( start < 0 ) {
74+ start = 0 ;
75+ }
76+
77+ return [ start , size - 1 ] ;
78+ }
79+ } else {
80+ if ( endText === "" ) {
81+ return [ Number ( startText ) , size - 1 ] ;
82+ } else {
83+ let end = Number ( endText ) ;
84+ if ( end >= size ) {
85+ end = size - 1 ;
86+ }
87+
88+ return [ Number ( startText ) , end ] ;
89+ }
90+ }
91+ }
92+
3393// This method will be called when Electron has finished
3494// initialization and is ready to create browser windows.
3595// Some APIs can only be used after this event occurs.
3696app . on ( 'ready' , ( ) => {
97+ protocol . handle ( "media" , ( request ) => {
98+ // https://github.com/electron/electron/issues/38749#issuecomment-1681531939
99+ const fp = path . join ( currentProject . basePath , decodeURIComponent ( request . url . slice ( 'media://' . length ) ) )
100+ const stats = fs . statSync ( fp ) ;
101+
102+ // console.log(fp, stats)
103+ const headers = new Headers ( ) ;
104+ headers . set ( "Accept-Ranges" , "bytes" ) ;
105+ headers . set ( "Content-Type" , "video/mp4" ) ;
106+
107+ let status = 200 ;
108+ const rangeText = request . headers . get ( "range" ) ;
109+
110+ if ( rangeText ) {
111+ const ranges = parseRangeRequests ( rangeText , stats . size ) ;
112+
113+ const [ start , end ] = ranges [ 0 ] ;
114+ // console.log(rangeText, stats.size, start, end);
115+ headers . set ( "Content-Length" , `${ end - start + 1 } ` ) ;
116+ headers . set ( "Content-Range" , `bytes ${ start } -${ end } /${ stats . size } ` ) ;
117+ status = 206 ;
118+ VidFilestream = fs . createReadStream ( fp , { start, end} ) ;
119+ } else {
120+ headers . set ( "Content-Length" , `${ stats . size } ` ) ;
121+ VidFilestream = fs . createReadStream ( fp ) ;
122+
123+ }
124+
125+ return new Response ( VidFilestream , {
126+ headers,
127+ status,
128+ } ) ;
129+ } )
130+
37131 showCreatorView = createShowCreatorView ( )
38132 showCreatorView . on ( 'close' , ( e ) => {
39133 if ( currentProject . isOpened ) {
@@ -47,7 +141,10 @@ app.on('ready', () => {
47141 if ( choice === 1 ) {
48142 e . preventDefault ( )
49143 } else {
50-
144+ if ( currentProject . isOpened ) {
145+ VidFilestream ?. destroy ( )
146+ currentProject . closeProject ( )
147+ }
51148 }
52149 }
53150 } )
@@ -57,8 +154,7 @@ app.on('ready', () => {
57154// for applications and their menu bar to stay active until the user quits
58155// explicitly with Cmd + Q.
59156app . on ( 'window-all-closed' , ( ) => {
60- /*if (currentProject.isOpened)
61- currentProject.closeProject()*/
157+
62158 if ( process . platform !== 'darwin' ) {
63159 app . quit ( ) ;
64160 }
@@ -93,9 +189,11 @@ ipcMain.handle("file-opened", async (e, data) => {
93189 let mainWindow = BrowserWindow . getFocusedWindow ( ) . getParentWindow ( ) ;
94190 BrowserWindow . getFocusedWindow ( ) . destroy ( )
95191
96- /*if (currentProject.isOpened) {
192+ if ( currentProject . isOpened ) {
193+ VidFilestream ?. destroy ( )
194+ mainWindow . webContents . send ( "slideshow:destroy" )
97195 currentProject . closeProject ( )
98- }*/
196+ }
99197
100198 currentProject = new WorkingFile ( data )
101199
@@ -104,14 +202,19 @@ ipcMain.handle("file-opened", async (e, data) => {
104202 } else {
105203 currentProject . openProject ( )
106204 }
107- console . log ( currentProject . toObject ( ) )
108- mainWindow . setTitle ( `ChoirSlide • ${ currentProject . projectName } ` )
205+ mainWindow . setTitle ( `ChoirSlide - ${ currentProject . projectName } ` )
109206 mainWindow . webContents . send ( "file-params" , currentProject . toObject ( ) ) ;
110207} )
111208
112209ipcMain . handle ( "file-save" , ( e , content ) => {
210+ dialog . showMessageBox ( BrowserWindow . fromId ( e . frameId ) , {
211+ title : "File Save" ,
212+ message : "File Is Saving" ,
213+ type : "info" ,
214+ } )
215+
113216 currentProject . saveProject ( content ) . then ( ( ) => {
114- dialog . showMessageBoxSync ( {
217+ dialog . showMessageBox ( BrowserWindow . fromId ( e . frameId ) , {
115218 title : "File Save" ,
116219 message : "File Saved Successfully" ,
117220 type : "info"
@@ -207,6 +310,7 @@ ipcMain.handle("slideshow:start", (e, content) => {
207310 presentationView . webContents . send ( "main:presentation" , { type : "init" , data} )
208311 } )
209312 showCreatorView . destroy ( )
313+ presenterView . focus ( )
210314 } else {
211315 dialog . showMessageBoxSync ( showCreatorView , {
212316 type : 'error' ,
0 commit comments