Quip Live Apps - resolver YouTube Embedded を作りました

CTOの齋藤です。

弊社では、日々の業務のほとんど全てといって良いほど多くの領域で、コラボレーションツールとして Quip を活用しています。 副代表として先日JOINした呉縞が Quip エヴァンジェリストとして組織全体のコラボレーションの活性化、営業組織の仕組み化、人材育成などに関わってきたこと、またツールとしても圧倒的な使い勝手の良さなどもあり、かけがえのないツールといって差し支えない存在となっています。

以前 Advent Calendar で外からみた Quip の紹介をしてきました。

Quipもっと使われるには

今回は、 QuipでYouTube動画をさくっと共有できたら便利なのに…という呉縞さんのオーダーで、三連休DIYでQuip Live App を作ってみたので、その紹介をしていきたいと思います。

目次

Quip Live Apps とは

Quip の Live App のご紹介

sc_ 2021-09-21 15.01.10.png
sc_ 2021-09-21 15.02.15.png

Quip Live Apps とは、Quip ドキュメント上の好きな位置に より強力なコミュニケーションをできるようにするためのカスタムアドオンのようなアプリ群のことです。Quipをご利用の皆さんは、プロジェクトトラッカーやカンバン、Salesforceレコード連携など、公式謹製の Live App を活用しているケースも少なくないかと思います。

この Live App 自体はサードパーティ開発者でも簡易に開発、公開できるようになっており、特に React を使って構築できるのが特徴です。今回この記事を書いた背景の一つには開発の容易さ=Live Appが増えてQuipでのコミュニケーションがもっと楽になるのでは、と考えた点があります。

今回弊社では YouTube をドキュメントに埋め込んで共有する仕組みがほしい、というところから 実際にアプリを作ってみたので、その紹介をしていきたいと思います。

resolver YouTube Embedded - この Quip アプリの概要

resolver YouTube Embedded は、Quip上の好きな場所にYouTubeの動画を埋め込むことができる Quip Live App です。

Quipドキュメント上で動画を共有して、勉強会やセミナーのメモ共有に使ったり、動画の位置指定を使って動画のセクションごとにQuip上でコラボレーションをするのに役立ちます。

投稿時点で Dreamforce 2021 もあったので、Salesforce開発をされている皆さんもQuipに興味を持たれる方もいらっしゃるかなと思い、Twitterでも少しご紹介させていただきました。

sc_ 2021-09-22 18.18.54.png

こんな感じで、Quipのドキュメント上でアットマークメンションから [resolver YouTube Embedded] を呼び出してもらって(インストールした組織で、 re と打てばインクリメンタルサーチですぐ出てくるはず!)、あとはURLを貼り付けて開始秒数などを input エリアで微調整してもらうと、他のドキュメントユーザがQuip上で動画を参照することができるようになります。

resolver YouTube Embedded の特徴

  • 開始位置の指定を含め、任意の動画を任意の開始位置でQuipドキュメントに埋め込んで共有することができる
  • (言うまでもなくLiveAppは)1ドキュメント上に複数埋め込めるので、動画のセクションごとに埋め込んでそれぞれの解説やコメントでのコミュニケーションをしたりできる

共有の仕掛け - 見に行ってみてねにはしたくない

YouTubeを別のサイトに埋め込む時って 動画のページに行って「共有」ボタンを押して、埋め込み用の iframeタグをコピーして……

といったステップを踏まなくてはならず、意外と手間がかかります。

Notion でも GoogleDocs でも Slack でも Quip でも同様なのですが、リンクだけが沢山載ったドキュメントってストレスかかりませんか?

「よく集約されたまとめ」を作るのは良いのですが、「詳しくはそれぞれのリンクを開いてね」というドキュメントがあったとして、読む側全員にそれを強いるのはしんどいと思うわけです。

Quip で目指すコミュニケーションは、非同期でJOINしてきたメンバーとの情報格差をなくし、その場でコラボレーションをすることで仕事の生産性を一気に高めることだと思っています。参加者に十分な時間があったり、最初からそれはそれ目的であるならば確かに価値のある場面はあろうとも、ただリンクの貼られた文献リンク集では少なくともありません。

共有したい動画のURLをコピーしてこの Live App を好きなQuipドキュメント上で呼び出してもらえれば、わざわざリンク先のページに飛ばなくても動画を再生できます。

⭐ちなみに、ドキュメントを全体公開にした場合は、もちろん誰でもこのAppで動画が見られるようになります!

resolver Youtube Embedded demo/sample

ついでに、動画開始位置のパラメータも保持できるようにしておきました。ビジネス系だと共有したい動画が20-30分の長さのものが多いと思うし、セミナーとかだと1時間以上の長尺になることもありますね。Quip Live Apps は依存している技術要素が React ということもあり、Quipドキュメント上で固定したい秒数をその場で気軽に変更→再描画、という微調整ができるようになっています。

開発メモ・そもそも Live Apps の作り方

ドキュメントが充実しており、 Get Started のところに沿って進めていくと、思ったよりも簡単にアプリが作れちゃいます!

