共同編集できる仕組みが作れるGoogle Drive Realtime APIを使ってみる
二度目の登場となります。 新規事業推進部のネコ好きセイカイです。
最近社内でもちょくちょく子供が生まれるor生まれた方等がいらっしゃいますが、 子供等作らずにみんなネコを飼った方が色々幸せになれるかと思います。
さて今回は「Google Drive Realtime API」を弄ってみようかと思います。
https://developers.google.com/drive/realtime/
何が出来るのか
Google Drive で実現されているような、リアルタイムに1つのドキュメントを共同編集する仕組みが提供されています。 とりあえず、Quickstartを参考にテキストの読み書きをしてみます。
準備
まず準備としてAPIを有効化する必要があります。
- API ConsoleにアクセスしてServiceタブから「DriveAPI」を有効化
- API AccessタブからOAuthClientIDを作成してClientIDをメモります。
準備は以上で完了です。
実装
下記URLからチュートリアル記事内のhtmlとjsコードと同様のファイルを作成します。
realtime-quickstart index.htmlを編集して、該当箇所に準備でメモったclientIdを挿入します。
ここまでで、用意されたコードが動きますので、サーバー上にアップして見てみます。
動かしてみると、左右のテキストエリアが同期しているのが分かります。
同様のURLをブラウザで開くと、ほぼリアルタイムに同期していますね。
処理を追う
realtime-client-utils.jsの内容は、認証と読み込みの処理の様ですので、リアルタイムなコラボレーション作業の実装はindex.htmlのscriptタグ内です。 処理の流れとしては下記のようになっています
- モデルを初期化して、テキストの初期値をセット(initializeModel)
- テキストエリアにリアルタイムなデータの読み書きをバインディング(onFileLoaded)
- テキスト変化時のイベントを拾ってテキストエリアに反映
- テキストエリアの有効化
下記で文字列のリアルタイム編集をするオブジェクトを生成しているようです。
1 |
[code lang="js"]var string = doc.getModel().getRoot().get('text');[/code] |
処理内容と使用しているinterfaceからgapi.drive.realtime.CollaborativeStringであることが分かります。 gapi.drive.realtime.CollaborativeString
要するにCollaborativeStringに文字列を渡すとサーバー側に送られ、サーバ側から変更が通知されるとCollaborativeStringにTEXT_INSERTED、TEXT_DELETED等のイベントが通知されるということのようです。
エディタを作ってみる
試しにということでeclipse orionを利用してrealtimeな共同編集が出来るエディタを作ってみます。
※orionに関しては(更新,埋め込み方法)
上で使ったindex.htmlを改変します。 Header等にorionの読み込みを追加
1 2 3 4 5 6 7 8 9 10 11 |
[sourcecode lang="html"] <link rel="stylesheet" type="text/css" href="https://eclipse.org/orion/editor/releases/3.0/built-editor.css"/> <script src="https://eclipse.org/orion/editor/releases/3.0/built-editor.js"></script> <style> pre.orionEditor { padding: 0px; border: 1px solid lightgrey; height: 500px; } </style> [/sourcecode] |
テキストエリアは一旦削除して、エディタの表示領域を追加。
1 |
[code lang="html"]<pre class="orionEditor" data-editor-lang="js"></pre>[/code] |
scriptタグ内のonFileLoadedを修正
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
[javascript]function onFileLoaded(doc) { require(["orion/editor/edit"], function (edit) { var orionEditor = edit({className:"orionEditor"})[0]; var string = doc.getModel().getRoot().get('text'); //CollaborativeStringの変更通知を受取 var updateEditor = function (event) { //キャレット位置の保持 var offset = orionEditor.getCaretOffset(); var lineIndex = orionEditor.getModel().getLineAtOffset(offset); //差分があれば上書き if (string.toString() != orionEditor.getText()) orionEditor.setText(string.toString()); //キャレット位置を戻す(差分&カラム位置はとりあえず無視) orionEditor.onGotoLine(lineIndex, 0, 0); }; string.addEventListener(gapi.drive.realtime.EventType.TEXT_INSERTED, updateEditor); string.addEventListener(gapi.drive.realtime.EventType.TEXT_DELETED, updateEditor); //初期テキストの読み込み orionEditor.setText(string.toString()); //エディタの変更内容をCollaborativeStringにセット orionEditor.getModel().addEventListener("Changed", function (event) { string.setText(orionEditor.getText()); }, false); }); } [/javascript] |
細かい部分を考慮出来ていないので、双方で操作すると微妙な感じですが、なんとなく動きますね。
URLのfileIdがGoogleDrive内のDocumentIdとなり、異なるfileIdでコラボレートすることは出来ません。
共有設定等はDrive側の設定値に依存しますので、プライベートなものを他人と共有は出来ません。
このあたりもAPIから許可可能?かもしれませんが、今回は一旦ここまでの内容です。
フルソースは下記に。(clientIdはダミーなので設定の必要があります)
ソースコード
色々可能性がありそうなので、皆さんも弄って遊んでみると楽しいかと思います。 では、とりあえずネコの写真を置いときます。