Skip to content

fixed local media local storage issue #72

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,13 @@ import { TranscriptEditor } from '@bbc/react-transcript-editor';
mediaUrl=// string url to media file - audio or video
isEditable={true}// se to true if you want to be able to edit the text
sttJsonType={ 'bbcKaldi' }// the type of STT Json transcript supported.
fileName={ this.state.fileName }// optional*
/>
```

_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)_


## System Architecture

<!-- _High level overview of system architecture_ -->
Expand Down
71 changes: 44 additions & 27 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ class App extends React.Component {
mediaUrl: null,
isTextEditable: true,
sttType: 'bbckaldi',
analyticsEvents: []
analyticsEvents: [],
fileName: 'Kate Darling Ted Talk'
};
// this.handleChangeLoadTranscriptJson = this.handleChangeLoadTranscriptJson.bind(this);
}

loadDemo() {
Expand All @@ -45,8 +45,12 @@ class App extends React.Component {
this.setState({
// transcriptData: kaldiTedTalkTranscript,
mediaUrl: fileURL,
fileName: file.name
});
}
else {
alert('select a valid audio or video file');
}
}

handleChangeLoadMediaUrl() {
Expand All @@ -59,21 +63,23 @@ class App extends React.Component {
}

handleChangeLoadTranscriptJson(files) {
const self = this;
const file = files[0];
// let type = file.type;
// TODO: add checks
// let transcriptJsonContent = FileReader.readAsText(file)
const fr = new FileReader();
fr.onload = function (e) {
// e.target.result should contain the text
console.log(JSON.parse(e.target.result));
self.setState({
transcriptData: JSON.parse(e.target.result),
// mediaUrl: tedTalkVideoUrl
});
};
fr.readAsText(file);

if (file.type ==='application/json') {
const fr = new FileReader();

fr.onload = (evt) => {
this.setState({
transcriptData: JSON.parse(evt.target.result)
});
};

fr.readAsText(file);

}
else {
alert('select a valid json file');
}
}

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

handleChangeTranscriptName = (value) => {
this.setState({ fileName: value });
}

render() {
return (
<div className={ style.container }>
Expand All @@ -133,6 +143,16 @@ class App extends React.Component {
<br />
<button onClick={ () => this.loadDemo() }>load demo</button>
<hr />
<label>Load Local Media</label>
<input
type="file"
onChange={ e => this.handleChangeLoadMedia(e.target.files) }
/>
or
<button onClick={ () => this.handleChangeLoadMediaUrl() }>
Load Media From Url
</button>
<br/>
<label>open Transcript Json</label>
<SttTypeSelect
name={ 'sttType' }
Expand All @@ -144,17 +164,6 @@ class App extends React.Component {
onChange={ e => this.handleChangeLoadTranscriptJson(e.target.files) }
/>

<br />
<label>Load Local Media</label>
<input
type="file"
onChange={ e => this.handleChangeLoadMedia(e.target.files) }
/>
or
<button onClick={ () => this.handleChangeLoadMediaUrl() }>
Load Media From Url
</button>

<br />
<label>Export transcript</label>
<button onClick={ () => this.exportTranscript() }>Export file</button>
Expand All @@ -174,11 +183,19 @@ class App extends React.Component {
<span className={ style.slider }></span>
</label>
<br />
<label>Transcript Name</label>
<input
type="text"
onChange={ e => this.handleChangeTranscriptName(e.target.value) }
value={ this.state.fileName }
/>
<br />
<button onClick={ () => this.clearLocalStorage() }>Clear Local Storage</button>
<hr/>

<TranscriptEditor
transcriptData={ this.state.transcriptData }
fileName={ this.state.fileName }
mediaUrl={ this.state.mediaUrl }
isEditable={ this.state.isTextEditable }
sttJsonType={ this.state.sttType }
Expand Down
2 changes: 1 addition & 1 deletion src/lib/TranscriptEditor/MediaPlayer/ProgressBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ProgressBar extends React.Component {
onChange={ this.props.buttonClick }
value={ this.props.value }
min='0'
max={ this.props.max }
max={ this.props.max.toString() }
/>
</div>
);
Expand Down
3 changes: 2 additions & 1 deletion src/lib/TranscriptEditor/MediaPlayer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ class MediaPlayer extends React.Component {
const playerControlsSection = (
<div className={ styles.controlsSection }>
<div className={ styles.titleBox }>
<h1 className={ styles.title }>{ this.props.mediaUrl }</h1>
<h1 className={ styles.title }>{ this.props.fileName? this.props.fileName : this.props.mediaUrl }</h1>
</div>
<PlayerControls
playMedia={ this.togglePlayMedia.bind(this) }
Expand Down Expand Up @@ -402,6 +402,7 @@ class MediaPlayer extends React.Component {
}

MediaPlayer.propTypes = {
fileName: PropTypes.string,
hookSeek: PropTypes.func,
hookPlayMedia: PropTypes.func,
hookIsPlaying: PropTypes.func,
Expand Down
1 change: 1 addition & 0 deletions src/lib/TranscriptEditor/MediaPlayer/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ video {
.title {
margin: 1em;
color: white;
height: 1em;
}

.helpText {
Expand Down
36 changes: 28 additions & 8 deletions src/lib/TranscriptEditor/TimedTextEditor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,29 +145,49 @@ class TimedTextEditor extends React.Component {
}

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

return newLastLocalSavedDate;
}

// eslint-disable-next-line class-methods-use-this
isPresentInLocalStorage(mediaUrl) {
const data = localStorage.getItem(`draftJs-${ mediaUrl }`);
if (data !== null) {
return true;
if (mediaUrl !== null) {
let mediaUrlName = mediaUrl;

if (mediaUrl.includes('blob')) {
mediaUrlName = this.props.fileName;
}

const data = localStorage.getItem(`draftJs-${ mediaUrlName }`);
if (data !== null) {
return true;
}

return false;
}

return false;
}

loadLocalSavedData(mediaUrl) {
const data = JSON.parse(localStorage.getItem(`draftJs-${ mediaUrl }`));
let mediaUrlName = mediaUrl;
if (mediaUrl.includes('blob')) {
mediaUrlName = this.props.fileName;
}
const data = JSON.parse(localStorage.getItem(`draftJs-${ mediaUrlName }`));
if (data !== null) {
const lastLocalSavedDate = localStorage.getItem(`timestamp-${ mediaUrl }`);
const lastLocalSavedDate = localStorage.getItem(`timestamp-${ mediaUrlName }`);
this.setEditorContentState(data);

return lastLocalSavedDate;
Expand Down
5 changes: 4 additions & 1 deletion src/lib/TranscriptEditor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ class TranscriptEditor extends React.Component {

render() {
const mediaPlayer = <MediaPlayer
fileName={ this.props.fileName }
hookSeek={ foo => this.setCurrentTime = foo }
hookPlayMedia={ foo => this.playMedia = foo }
hookIsPlaying={ foo => this.isPlaying = foo }
Expand Down Expand Up @@ -248,6 +249,7 @@ class TranscriptEditor extends React.Component {

<main className={ style.main }>
<TimedTextEditor
fileName={ this.props.fileName }
transcriptData={ this.state.transcriptData }
timecodeOffset={ this.state.timecodeOffset }
onWordClick={ this.handleWordClick }
Expand All @@ -274,7 +276,8 @@ TranscriptEditor.propTypes = {
mediaUrl: PropTypes.string,
isEditable: PropTypes.bool,
sttJsonType: PropTypes.string,
handleAnalyticsEvents: PropTypes.func
handleAnalyticsEvents: PropTypes.func,
fileName: PropTypes.string
};

export default TranscriptEditor;