見出し画像

Chatworkをスリム化するChrome拡張機能「Slim Chatwork」をリリースしたので宣伝と小話を

どうも、フロントエンドエンジニアのHiga Tsubasaです。

名前の通り、Chatworkをスリム化するGoogle Chrome用拡張機能「Slim Chatwork」を作りましてリリースしたので折角ですし宣伝も兼ねましてちょっとだけ小話をと。

公式サイト:https://cofus.work/chrome-extensions/slim-chatwork/
拡張機能インストール:https://chrome.google.com/webstore/detail/slim-chatwork/hckmjlnhaeikfnmmfjniechjanhhfnjh

何が出来るの?

Chatworkの左側にあるルームリストのサイズをスリム化出来たり、フォントをGoogle fontsから選べたり、カラースキームを変更出来たり、定型文登録が出来たり、約物半角化が出来たり、シンタックスハイライトが使えたり...etc

結果的に色んな機能を実装しちゃいましたが、メインの機能は名前の「Slim Chatwork」の通りChatworkの左サイドに表示されるルームリスト内のグループチャットの表示サイズを自由に変更出来るスリム化機能です。

Chatworkユーザーあるあるでしょうが、グループチャットが多ければ多いほど、またそれらチャットの活性度が高ければ高いほどチャットの切り替えを頻繁に行う事になるわけですが、その切り替えの度にスクロールがしたくない。出来る限り一画面で多くのグループチャットを表示させたい!と思ったのが制作のキッカケです。

実はリリースまでに1年半も掛かったっていう...

元々上記の理由で個人的に早急にどうにかしたくて10分ぐらいでパパっと作っちゃって結構長い間使っていたのですが、実は一般化してリリースするまでには1年半も掛かってます。「多分便利だと思うからいつか一般化してリリースしよかねー」と思ったままいつの間にか時が過ぎまくったパターンですね。いつかやろうは馬鹿野郎とはよく言ったものです。

実際には設計から → デザイン → 実装 → テスト → 限定リリース → 一般リリース含めて約1週間半強で出来たので大して難しい事はしていないのですが、やる気が出て行動に移すまでに1年半も掛かってしまいました。

ちなみにやる気が起きたキッカケは退職までの有給消化期間がまぁまぁ長かったからというこれまたあるあるな理由。退職せず暇を持て余す時間がなければ多分一生一般化してなかったかもです笑

改めて即行動を意識しようと思った26歳の春を過ごしながら黙々と粛々と実装していきました。

手軽にポチポチ設定&リアルタイム反映がしたかったからポップアップUI設定にこだわってみた

やる気さえ出ちゃえばこっちのものでして、あとはどうやって作っていこうかなの問題です。実は過去にも見え〜るAltYouTube Fixeder(YouTubeの仕様変更で使えなくなってます)など、その他にも4つぐらいリリースした経験があったのでぼちぼちノウハウはありましたが、今回割と勉強にもなった&こだわってみた実装のポイントとしてポップアップUIからの設定&リアルタイム反映があります。

実際に設定をしている様子を見たほうがわかりやすいかもですので動画も載せておきます。もしよかったら再生してみてくださいませ。

動画の中でも登場しますが、スライダーを操作したりON・OFF操作を行っているUIがポップアップUIに当たります。

通常今回の様な特定の設定に基づき特定のサイトのDOM操作やスタイル操作を行う拡張機能を作るとなると、別途オプションページを用意してそこでポチポチ設定後、対象サイトをリロードして設定を反映させるという方式がよく使われたりします。実際にユーザーが行う操作の流れで言うとこんな感じ。

① 拡張機能のアイコンからオプションページへ移動する → ② オプションページでポチポチ設定 → ③ オプションページを閉じる → ④ タブ移動で対象のページを開く → ⑤ 対象ページをリロード(必要あれば)

まぁよくやる操作ですよね。比較的簡素な仕様にまとめやすいので多くの拡張機能がオプションページを持っていたりします。ちなみに設定の度に上記の様な操作が毎回発生しちゃうのがデメリットでもあります。

滅多に設定を弄る必要がない拡張機能でしたらオプションページを用いた方法でも問題ありません。

ただ今回作る拡張機能ではChatworkのルームリストのサイズを自由に変更できるのが目玉機能だったり、また一部機能においては機能のON・OFFのスイッチを気軽に出来る必要があったので、ある程度設定の保存と反映をリアルタイムに可能にする必要性がありました。

当然オプションページを用いる方法だと何度もオプションページを行き来するのでまぁキツイ。ということでポップアップUI設定方式を取ることに。

ポップアップUI設定の良い所はユーザーに操作させる回数を少なく出来る点です。対象ページにて拡張機能のアイコンをクリックし表示されたポップアップの中で設定を行い、設定データをStorageに保存するまでを行います。オプションページで行っていた事をポップアップUI内で行っちゃうわけですね。
あとはポップアップ内で動いているスクリプトからsendMessageでDOM操作やスタイル操作を行うためのコンテンツスクリプトと連携して、Storageのデータを取得&DOM操作やスタイル操作を行えばリアルタイムに設定を反映させる事が出来ます。

① 対象ページを開く → ② 拡張機能のアイコンをクリックしポップアップUIを開く → ③ ポチポチ設定すると反映される

変更した設定がリアルタイムに反映されるので心ゆくまでカスタマイズが出来る。今回実装するにおいて一番こだわったポイントでした。

その代り実装において気にしてあげる部分も

ちなみにリアルタイム性と利便性を一番にした代償として、Storageにデータをセット可能な回数の制限(chrome.storage APIで1分間に120回まで)を気にしてあげる必要性が出てきました。

120 MAX_WRITE_OPERATIONS_PER_MINUTE

