📒

Tauri + React (Rust + TypeScript)で、Notionにお手軽にメモを取れるデスクトップアプリを作った

2023/01/14に公開

TL;DR

https://github.com/h1g0/daily-notion

  • Tauri + React (使用言語は Rust + TypeScript)でNotion用のデスクトップアプリを作ったよ
  • 起動するとすぐにメモできるよ
  • メモはNotion上の指定したデータベースに、日付ごとにページを分けて自動保存されるよ
  • マルチプラットフォーム(Windows, macOS, Linux)対応だよ

はじめに

Notionというメモアプリを便利に使っています。

しかし1つ不満があって、Notionって、メモを取り始めるまでに意外と手間がかかります。
メモを取る前に「目的のページを開く→子ページを新規作成する→テンプレートを選ぶ→タイトルを入力する」みたいな手順を踏まないといけなかったりします。

これでは、「今すぐどこかにメモを取りたい」という時には結構困ります。

一方で、Notionの競合アプリであるObsidianCraftには、「デイリーノート」 (Daily Notes)という機能があります。

これは、

  1. アプリを起動すると空白のページが自動的に作成され、そのページが開く
  2. そのページは今日の日付をタイトルとして、あらかじめ指定した場所に保存される
  3. ユーザはその「今日のページ」に即メモを取り始めることができる

というものです。

この「デイリーノート」機能がNotionにもあれば便利だと考えたので、Tauri + React (使用言語は Rust + TypeScript)でNotion用のデイリーノート機能に特化したデスクトップアプリを作りました。

コードはこちらのGitHubリポジトリに公開しています。

使い方

ソースコードからビルド

このアプリは一応GitHubリポジトリのReleaseページでインストーラを配布していますが、後述するコード署名の問題により、現状では自分でソースコードからビルドすることを推奨します。

環境構築

がインストールされていない場合、インストールします。

任意のディレクトリで

$ git clone git@github.com:h1g0/daily-notion.git

としてリポジトリをクローンし、

$ cd daily-notion
$ yarn

として各種モジュールをインストールします。

実行

$ yarn tauri dev

として、認証画面が出たらインストール成功です。

ビルド

$ yarn tauri build

で、./src-tauri/target/release以下に実行ファイルとインストーラが作成されます。

認証

認証画面

実行すると、最初にこのような認証画面が表示されます。
このアプリを使用するためには、「インテグレーショントークン」と「データベースID」の2つの値をNotionから入手する必要があります。

インテグレーショントークンの入手

こちらを参考に、下記の手順に従ってインテグレーションを作成します。

  1. https://www.notion.so/my-integrationsにアクセスする
  2. 「新しいインテグレーション」をクリック
  3. 適宜情報を入力
    1. 名前:任意(Daily Notionとかが分かりやすいかも)
    2. ロゴ:無しで可
    3. 関連ワークスペース:アプリを使いたいワークスペース
    4. 機能:下記の画像を参考に次のように選択
      • 「コンテンツを読み取る」「コンテンツを更新」「コンテンツを挿入」にチェックを入れる
      • 「コメントの読み取り」「コメントを挿入」にはチェックを入れない
      • 「ユーザ情報なし」を選択
  4. 「送信」をクリック

機能

次の画面で、インテグレーショントークンを入手できます。

トークン

トークンをコピーしたら、先ほどのアプリの認証画面に戻り、"Integration Token"(上の入力欄)にトークンをペーストしてください。

コネクトの追加とデータベースIDの入手

  1. Notionで、このアプリのメモを保存したいデータベースを作成し(もしくは開き)ます。
  2. Notionの画面の右上にある「…」ボタンをクリックし、メニューを表示します。
  3. 「コネクト」 > 「コネクトの追加」から、先ほど設定したインテグレーションを選択します。
  4. 「続行しますか?」に「はい」をクリックします。
  5. 「共有」>「リンクをコピー」(もしくはブラウザで開いたときのアドレスバー)から、そのデータベースのURLを取得します。
  6. https://www.notion.so/{ユーザー名}/{データベースID}?~となっているので、この中からデータベースIDのみコピーします。

データベースIDをコピーしたら、先ほどのアプリの認証画面に戻り、"Database ID"(下の入力欄)にトークンをペーストしてください。

2つの値が入力できたら、Authenticateボタンをクリックします。

メモを取る

メモ画面

認証に成功し、データのロードが完了すると、メモを取り始めることができます。
現状ではプレーンテキストのみに対応し、Markdownなどの装飾には対応していません。

Notionにリアルタイムで保存される

書いたメモは先ほど指定したデータベースに、YYYY-MM-DD(例:2023-01-14)のタイトルで自動的に保存されます。

右上のアイコンがローディングスピナー(グルグル)の時は保存/ロード中、緑のチェック☑アイコンになっていたら保存/ロードが完了しています。

上のGIF動画のようにNotionの画面を並べると、書いた文章が自動的に保存され、リアルタイムでNotionに反映されていることが分かります。

