Skip to content

Commit 650651a

Browse files
authored
fixed local media local storage issue (#72)
* fixed local media local storage issue added optional fileName param to use as key for saving local media into local storage. only catch is that the mediaUrl should be present along side the transcriptData when initialising the component * PR changes * fixed progressBar issue max value needs to be cast to string
1 parent d9d1b6b commit 650651a

File tree

7 files changed

+84
-38
lines changed

7 files changed

+84
-38
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,13 @@ import { TranscriptEditor } from '@bbc/react-transcript-editor';
6666
mediaUrl=// string url to media file - audio or video
6767
isEditable={true}// se to true if you want to be able to edit the text
6868
sttJsonType={ 'bbcKaldi' }// the type of STT Json transcript supported.
69+
fileName={ this.state.fileName }// optional*
6970
/>
7071
```
7172

73+
_Note: `fileName` it is optional but it's needed if working with user uploaded local media in the browser, to be able to save and retrieve from local storage. For instance if you are passing a blob url to `mediaUrl` using `createObjectURL` this url is randomly re-generated on every page refresh so you wouldn't be able to restore a session, as `mediaUrl` is used as the local storage key. See demo app for more detail example of this[`./src/index.js`](./src/index.js)_
74+
75+
7276
## System Architecture
7377

7478
<!-- _High level overview of system architecture_ -->

src/index.js

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ class App extends React.Component {
1818
mediaUrl: null,
1919
isTextEditable: true,
2020
sttType: 'bbckaldi',
21-
analyticsEvents: []
21+
analyticsEvents: [],
22+
fileName: 'Kate Darling Ted Talk'
2223
};
23-
// this.handleChangeLoadTranscriptJson = this.handleChangeLoadTranscriptJson.bind(this);
2424
}
2525

2626
loadDemo() {
@@ -45,8 +45,12 @@ class App extends React.Component {
4545
this.setState({
4646
// transcriptData: kaldiTedTalkTranscript,
4747
mediaUrl: fileURL,
48+
fileName: file.name
4849
});
4950
}
51+
else {
52+
alert('select a valid audio or video file');
53+
}
5054
}
5155

5256
handleChangeLoadMediaUrl() {
@@ -59,21 +63,23 @@ class App extends React.Component {
5963
}
6064

6165
handleChangeLoadTranscriptJson(files) {
62-
const self = this;
6366
const file = files[0];
64-
// let type = file.type;
65-
// TODO: add checks
66-
// let transcriptJsonContent = FileReader.readAsText(file)
67-
const fr = new FileReader();
68-
fr.onload = function (e) {
69-
// e.target.result should contain the text
70-
console.log(JSON.parse(e.target.result));
71-
self.setState({
72-
transcriptData: JSON.parse(e.target.result),
73-
// mediaUrl: tedTalkVideoUrl
74-
});
75-
};
76-
fr.readAsText(file);
67+
68+
if (file.type ==='application/json') {
69+
const fr = new FileReader();
70+
71+
fr.onload = (evt) => {
72+
this.setState({
73+
transcriptData: JSON.parse(evt.target.result)
74+
});
75+
};
76+
77+
fr.readAsText(file);
78+
79+
}
80+
else {
81+
alert('select a valid json file');
82+
}
7783
}
7884

7985
handleIsTextEditable = () => {
@@ -117,6 +123,10 @@ class App extends React.Component {
117123
this.setState({ analyticsEvents: [ ...this.state.analyticsEvents, event ] });
118124
}
119125

126+
handleChangeTranscriptName = (value) => {
127+
this.setState({ fileName: value });
128+
}
129+
120130
render() {
121131
return (
122132
<div className={ style.container }>
@@ -133,6 +143,16 @@ class App extends React.Component {
133143
<br />
134144
<button onClick={ () => this.loadDemo() }>load demo</button>
135145
<hr />
146+
<label>Load Local Media</label>
147+
<input
148+
type="file"
149+
onChange={ e => this.handleChangeLoadMedia(e.target.files) }
150+
/>
151+
or
152+
<button onClick={ () => this.handleChangeLoadMediaUrl() }>
153+
Load Media From Url
154+
</button>
155+
<br/>
136156
<label>open Transcript Json</label>
137157
<SttTypeSelect
138158
name={ 'sttType' }
@@ -144,17 +164,6 @@ class App extends React.Component {
144164
onChange={ e => this.handleChangeLoadTranscriptJson(e.target.files) }
145165
/>
146166

147-
<br />
148-
<label>Load Local Media</label>
149-
<input
150-
type="file"
151-
onChange={ e => this.handleChangeLoadMedia(e.target.files) }
152-
/>
153-
or
154-
<button onClick={ () => this.handleChangeLoadMediaUrl() }>
155-
Load Media From Url
156-
</button>
157-
158167
<br />
159168
<label>Export transcript</label>
160169
<button onClick={ () => this.exportTranscript() }>Export file</button>
@@ -174,11 +183,19 @@ class App extends React.Component {
174183
<span className={ style.slider }></span>
175184
</label>
176185
<br />
186+
<label>Transcript Name</label>
187+
<input
188+
type="text"
189+
onChange={ e => this.handleChangeTranscriptName(e.target.value) }
190+
value={ this.state.fileName }
191+
/>
192+
<br />
177193
<button onClick={ () => this.clearLocalStorage() }>Clear Local Storage</button>
178194
<hr/>
179195

180196
<TranscriptEditor
181197
transcriptData={ this.state.transcriptData }
198+
fileName={ this.state.fileName }
182199
mediaUrl={ this.state.mediaUrl }
183200
isEditable={ this.state.isTextEditable }
184201
sttJsonType={ this.state.sttType }

src/lib/TranscriptEditor/MediaPlayer/ProgressBar.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class ProgressBar extends React.Component {
1414
onChange={ this.props.buttonClick }
1515
value={ this.props.value }
1616
min='0'
17-
max={ this.props.max }
17+
max={ this.props.max.toString() }
1818
/>
1919
</div>
2020
);

src/lib/TranscriptEditor/MediaPlayer/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ class MediaPlayer extends React.Component {
360360
const playerControlsSection = (
361361
<div className={ styles.controlsSection }>
362362
<div className={ styles.titleBox }>
363-
<h1 className={ styles.title }>{ this.props.mediaUrl }</h1>
363+
<h1 className={ styles.title }>{ this.props.fileName? this.props.fileName : this.props.mediaUrl }</h1>
364364
</div>
365365
<PlayerControls
366366
playMedia={ this.togglePlayMedia.bind(this) }
@@ -402,6 +402,7 @@ class MediaPlayer extends React.Component {
402402
}
403403

404404
MediaPlayer.propTypes = {
405+
fileName: PropTypes.string,
405406
hookSeek: PropTypes.func,
406407
hookPlayMedia: PropTypes.func,
407408
hookIsPlaying: PropTypes.func,

src/lib/TranscriptEditor/MediaPlayer/index.module.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ video {
3030
.title {
3131
margin: 1em;
3232
color: white;
33+
height: 1em;
3334
}
3435

3536
.helpText {

src/lib/TranscriptEditor/TimedTextEditor/index.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,29 +145,49 @@ class TimedTextEditor extends React.Component {
145145
}
146146

147147
localSave = () => {
148-
const mediaUrl = this.props.mediaUrl;
148+
let mediaUrlName = this.props.mediaUrl;
149+
// if using local media instead of using random blob name
150+
// that makes it impossible to retrieve from on page refresh
151+
// use file name
152+
if (this.props.mediaUrl.includes('blob')) {
153+
mediaUrlName = this.props.fileName;
154+
}
149155
const data = convertToRaw(this.state.editorState.getCurrentContent());
150-
localStorage.setItem(`draftJs-${ mediaUrl }`, JSON.stringify(data));
156+
localStorage.setItem(`draftJs-${ mediaUrlName }`, JSON.stringify(data));
151157
const newLastLocalSavedDate = new Date().toString();
152-
localStorage.setItem(`timestamp-${ mediaUrl }`, newLastLocalSavedDate);
158+
localStorage.setItem(`timestamp-${ mediaUrlName }`, newLastLocalSavedDate);
153159

154160
return newLastLocalSavedDate;
155161
}
156162

157163
// eslint-disable-next-line class-methods-use-this
158164
isPresentInLocalStorage(mediaUrl) {
159-
const data = localStorage.getItem(`draftJs-${ mediaUrl }`);
160-
if (data !== null) {
161-
return true;
165+
if (mediaUrl !== null) {
166+
let mediaUrlName = mediaUrl;
167+
168+
if (mediaUrl.includes('blob')) {
169+
mediaUrlName = this.props.fileName;
170+
}
171+
172+
const data = localStorage.getItem(`draftJs-${ mediaUrlName }`);
173+
if (data !== null) {
174+
return true;
175+
}
176+
177+
return false;
162178
}
163179

164180
return false;
165181
}
166182

167183
loadLocalSavedData(mediaUrl) {
168-
const data = JSON.parse(localStorage.getItem(`draftJs-${ mediaUrl }`));
184+
let mediaUrlName = mediaUrl;
185+
if (mediaUrl.includes('blob')) {
186+
mediaUrlName = this.props.fileName;
187+
}
188+
const data = JSON.parse(localStorage.getItem(`draftJs-${ mediaUrlName }`));
169189
if (data !== null) {
170-
const lastLocalSavedDate = localStorage.getItem(`timestamp-${ mediaUrl }`);
190+
const lastLocalSavedDate = localStorage.getItem(`timestamp-${ mediaUrlName }`);
171191
this.setEditorContentState(data);
172192

173193
return lastLocalSavedDate;

src/lib/TranscriptEditor/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ class TranscriptEditor extends React.Component {
196196

197197
render() {
198198
const mediaPlayer = <MediaPlayer
199+
fileName={ this.props.fileName }
199200
hookSeek={ foo => this.setCurrentTime = foo }
200201
hookPlayMedia={ foo => this.playMedia = foo }
201202
hookIsPlaying={ foo => this.isPlaying = foo }
@@ -248,6 +249,7 @@ class TranscriptEditor extends React.Component {
248249

249250
<main className={ style.main }>
250251
<TimedTextEditor
252+
fileName={ this.props.fileName }
251253
transcriptData={ this.state.transcriptData }
252254
timecodeOffset={ this.state.timecodeOffset }
253255
onWordClick={ this.handleWordClick }
@@ -274,7 +276,8 @@ TranscriptEditor.propTypes = {
274276
mediaUrl: PropTypes.string,
275277
isEditable: PropTypes.bool,
276278
sttJsonType: PropTypes.string,
277-
handleAnalyticsEvents: PropTypes.func
279+
handleAnalyticsEvents: PropTypes.func,
280+
fileName: PropTypes.string
278281
};
279282

280283
export default TranscriptEditor;

0 commit comments

Comments
 (0)