Slackのチャンネルを並べて表示させるChrome拡張作った（中身の解説）

slackのチャンネルを並べて見れるようにしたい思い、これを実現するChromeのExtension「Slack Columns」を作りました。この記事ではこのExtensionが何を行っているかを解説します。

# 作ったもの
作ったChromeのExtensionは[こちら](https://chrome.google.com/webstore/detail/slack-columns/jemgmalconedknjjjbfbigecijkdnkgi?hl=ja)です。

- Chrome Extension: https://chrome.google.com/webstore/detail/slack-columns/jemgmalconedknjjjbfbigecijkdnkgi?hl=ja
- Github: https://github.com/k8shiro/chrome_extension_slack_columns

こんな感じでSlackのチャンネルを並べて表示できます。

![slack01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86684/f7f5bc9a-1057-f97a-58b1-adc4f16bfe2e.png)

使い方はChromeにExtensionの追加後、Extensionのメニュー(SLのアイコンクリック)に並べたいチャンネルのURLをsubmitして、自分のslackのワークスペースに移動します。
※ submit後ページを更新しないと反映されません。

![slack02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86684/e72b29f3-9bd8-6beb-4fc1-218da7bd0aba.png)

すると、左にワークスペースが表示され右に登録したチャンネルが並びます。



# 何をやっているか

このExtensionで何をしているのかを開発した順番で解説します。

## 1. チャンネルを並べて表示する。

今回やりたかったのは、「画面が分割されSlackの複数のチャンネルを一画面で見ることができるようにする。」で、これを実現する方法として、iflameを並べてしまうことを考えました。

このタイミングのコードは残っていないのですが、処理としては、

1. slackのページの元のbodyのinnerHTMLを消す
2. 現在のURLを取得
3. chrome.storageに保存しているslack channelのURLリストを取得
4. 現在のURLとslack channelのURLリストをiflameで並べていく
5. cssでiflameの幅を調整

のような簡単なものです。ここまでで以下のようなものが出来上がりました。

![slack01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86684/8a145c49-bad0-1f1d-bdff-19fa8c4b0784.png)

これでもそこそこ便利だったのですが、右に並べた各チャンネルにサイドバーが表示されていて邪魔です。

## 2. サイドバーを消す

ということでサイドバーを消すことにしました。行うこととしては各iflame内でサイドバー関連のcssをいじって消していきます。
コード全体は[こちら](https://github.com/k8shiro/chrome_extension_slack_columns/blob/c3273781cd2cbae30991679c2f561960826d269b/src/content.js)でその中のiframeLoadedという関数をiflameがロードされたタイミングで実行されるようにしています。

```js
function iframeLoaded(lineId) {
    data1 = document.getElementById(lineId);
    data1.contentWindow.document.getElementsByClassName('p-classic_nav__team_header')[0].style.display = "none";
    data1.contentWindow.document.getElementsByClassName('p-workspace__sidebar')[0].style.display = "none";
    data1.contentWindow.document.getElementsByClassName('p-workspace--context-pane-collapsed')[0].style.gridTemplateColumns = "0px auto"
}
```

上記コードはlineIdがiflameのIDで不要なサイドバーを`display = "none"`にした後、コメントが流れるスレッド部分の表示位置を修正しています。ここまでで見た目は[作ったもの](#作ったもの)で紹介した状態と同じになります。

## 3. チャンネルを移動してもURLが変わらない問題

一番左側はサイドバーも表示するようにしていたのですが、元のbodyを消してすべてiflameに押し込んだ弊害で、チャンネルを切り替えてもchromeのアドレスバーのURLが切り替わらなくなってしまいました。

そこで一番左のみiflameを使わないようにしました。
コード全体は[こちら](https://github.com/k8shiro/chrome_extension_slack_columns/blob/b11273a390dcc3d2b1d3d750bec0e9aa02b4dd72/src/content.js)で以下のように、window.onloadのタイミングで、今まで元のbodyをすべて消していたのを止め、元のbodyの下にiflameを並べるようにしています。

```js
window.onload = function() {
    let originUrl = location.href ;
    let body = document.body;
    body.setAttribute("id", "origin")
    let newBody = document.createElement('body');
    newBody.appendChild(body)
    newBody.style.display = "flex"

    let wrapper = document.createElement('div');
    wrapper.setAttribute("id", "wrapper")
    newBody.appendChild(wrapper)

    document.documentElement.appendChild(newBody)

    chrome.storage.sync.get(
        {channels: []},
        function(channels) {
            for(let i = 0; i < channels['channels'].length; i++) {
                addLine('channel'+String(i), channels['channels'][i])
            }
        }
    );
};
```

上記処理では新しいbodyを生成し、元のbodyをその下に追加しているのでbodyの下にbodyがある状態になっています。はじめは元のbodyはdivに書き換えたりしてみたのですが、SlackがReactだからか?、原因はよくわからないのですが上手く動かなかったので試行錯誤の末このような形になっています。

## 4. その他

これ以降は、細かい修正で、iflame内のサイドバーの生成を待ってからcss書き換えを行ったり、iflameが一度に呼ばれないように若干ずらして読み込まれるようにしました。この記事の執筆時点でのコードは[こちら](https://github.com/k8shiro/chrome_extension_slack_columns/tree/0c84b7b74dbf122620798b93b4f6c0d4fa28cb5e)です。

また、ChromeのExtensionの公開が大変でした。どうやらExtensionのページの説明文や画像ををある程度しっかり書かないとスパムと判定され公開の審査に落ちるようです。

# まとめ

slackのチャンネルを並べて見れるようするChromeのExtension「Slack Columns」を作成したので、内部で何をしているのか紹介しました。このExtensionのコードは[こちら](https://github.com/k8shiro/chrome_extension_slack_columns)で公開しています。つくりとしてSlackの仕様変更に弱く、またバグ等もあると思うので見つけた方はプルリクください。