手順どおりにすすめていくと、 Weather Live App という、指定した都市の天気を表示してくれる Live App を作ることができます。これを参考にして、ご自身のアプリを作っていくとイメージがつくと思います。

sc_ 2021-09-20 20.36.24.png

ただ、 Weather Live App のサンプルはあくまでその場で指定された都市の天気情報を取得して再描画してくれるのみで、たとえば入力した都市名をリロード後や別のタイミングに覚えてくれるようにはなっていません。

今回のようにあるQuipユーザAさんが指定したYouTubeのURLをドキュメント上に永続化して、BさんもそのURLの動画を観られるようにするには、quip の RootRecord に対して値のsetをしてあげる必要があります。そうすると Quip API で言うところの edit-document が呼び出され、以後その値は RootRecord へのgetを介して呼び出すことができるようになります。

RootRecord は Quipのデータの保存単位である Record を最上位で管理するオブジェクトです。👇の図は引用リンクにあるQuipブログで解説されているもので、 Poll(投票)アプリのデータ構造がとてもわかりやすく説明されています。

https://d2i1pl9gz4hwa7.cloudfront.net/h4WD1yujL4UZaUaTkdwrdA

なぜツリー状なのかというと、

Quip blog - Embedding third-party React apps in Quip for fun and profit – Part 2

In particular, we decided to make storing data in Quip conceptually similar to putting data into a nested JSON object.

*弊方訳**

(直感的にするため、)とりわけ、Quipへのデータの永続化は、ネストされたJSONオブジェクトにデータを更新するイメージに近しくすることにした

******

とのことです。RootRecordがあり、ツリー状にデータ構造をぶら下げていくイメージはたしかに直感的ですね。長くドキュメントを更新していくと読み込みが重いドキュメントも増えてきますが、このあたりに原因というか重くしないためのヒントがありそうです。

アプリはReactで作っていきます。qla init でアプリを最初に作成する時にTypeScriptを指定できますが、TypeScriptを使わずJavaScriptで開発することも可能です。Reactはpropとstateの理解がキモで、型があった方が個人的にはそのあたりも後で楽になると思うので、どちらかといえば デフォルトである TypeScript で統一しておけば良いかなと思います。

開発の前提として、Nodeのインストールと、Quip をコマンドラインで動かすための パッケージのインストール、それと CLI を使うにあたって Quipのアカウント(qla login で認証する必要がある)が必要になります。

開発全般のタスクはコーディングを除けばnpmとquip-cli (qla command)で完結するようになっています。

流れとしてはこんな感じです。

  • qla init または、既存コードをソースリポジトリから pull
  • npm run build / npm start
  • アプリを任意のドキュメントに埋め込んでローカルデバッグ
  • qla bump でバージョンをインクリメント
  • (任意)ソースリポジトリへpush / 適宜CI/CD
  • qla publish でローカルからQuipコンソール側へ最新版を反映
  • コンソール、または qla release でベータリリースしてベータユーザ(コンソールで招待したユーザ)と一緒にテスト
  • コンソール、または qla release で本番リリースを行う
  • (任意)ソースリポジトリにタグ打ち

手順にあるベータ/本番リリースについてはコンソール上でもできますが、GUIでの繰り返しはやはり楽ではないので、上記の一連の流れをCLIベースで完結させるのが良いと思います。

qla init => npm start => npm run build => qla bump => qla publish => qla release

です。任意の欄で記載しましたが、 Github Actions の Webpack テンプレートなどで main push → ベータ作成、main pr マージで 本番リリース、って感じにすればほぼほぼ自動化できるんじゃないでしょうか。

Live App 開発で良いと思ったところ

React TypeScript で開発ができる

Quip Live Apps の開発は React ベースで行います。前述の通り、TypeScript にするかどうかは、プロジェクトをinit するときに選ぶことができます。特にネガティブな感情がなければ、デフォルトのまま(TypeScript 版を選択)をおすすめします。 React + TypeScript だと、比較対象に並べる是非はあるとして Aura や LWC に比べても全体での利用者自体がおそらく多く、(その分情報の取捨選択は重要ですが)調べながらの実装が楽になるかと思います。

sc_ 2021-09-20 20.50.35.png

Quipドキュメント上で localhost としてアプリをローカルデバッグできる

ローカルモードをOnにすると、npm start している間の変更内容をすぐに任意のQuipドキュメント上で確認することができます。(ホットリロードではなく、ローカルモードになっている Live App に対して手動での再読み込みは必要ですが)

このローカルモード、個人的にはキラーユースケースだと思ってます。好きなドキュメントに埋め込んで localhostでデバッグできるんです。

何が良いってそのまま問題なければ build したものを qla release でベータにしてローカルモード解除すれば、

埋め込んだドキュメント上でベータを確認できます。ローカル開発して同じドキュメント上でそのままベータユーザに追加した社内メンバーからコメントもらえるんですよね。

開発が一段落したときに、ビジネスユーザにGithubのIssues/PRを見に来てもらったり、BTSかカンバンツールで連絡入れたり、といったパイプラインが要らなくて、コミュニケーションがQuip上で完結する。これめちゃくちゃ便利じゃないですか? もちろんGithub→Slackでも良いけどやっぱりツールが分かれちゃうわけで。