また、上のナビゲーションバーで

  • 「<」アイコンをクリックで前日のノートへの移動
  • 「🕓」アイコンをクリックで今日のノートへの移動
  • 「>」アイコンをクリックで翌日のノートへの移動
  • 日付文字列(=タイトル)をクリックで、任意の日付のノートへの移動

が可能になっています。

開発で苦労した点・良かった点・今後の展望

苦労した点

  • Notionが提供しているJavaScript/TypeScript用のSDKが、Tauriが提供しているHTTP通信ライブラリのfetchと相性が悪く、そのままでは使用できなかった。
    • そのため、SDKのコードを読みつつ、その中で相性が悪い部分のコードを自分で車輪の再発明する必要があった。
  • Notion APIで取得できるノートのデータは、非常に複雑で入り組んだ構造体になっている。プレーンテキスト1つ読み書きするだけでも、その構造体の奥深くまで取りに行かないといけないので大変だった。
    • そのため現状では、ノートの最初のパラグラフに全てのテキストを入れる仕様にしている。
    • Notion側でMarkdownのような平易な形式で出し入れするAPIを用意してくれれば楽なのに……。
  • BlueprintのTextAreaコンポーネントが、なかなか思った通りのheightにならない。
  • 現状では雑にstyle={{ height: "100%" }}を指定している。
  • でもこれだと、ナビゲーションバーの高さだけ画面からはみ出してしまっているのでどうにかしたい。

良かった点

  • Notionをサーバサイドとして使うことで、フロントエンドの開発に集中できた
    • 自分でサーバサイドまで書くのは大変なので、それをNotionに丸投げして自分の欲しいアプリケーションが作れたのは良かった。
  • Notion APIが(比較的)分かりやすかった
  • Notion APIアクセス頻度制限が太っ腹だった
    • 世の中の大抵のAPIには「アクセスは1時間あたりn回までにしてくださいね」みたいな回数制限・頻度制限がある。
    • Notionの場合、公式のリファレンスに「平均して3回/秒ならいいよ[1]」と、かなり太っ腹な制限がかけられている。
    • そのため、ほぼリアルタイム[2]でのNotionへの通信・保存が可能になっている。
  • Blueprintを使用することで、とてもお手軽にUIを構築できた
  • 実際に手を動かすことで、Reactをより深く学ぶことができた

今後の展望

このアプリは「自分が使えればいい」ぐらいのスタンスで開発したので、まだまだ「一応使える」レベルの状態です。
できれば今後実装していきたい箇所が沢山あります。以下にいくつか例を挙げます。

コード署名の問題

このアプリはGitHub ActionsでCI/CDを整備し、クリック1回でビルドとReleaseページへのインストーラのデプロイが可能になっています。

しかし、それらのインストーラはコード署名がされておらず、macOSではデフォルト設定の場合、インストーラの実行を阻止されてしまいます。また、Windowsでも同様に「本当にインストールして良いの?」的な警告が出てしまいます。

コード署名用の証明書の取得には(特に趣味のOSS開発者にとっては)決して安くない金額がかかるので、どうしようか悩みどころです。

アップデータの実装

現状ではアップデータがないので、バージョンアップされたら再度手動でインストールしないといけません。

モダンなアプリケーションはセルフアップデータがあるのが普通だと思いますし、Tauriにもアップデータ機能が用意されているので、それを利用して実装したいですね。

アイコンをオリジナルなものにする

現状ではTauriのデフォルトアイコンのままなので、それもどうにかしたいですね。

Public Integrationにする

現状のNotionには、Internal IntegrationPublic Integrationの2種類のインテグレーションがあります。

前者はワークスペース毎に作成しないといけないもので、後者は一度作成すれば、誰でも使えるようになるものです。

このアプリの性格的には後者が望ましいのですが、後者として実装するために必須なRedirect URIでの認証の受け取り方が現状のTauriでは不可能?らしく、前者のInternal Integrationとしてあります。

ハンバーガーメニューの実装

メニューを実装しようと思って、左上にハンバーガーメニュー用のボタン[三]を付けてあるのですが、現状では何の機能もない飾りになっています。
ここにも何か実装したいですね。

おわりに

このアプリを作ったおかげで、今年の正月休みを充実したものにすることができました[3]

もし使ってみていただけた方がいらっしゃいましたら、感想やバグ報告等頂けると嬉しいです。

また、今後の展望にも書いたとおり、現状では足りない箇所がたくさんあるので、もしよろしければコードコミット等でコントリビュートして下さる方も大歓迎です。

脚注
  1. 原文: "The rate limit for incoming requests per integration is an average of three requests per second. Some bursts beyond the average rate are allowed." ↩︎

  2. 厳密には、最後に文字入力されてから500ms経過したら保存処理をおこなっている ↩︎

  3. 厳密にはしばらく前に少し作って放置していたのを正月休みに形にした。 ↩︎

GitHubで編集を提案

Discussion