Since Chrome 40.
The maximum number of set, remove, or clear operations that can be performed each minute. This is 2 per second, providing higher throughput than writes-per-hour over a shorter period of time.
Updates that would cause this limit to be exceeded fail immediately and set runtime.lastError.

Slim ChatworkではROOMLIST SIZEという機能でレンジスライダーを使用した部分がありますが、当然この部分もinputイベントでリアルタイムに設定が反映できる様にしています。

何も考えずにスライダーをビュンビュンしちゃうとあっと言う間に1分間に120回までの制限に引っかかるので、throttleで間引くことで対処したりしました。

またオプションページとは違い設定を一括保存する事も出来そうもなかったので(今思えばポップアップUIを閉じたタイミングで一括保存とか出来るかもねと思ったり。)、逐一Storageに値をセットしたり取得したりする必要も出てきました。
そのためあらゆる所でsetSyncStorageやgetSyncStorageが登場していますが、ここらへんは最初で以下の様に非同期仕様の関数を用意しておいたので割とシンプルに実装出来たり。

/**
 * Set chrome storage sync.
 * @description chrome.storage.sync.setを用いて値をstorageに保存します.
 * @param {Object} obj
 */
export const setSyncStorage = obj => {
  return new Promise(resolve => {
    chrome.storage.sync.set(obj, () => {

      let error = chrome.runtime.lastError;
      if (error) {
        // errorが発生した場合.
      }

      resolve();
    });
  });
};

// セットする例.
(async () => {
  await setSyncStorage({ key_name: value });
})();
/**
 * Get chrome storage sync.
 * @description chrome.storage.sync.getを用いて値をstorageから取得します.
 */
export const getSyncStorage = (key = null) => {
  return new Promise(resolve => {
    chrome.storage.sync.get(key, item => {
      key ? resolve(item[key]) : resolve(item);
    });
  });
};

// 取得する例.
(async () => {
  let all_value = await getSyncStorage();
  let key_value = await getSyncStorage('key_name');
})();

Chatworkの仕様上必要になった処理とか

あとChatwork側の仕様で必要になった処理としては、デプロイの度にDOMのクラス属性が変わるのでページ読み込みのタイミングでDOM解析し、Storageへクラス名を保存してあげたりしました。と言っても変わる箇所は決まっているので範囲は狭いです。

他にはシンタックスハイライトの有効化も機能の1つとして実装しましたが、チャットツールの性質上絶えず新しくコンテンツが流れて来るので都度処理が必要になってきます。ココらへんはMutationObserverでDOMの変化を監視して都度発火させるようにしました。ぶっちゃけますと初めて使ったのでこれまた勉強に。


シンタックスハイライト有効化の設定画面。まだテーマがgithubオンリーだったり実装自体も実験的な機能です。

ちょっと実装していて楽しかった部分としてはChatwork固有のクラスリストをまとめたymlを用意してJavaScriptと管理を別にした点です。カラースキームの変更機能も実装しましたが、そのカラーを適用させるクラス名のリストとして利用しました。


キーカラーを選ぶことでモノクロマティックスキームを自動で生成。キーカラーはピッカーで選ぶ事も可能。また完全に手動でHEX値を設定することも出来たり。

意外と数が多かったので切り分けることでメンテナンス性も高まりましたし、なによりymlの見やすさが最高で実装も楽しかったです。

あと作ってて色々学ぶことが

私普段は受託系のWebサイト制作にてフロントをいじいじしてるのでモダンな環境で実装する機会って意外と少なかったりします。
そんな中で折角プライベートな時間で自由に作れるわけなので流石に2019年にもなってJquery依存というのもアレですし、今回は思い切って全てES6仕様で組んでみることにしました。
別にJqueryが悪いわけじゃないのですけど、やっぱり使わずに実装出来るのと出来ないのとでは幅が変わってきますしね。実際やっぱり知らないことも沢山有りましたし良い機会になりました。

あとはデザイン。こればっかりは職域的に手を出してこなかった領域ですのでまぁ困りました。ですがやっぱり折角ですのでPhotoshop開いて一からデザインしていくことに。
とは言えぶっちゃけ何が正解か分からないのでポップアップUIだけで数日潰すとか余裕でありました。
未だに操作しやすいのか慣れちゃったのか分からずなので根本的に勉強しないとなと思う次第です。

ポップアップUI以外にも公式サイトのデザインにもチャレンジしてみました。日頃Web制作のフロントエンドやっているのでポップアップUIはまだしも、Webページなら簡単な形は出来るんじゃないかと思いましたがこれがまぁ進まない進まない笑。上手いこと形に落とし込めずで消化不良のオンパレードでした。

改めてデザイナーさん凄いなと思いましたし、あとディレクターさんの存在ってデカイんだなと。まず「構成どしよ汗」でフリーズしたレベルでしたのでフロントエンドと言えどもコーディング脳だけだと何も作れないんだなと、至極当然の事をこれまた必然的な形で恐怖を覚えました。

ろくに転職活動もせず有給消化期間をほぼSlim Chatwork制作に費やしてしまいましたけどw、まぁ浅々でしたが色んな意味で勉強になりまして良かったです。分からずともまずは手を出してみる。やっぱりこれが何よりの学びですよね。

というわけで

ぐだぐだ書いてたらもう文字数的に小話じゃなくなってきたのでここら辺で終わりたいと思います笑

というわけでChatworkをご利用の方は是非Slim Chatworkも一緒に使ってみてはいかがでしょうか!感想お待ちしております(@_cofusまで)


---
そうそう、note登録だけしてて全く活用してなかったのでこういう技術系以外の投稿先としてはいい場所ですね。Qiitaと迷った時はnoteに投稿しよっと。

この記事が気に入ったらサポートをしてみませんか?