リンクURLだけ書いてるのどうなんって話と同じで、受け手の負担を生じさせないのが大事。

Live App 開発で詰まったところ

CSP(Content-Security-Policy)の設定

木村さんが qiita で書かれていたように、CSP(Content-Security-Policy)については僕も手惑いました。

ああそうか、と言われたらそうなのですが、npm側は問題なくても ブラウザでエラーを見てmanifest.jsonへのallow設定をする必要があるに思い至るまでには少々手こずります。csp_sourcesディレクティブで正しくコンテンツタイプと対応するURLを指定することでCSPヘッダが生成され外部リクエストが可能になります。

* 貼ったURLのプレビューができるQuip Live Appを作りました 

React / TypeScript の形式知・共有ナレッジづくり

アプリ公開までのとっつきやすさ、ベースラインは非常に低く設計されていると感じる一方、React や TypeScript を使うからにはナレッジベースを組織やチームで蓄積していかねば、という危機感もありました。日々パワポとにらめっこしていたり、なまじSalesforce bundled な技術要素に時間を割いている中で、フック化を検討したりTypeScript周りのCIを考え出すとボリュームとしてはそこそこヘビーになってきます。えいやで作ったところをうまく並行開発できるようにナレッジ化のバランスを考えながら組んでいくのがポイントです。Reactコンポーネント単位でAppExにカタログ化できれば早いのですが。

これから拡張していく機能

色々書いてきましたが最小限の開発しかしてないので、少しずつ Issues に貯めておいて機能拡張していきたいと思います。このあたりを今後追加する機能で考えてます:

タイトルなど Data API からメタ情報の取得

YouTubeの動画に関する情報はYoutube Data APIを介して取得することができます。YouTubeはスクレイピングすることは規約で禁じられています。一方で、API利用はリクエストの従量制限(クォータ)が発生するので緩和含めたキャパシティ設計を一般公開時にどうするか、Issuesの他のNice to haveと見比べて検討していく予定です。

YouTube Data API の概要

Github Actionsからベータリリースの自動化

弊社は製品開発においてはソースリポジトリにGithubを利用しているので、身軽さとコンテキストスイッチ削減のためにも基本的にActionsで自動化をしていこうかなと思っています。VSCodeが結構巻き取ってくれるものの、UnitTest、Lint、リファクタなどなど横展開していくために、ツール自体を統合したいというのもありますし。モバイル特化なら Bitrise も候補なのですが、意外とデスクトップやブラウザもあるしCI/CDツールの選定は難しいところです。逆に、 Actions のデバッグ自体がもうちょっとやりやすくなればなと思ってます。Codespacesには期待しています。

モバイル完全対応

Quipを出先や家事の合間に見るってケースも多いと思います。たとえばマネージャの方だと、在宅でもオンラインMTG含めてモバイルだけで済ませたりすることもあったりするようで(Macを開けて製作作業する日とMTG参加と様子見だけで済む日を分けている、という働き方をしているような方のケース)、そういう方・状況にとってはモバイルアプリでどれだけ仕事を完結できるかが重要ですね。

 にあるように isMobile() 判定子が使えます。

具体的には isMobile() では、ネイティブモバイルからのアクセスを判断することができます。

Client Environment | Live Apps for Quip

  • quip.apps.isMobile : Quip のモバイルアプリからのアクセス時にTrue
  • quip.apps.isNative : Quip のデスクトップアプリまたはモバイルアプリからのアクセス時にTrue
  • quip.apps.isDesktopWeb :Quip のデスクトップウェブブラウザからのアクセス時にTrue
  • quip.apps.isIos : iOS のモバイルアプリからのアクセス時にTrue
  • quip.apps.isAndroid: Android のモバイルアプリからのアクセス時にTrue
  • quip.apps.isWindows: Windows のデスクトップアプリからのアクセス時にTrue
  • quip.apps.isMac: macOS のデスクトップアプリからのアクセス時にTrue
sc_ 2021-09-20 23.53.42.png

IAB、ブラウザ、Salesforceのレコードページへの埋め込み、ネイティブアプリなどの環境に応じた Graceful Degradation への留意が必要です。このアプリも、現状では、モバイルアクセスの場合は YouTube へのリンクを表示するのみとし、YouTubeアプリへのインテントを期待していますが、Quipドキュメントは移動中や会議の間などのスキマ時間でも見られるのが好ましいと考えるため、やはり優先的にモバイルへの完全対応をしたいと考えています。

終わりに

いろいろ書いてきたのですが、今後 AppExchange での全体公開など、Salesforceエコシステムの中でも使っていただけるよう、また、QuipのLive Appがとても開発しやすいということをより広く知っていただければと思ってます。まだまだ色々な施策、企画、製品を世に出していきたいと思いますので、今後ともご愛顧のほどよろしくお願いいたします。

Share

お問い合わせContact

弊社へのご相談、取材、その他お問い合わせはこちら