-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Coediting: Refactor Collaborative Editing to be more independent from…
… Gutenberg
- Loading branch information
Showing
33 changed files
with
1,457 additions
and
1,286 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Gutenberg Collaborative Editing Plugin | ||
## Based on WebRTC | ||
--- | ||
|
||
### Starting App | ||
Peer starting coediting has to generate a uuid using: | ||
``` | ||
const coeditingId = Coediting.uuid(); // static function | ||
``` | ||
|
||
After that pass that to Coediting module: | ||
|
||
``` | ||
window.history.replaceState( '', '', '#' + coeditingId ); | ||
const coediting = new Coediting( coeditingId ); | ||
``` | ||
|
||
Peer not starting coediting has to join and get that coeditingId somehow possibly by sharing url. | ||
|
||
___ | ||
|
||
## API | ||
|
||
**Events** | ||
|
||
* `peerFound` - checked via long polling to /get/coeditingId route to server. | ||
``` | ||
coediting.on( 'peerFound', function( peer ) { | ||
// peer => peer signal used for connection establishment | ||
} ); | ||
``` | ||
|
||
* `peerSignal` - received from other peer as offer. | ||
``` | ||
coediting.on('peerSignal', function(signal){ | ||
// signal => signal that is received from another peer. | ||
}); | ||
``` | ||
|
||
* `peerConnected` - emitted after peerSignal and connection is established. | ||
``` | ||
coediting.on('peerConnected', function(){ | ||
// peer is connected. | ||
}); | ||
``` | ||
|
||
* `peerData - triggered when data is received. | ||
``` | ||
coediting.on('peerData', function(data){ | ||
//data is always json stringified | ||
}); | ||
``` | ||
|
||
|
||
## Data Format | ||
|
||
Payload should always be JSON object which can be sent directly using coediting.send without stringify. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/** | ||
* External dependency | ||
*/ | ||
import classnames from 'classnames'; | ||
import { connect } from 'react-redux'; | ||
|
||
/** | ||
* WordPress dependency | ||
*/ | ||
import { BlockEdit, getBlockDefaultClassname, getBlockType, hasBlockSupport } from '@wordpress/blocks'; | ||
import { addFilter } from '@wordpress/hooks'; | ||
import { getWrapperDisplayName } from '@wordpress/element'; | ||
|
||
/** | ||
* Internal dependency | ||
*/ | ||
import './style.scss'; | ||
// TODO: Move selectors to the local folder | ||
import { | ||
getFrozenBlockCollaboratorColor, | ||
getFrozenBlockCollaboratorName, | ||
isBlockFrozenByCollaborator, | ||
} from '../../editor/selectors'; | ||
|
||
const withFrozenMode = ( BlockItem ) => { | ||
const WrappedBlockItem = ( { collaboratorColor, collaboratorName, isFrozenByCollaborator, ...props } ) => { | ||
if ( ! isFrozenByCollaborator ) { | ||
return <BlockItem { ...props } />; | ||
} | ||
|
||
const { block } = props; | ||
const { attributes, name, isValid, uid } = block; | ||
const blockType = getBlockType( name ); | ||
|
||
// Determine whether the block has props to apply to the wrapper. | ||
let wrapperProps; | ||
if ( blockType.getEditWrapperProps ) { | ||
wrapperProps = blockType.getEditWrapperProps( attributes ); | ||
} | ||
|
||
// Generate a class name for the block's editable form | ||
const generatedClassName = hasBlockSupport( blockType, 'className', true ) ? | ||
getBlockDefaultClassname( block.name ) : | ||
null; | ||
const className = classnames( generatedClassName, block.attributes.className ); | ||
|
||
return ( | ||
<div | ||
className={ `editor-block-list__block is-frozen-by-collaborator is-${ collaboratorColor }` } | ||
{ ...wrapperProps } | ||
> | ||
<legend className="coediting-legend">{ collaboratorName }</legend> | ||
<div className="editor-block-list__block-edit"> | ||
{ isValid && <BlockEdit | ||
attributes={ attributes } | ||
className={ className } | ||
id={ uid } | ||
name={ name } | ||
/> } | ||
</div> | ||
</div> | ||
); | ||
}; | ||
WrappedBlockItem.displayName = getWrapperDisplayName( BlockItem, 'frozen-mode' ); | ||
|
||
const mapStateToProps = ( state, { uid } ) => ( { | ||
collaboratorColor: getFrozenBlockCollaboratorColor( state, uid ), | ||
collaboratorName: getFrozenBlockCollaboratorName( state, uid ), | ||
isFrozenByCollaborator: isBlockFrozenByCollaborator( state, uid ), | ||
} ); | ||
|
||
return connect( mapStateToProps )( WrappedBlockItem ); | ||
}; | ||
|
||
addFilter( 'editor.BlockListBlock', 'coediting/block-item/frozen-mode', withFrozenMode ); |
Oops, something went wrong.