@@ -8,19 +8,15 @@ import 'springboard/modules/files/files_module';
88
99import type { FileSaver , RecordingConfig } from './services/recorder' ;
1010
11+ // @platform "node"
12+ import { uploadFile } from './services/upload_service' ;
13+ // @platform end
14+
1115let fileSaver : FileSaver | undefined ;
1216
1317// @platform "node"
1418import fs from 'node:fs' ;
15- fileSaver = {
16- writeFile : async ( fileName , buffer ) => {
17- if ( ! fs . existsSync ( './midi_files' ) ) {
18- fs . mkdirSync ( 'midi_files' )
19- }
20-
21- await fs . promises . writeFile ( fileName , buffer ) ;
22- } ,
23- } ;
19+ // fileSaver will be set inside the module after recordingConfig is available
2420// @platform end
2521
2622import { MidiRecorderImpl } from './services/recorder' ;
@@ -35,25 +31,51 @@ type DraftedFile = {
3531
3632const initialRecordingConfig : RecordingConfig = {
3733 inactivityTimeLimitSeconds : 60 ,
34+ uploaderUrl : '' ,
3835} ;
3936
4037springboard . registerModule ( 'JamScribe' , { } , async ( moduleAPI ) => {
41- // @platform "node"
42- await moduleAPI . getModule ( 'io' ) . ensureListening ( ) ;
43- // @platform end
38+ if ( moduleAPI . deps . core . isMaestro ( ) ) {
39+ await moduleAPI . getModule ( 'io' ) . ensureListening ( ) ;
40+ }
4441
4542 const recordingConfig = await moduleAPI . statesAPI . createPersistentState ( 'recordingConfig' , initialRecordingConfig ) ;
4643 const draftRecordingConfig = await moduleAPI . statesAPI . createSharedState ( 'draftRecordingConfig' , recordingConfig . getState ( ) ) ;
4744
45+ // @platform "node"
46+ fileSaver = {
47+ writeFile : async ( fileName , buffer ) => {
48+ if ( ! fs . existsSync ( './midi_files' ) ) {
49+ fs . mkdirSync ( 'midi_files' )
50+ }
51+
52+ await fs . promises . writeFile ( fileName , buffer ) ;
53+
54+ try {
55+ await uploadFile ( fileName , 'audio/midi' , buffer , recordingConfig . getState ( ) . uploaderUrl ) ;
56+ } catch ( error ) {
57+ console . error ( 'Upload failed, but file saved locally:' , error ) ;
58+ }
59+ } ,
60+ } ;
61+ // @platform end
62+
4863 const logMessages = await moduleAPI . statesAPI . createSharedState < LogMessage [ ] > ( 'logMessages' , [ ] ) ;
4964 const draftedFiles = await moduleAPI . statesAPI . createSharedState < DraftedFile [ ] > ( 'draftedFiles' , [ ] ) ;
5065
51- const changeDraftInactivityTimeLimit = moduleAPI . createAction ( 'changeDraftInactivityTimeLimit' , { } , async ( { limit} : { limit : number } ) => {
52- draftRecordingConfig . setState ( c => ( { ...c , inactivityTimeLimitSeconds : limit } ) ) ;
53- } ) ;
54-
55- const submitInactivityTimeLimit = moduleAPI . createAction ( 'submitInactivityTimeLimit' , { } , async ( ) => {
56- recordingConfig . setState ( c => ( { ...c , inactivityTimeLimitSeconds : draftRecordingConfig . getState ( ) . inactivityTimeLimitSeconds } ) ) ;
66+ const actions = moduleAPI . createActions ( {
67+ changeDraftInactivityTimeLimit : async ( { limit} : { limit : number } ) => {
68+ draftRecordingConfig . setState ( c => ( { ...c , inactivityTimeLimitSeconds : limit } ) ) ;
69+ } ,
70+ submitInactivityTimeLimit : async ( ) => {
71+ recordingConfig . setState ( c => ( { ...c , inactivityTimeLimitSeconds : draftRecordingConfig . getState ( ) . inactivityTimeLimitSeconds } ) ) ;
72+ } ,
73+ changeDraftUploaderUrl : async ( { url} : { url : string } ) => {
74+ draftRecordingConfig . setState ( c => ( { ...c , uploaderUrl : url } ) ) ;
75+ } ,
76+ submitUploaderUrl : async ( ) => {
77+ recordingConfig . setState ( c => ( { ...c , uploaderUrl : draftRecordingConfig . getState ( ) . uploaderUrl } ) ) ;
78+ } ,
5779 } ) ;
5880
5981 moduleAPI . registerRoute ( '/' , { } , ( ) => (
@@ -63,8 +85,12 @@ springboard.registerModule('JamScribe', {}, async (moduleAPI) => {
6385 recordingConfig = { recordingConfig . useState ( ) }
6486
6587 draftInactivityTimeLimit = { draftRecordingConfig . useState ( ) . inactivityTimeLimitSeconds }
66- onDraftInactivityTimeLimitChange = { ( limit : number ) => changeDraftInactivityTimeLimit ( { limit} ) }
67- submitInactivityTimeLimitChange = { ( ) => submitInactivityTimeLimit ( { } ) }
88+ onDraftInactivityTimeLimitChange = { ( limit : number ) => actions . changeDraftInactivityTimeLimit ( { limit} ) }
89+ submitInactivityTimeLimitChange = { ( ) => actions . submitInactivityTimeLimit ( ) }
90+
91+ draftUploaderUrl = { draftRecordingConfig . useState ( ) . uploaderUrl }
92+ onDraftUploaderUrlChange = { ( url : string ) => actions . changeDraftUploaderUrl ( { url} ) }
93+ submitUploaderUrlChange = { ( ) => actions . submitUploaderUrl ( ) }
6894 />
6995 ) ) ;
7096
@@ -76,7 +102,7 @@ springboard.registerModule('JamScribe', {}, async (moduleAPI) => {
76102 // default implementation of file saver
77103 if ( ! fileSaver ) {
78104 fileSaver = {
79- writeFile : ( fileName , buffer ) => {
105+ writeFile : async ( fileName , buffer ) => {
80106 const filesModule = moduleAPI . deps . module . moduleRegistry . getModule ( 'Files' ) ;
81107 const file = new File ( [
82108 new Blob ( [ buffer . toString ( ) ] )
@@ -120,6 +146,10 @@ type MainProps = {
120146 draftInactivityTimeLimit : number ;
121147 onDraftInactivityTimeLimitChange : ( newLimit : number ) => void ;
122148 submitInactivityTimeLimitChange : ( ) => void ;
149+
150+ draftUploaderUrl : string ;
151+ onDraftUploaderUrlChange : ( newUrl : string ) => void ;
152+ submitUploaderUrlChange : ( ) => void ;
123153}
124154
125155const Main = ( {
@@ -128,7 +158,10 @@ const Main = ({
128158 recordingConfig,
129159 draftInactivityTimeLimit,
130160 onDraftInactivityTimeLimitChange,
131- submitInactivityTimeLimitChange
161+ submitInactivityTimeLimitChange,
162+ draftUploaderUrl,
163+ onDraftUploaderUrlChange,
164+ submitUploaderUrlChange
132165} : MainProps ) => {
133166 const [ isConfigModalOpen , setIsConfigModalOpen ] = useState ( false ) ;
134167
@@ -152,6 +185,9 @@ const Main = ({
152185 draftInactivityTimeLimit = { draftInactivityTimeLimit }
153186 onDraftInactivityTimeLimitChange = { onDraftInactivityTimeLimitChange }
154187 submitInactivityTimeLimitChange = { submitInactivityTimeLimitChange }
188+ draftUploaderUrl = { draftUploaderUrl }
189+ onDraftUploaderUrlChange = { onDraftUploaderUrlChange }
190+ submitUploaderUrlChange = { submitUploaderUrlChange }
155191 />
156192
157193 < div className = "main-grid" >
@@ -192,7 +228,7 @@ const Main = ({
192228 </ div >
193229 < ul className = "log-list" >
194230 { logs . length > 0 ? (
195- [ ...logs ] . reverse ( ) . map ( ( logEntry , i ) => {
231+ [ ...logs ] . reverse ( ) . map ( ( logEntry ) => {
196232 const formatTime = ( date : Date | string | number ) => {
197233 const dateObj = new Date ( date ) ;
198234 const now = new Date ( ) ;
@@ -218,7 +254,7 @@ const Main = ({
218254 < li key = { logEntry . id } className = 'log-item fade-in' >
219255 < span className = "log-timestamp" > { formatTime ( logEntry . timestamp ) } </ span >
220256 < span className = "log-message" > { logEntry . message } </ span >
221- </ li >
257+ </ li >
222258 ) ;
223259 } )
224260 ) : (
0 commit comments