meteor-sharejs
meteor-sharejs copied to clipboard
Next steps for sharejs
I think to prepare sharejs for the future we need to focus on these points.
- [x] Rewrite the code in ecmascript 2015
- [x] Use npm packages for code mirror and ace
- [ ] Add React components for the editor
emascript 2015
The main reason is, that I never really liked coffeescript. It will also help users with no coffeescript experience to faster dig into the code.
NPM Packages
The current importing of ace and code mirror works, but with the introduction of npm packages in meteor 1.3 this seems to be a better suitable approach.
React Components.
As React gained some serious focus in the meteor community this should be supported.
React is so much easier and faster than blaze just DO IT :)
Thanks bro <3
You may also want to check out a rather long discussion we had about supporting rich text editing over at share/ShareJS#1.
Regarding "just do it" with react: I think this is easier said than done, although I agree that having both Blaze and React components would be potentially useful.
@mizzao I'm currently working on a project which required me to use React instead of Blaze and things work perfectly. If you need my help, please let me know!
Hi @vincentracine - @DavidSichau is doing most of the work on this package now, so I'm sure he'll be interested. Do you have some example code available somewhere or posted in a gist (other than what you pasted in that other issue?)
@vincentracine It would be nice if you could share some code with me.
I am currently working on the transition to npm packages. As soon as I finish this I will focus on react.
@DavidSichau @mizzao Here you go guys. The code works but for some reason right now setting the mode or theme throws an error and so I raised a new issue but this should work.
// AceEditor.js
export default AceEditor = React.createClass({
getInitialState(){
return {
doc: null,
editor: null
}
},
componentDidMount(){
// Get Ace Editor from DOM
this.setState({
editor: ace.edit("editor")
});
// Set Ace Editor behaviour
//this.setTheme('ace/theme/chrome');
//this.state.editor.getSession().setMode("ace/mode/python");
this.state.editor.setFontSize(14);
this.state.editor.setShowPrintMargin(false);
this.state.editor.getSession().setUseWrapMode(true);
this.state.editor.$blockScrolling = Infinity;
this.state.editor.resize();
this.onChange();
},
shouldComponentUpdate(nextProps, nextState) {
return nextProps.docid !== this.props.docid;
},
componentDidUpdate(){
this.onChange();
},
componentWillUnmount(){
// Disconnect from ShareJS
this.disconnect();
// Clean up Ace memory to avoid memory leaks
this.state.editor.destroy();
},
// ------- ShareJS
onChange(){
// Doesn't have a document opened but wants to connect
if(!this.isConnected() && this.props.docid){
this.connect(this.props.docid);
}
// Has a document opened but wants to open a new document
if(this.isConnected() && this.props.docid){
this.disconnect();
this.connect(this.props.docid);
}
// Has a document opened but wants to close it
if(this.isConnected() && !this.props.docid){
this.disconnect();
}
},
connect(documentId){
let self = this;
if(this.isConnected()){
throw new Error('Already connected to ShareJS');
}
// Open the document
sharejs.open(documentId, 'text', function(error, doc){
if(error) {
console.error("Connection error:", error);
}else{
// Update state
self.setState({ doc: doc });
// Check we are connected
if(self.isConnected()){
// Attach ace editor to document
doc.attach_ace(self.state.editor);
console.log('Opened document [',documentId,']');
}else{
console.error("Document was opened but closed right away");
}
}
});
},
disconnect(){
if(this.isConnected()){
let name = this.state.doc.name;
this.state.doc.close();
if(this.state.doc.state === 'closed'){
console.log('Closed document [',name,']');
}else{
console.error('Failed to close document [',name,']');
}
this.state.doc.detach_ace();
}
},
isConnected(){
return this.state.doc != null && this.state.doc.state === 'open';
},
// ------- End of ShareJS
// ------- Editor State
setTheme(theme){
this.state.editor.setTheme(theme);
},
getAceInstance(){
return this.state.editor;
},
getText(){
return this.state.editor ? this.state.editor.getValue() : null;
},
// ------- End of Editor State
render() {
return (
<div id='editor' ref="editor" data-doc={this.props.docid} className="shareJSAce"></div>
)
}
});
And you can use it like this:
EditorPage = React.createClass({
mixins: [ReactMeteorData],
getMeteorData() {
return {
currentUser: Meteor.user(),
document: Documents.findOne({_id: this.props.docId})
}
},
ready(){
return this.data.document;
},
render(){
return (
<Row class="container-fluid">
<div className="col-xs-12">
<h3 className="file-name">{this.ready() ? this.data.document.title : 'Loading...'}</h3>
{this.ready() ? (
<AceEditor ref="editor" docid={this.props.docId}/>
) : null}
</div>
</Row>
)
}
});
@vincentracine Sorry for the long delay. I will take a look at this. I think the best would be to distribute it as an individual package. Something like sharejs-ace-react
.
I will first merge my other pull request and than have a look at your code.