Slack投稿をニコ動風に画面に流すChrome拡張機能をつくったよ〜
このコロナ禍において、ZoomやGoogle Meetを使ってオンラインミーティングを行う人が増えたのではないでしょうか。 その際にPC画面を共有して、スライドなどの資料を参加者全員で眺めるということをしていると思います。 ビデオ会議ツールのチャット機能は、わざわざ発言するまでもないようなちょっとしたリアクションなどを示すのに手軽に使えて便利ですが、ちょっと無機質な気もします。 そこで、ニコニコ動画のようにコメントが画面上を流れていく、そういうツールがあったら盛り上がりそうですよね! 実は、そういうツールは世の中にすでにあります。
投稿者は自らニックネームをつけてコメントを投稿できます。
普通のコメントと質問を区別して投稿することもできて便利です。
絵文字がふわふわ〜って出てきてかわいいです。
が、ニックネーム方式だとユーザ依存で、匿名を許容しています。 投稿されたコメントや質問の詳細が知りたいときに、誰が発言したのか不明だと進行がグダるおそれがあります。
また、コメントを後から追いたいとき、もちろんそれ以外のシーンでもコメントがSlackに存在していることが便利そのものです。 例えば検索したり、ピン留めしたり、メッセージURLを共有したり保存したり、絵文字でリアクションしたり、スレッドで話題を深堀りしたり…。
ということで、つくりました! Slackに投稿したメッセージが、画面上に流れるツール!
正確にはChromeタブ上にコメントが流れるようにするChrome拡張機能です。 その名もSlarrage(スラージ)!Slack + barrage(弾幕)から付けた造語です。
使い方はインストール後に、Chromeでお好きなSlackワークスペースのチャンネルを開きます。 すると画面上部に「Slarrage is watching this channel」という帯が表示され、このチャンネルに投稿されたメッセージが、ニコ動風コメントのように画面の上を流れるという寸法です。 実際にコメントを流すためにはもう一つ設定が必要で、コメントを流したい任意のChromタブを開き*1、Slarrageの拡張機能アイコンをクリックして飛び出る画面の「Show comments this tab」ボタンをクリックします。 そうすることで、そのタブ上で監視対象のSlackチャンネルに投稿されたメッセージが流れます。
さらに流れるテキストに添えるコマンドもいくつか実装しています。
例えば監視対象のSlackチャンネルに こんにちは [red]
と投稿すると、流れるテキスト「こんにちは」の色が赤くなるといった具合です。
テキストを流さず画面下部中央に固定表示するためのコマンド bottom
や、テキストを大きく表示するためのコマンド big
などもあります。
これらは組み合わせることが可能で こんにちは [red bottom big]
と投稿すると、「こんにちは」と赤く大きなテキストが下部中央に固定表示されます。
その他、振動するアニメーション shake
など、いろいろ実装しているので試してみてください。
そうそう、このSlarrageですがChrome拡張機能ということで、コメントが流れるのはそのChromeブラウザ上に限定されます。 Chromeの外で動くパワーポイントのようなアプリケーションなどに、コメントを流すことはできないので悪しからず。
技術的なメモ
GitHub Repoはこちら
没案
最初にこのツールを作ったときの構成は、こんな感じです。
矢印はデータの流れです。
PCやスマホなどからSlackにメッセージを投稿すると message.channels
というイベントが発生するので、それをEvent APIで受け取ります。
Event APIは、指定したURLにイベントを通知してくれる仕組みで、今回はCloud Functionsのエンドポイントを指定しました。
Cloud Functionsは投稿イベントを受け取り、その内容をFirestoreに書き込みます。 SlarrageはFirestoreの書き込みイベントを監視しているので、つまり、SlarrageはSlackにメッセージが投稿されたことを感知できるというわけです。
この構成は、最初はうまく機能しているように見えましたが、SlackのEvent APIからの通知がたまに詰まることがあり断念…。
Chrome拡張機能のみで実現
Slackの指定チャンネルへのメッセージ投稿をどうフックするかが問題でしたが、Chrome拡張機能であるSlarrageがSlackタブのDOMの変化を監視すれば実現できるのでは、と思い至りました。実際これはうまく行きました!
もっとも、APIでも何でもない=約束ではなく問答無用で破壊的な変更が起こりうるということなので、将来突然壊れる可能性はあります。
Chrome拡張機能のパーミッションとactiveTab
Chrome拡張機能をChromeウェブストアで配布しようと思い、今回が人生初の拡張機能公開だったので、5ドル払って開発者登録を行いました。 そして、ソースファイル等をまとめたzipファイルをアップロードし、審査の申請を行おうとしたところ「この拡張機能は広範囲のホスト権限を要求している」と言った旨のアラートとともに「そういうわけで審査にかなり時間かかるよ」と言われてしまい、パーミッションまわりを見直すことにしました。
Chrome拡張機能にはcontent scriptと呼ばれる、タブで開いているページ上で実行されるスクリプトを指定することができます。 次のmanifest.jsonの一部のように「どのURLにマッチしたら、そのページ上で、どのスクリプトを実行する」というのを指定します。
"content_scripts": [ { "matches": ["https://app.slack.com/*"], "js": ["content/observer.js", "content/watchingAlert.js"] }, { "matches": ["<all_urls>"], "js": ["content/presentation.js"] } ],
問題となったのは <all_urls>
という指定で、これが「広範囲のホスト権限の要求」に相当します。
あらゆるページ(URL・ホスト)でスクリプトを実行可能にすることは、要求する権限として大きいようです。
そこで、このcontent scriptを外して、activeTabという仕組みでターゲットとなるタブ、ページにスクリプトを流し込むように実装し直しました。 つまり、content scriptは自動的にスクリプトが実行されるのが問題であって、ユーザが能動的なアクションを取ればスクリプトを実行してもいいでしょうという発想っぽくて、能動的なアクションとは例えば、拡張機能アイコンを押すことによるポップアップ表示、とか。
流れるコメント
画面を流れるコメントは、DOMを生成してposition: fixedでz-indexをでっかくしてtop, leftをいい感じにしているだけで、とても単純です。 当初、少し頭を悩ませたのは、クリックやホバーなどのマウスイベントを無視したいということでした。 流れるコメントがページを操作するユーザの邪魔になったら嫌なので。
調べるとCSSにpointer-event
というプロパティがあって、これをnone
にするとマウスイベントが無視されるとのことでした。