ショートカットキーが身につくアプリ Shortype の version 1.0.0 をリリースしました

はじめに

こんにちは、えにしテック佐藤大介(AudioStakes)です。

現在参加しているフィヨルドブートキャンプの自作サービス課題として「ショートカットキーが身につくアプリ Shortype」の version 1.0.0 をリリースしました。

Shortype は「キーボードから手を離さず作業できるようになりたい」というモチベーションで開発してきました。

3週間前にプロトタイプをリリースしており、その作成過程は ショートカットキーが身につくアプリ「Shortype」のプロトタイプをリリースしました に記載しています。

この記事では、プロトタイプから磨きをかけてきた Shortype の特徴を紹介します。

Shortype とは

Shortype は、クイズに答えるだけで自然とショートカットキーが身につく Web サービスです。

f:id:AudioStakes:20220331154932g:plain
Shortype のデモ動画
※右下の黒いオーバーレイに実際にタイプしたキーを表示

動作環境として、ブラウザは Google Chrome もしくは Microsoft Edge、OS は macOS に対応しています。

shortype.vercel.app

操作はショートカットキーをタイプするだけ

出題内容にあったショートカットキーをタイプする(入力する)だけで、問題が次々に進んでいきます。正解したときはそのまま次の問題へ進み、不正解だったときは画面に表示された正解を入力します。

この繰り返しにより、自然とショートカットキーが身につく仕組みとなっています。

このシンプルな操作「Shortcut key を type する」はサービス名 Shortype にも反映しています。

公式ドキュメントのショートカットキーを完全網羅

練習できるツールは「Google Chrome」と「macOS の Terminal」の2つがあります。どちらも公式ドキュメントに掲載されているショートカットキーをすべて出題しています。

ツールの選択は「T キーを押す」もしくは「『ツールを選ぶ』ボタン」から行えます。

f:id:AudioStakes:20220331155411p:plain

※ 正解判定できないショートカットキーは「自己採点」という形で出題しています。

身についていないショートカットキーの出題頻度が自動的に高まる

回答するたびに正解判定の結果がブラウザに保存され、その正答率をもとに「身についたかどうか」がショートカットキー単位で判定されます。全体としてどれくらい身についているか、円グラフと表で確認できます。

f:id:AudioStakes:20220331155449p:plain
現在の身についた度合いを示す円グラフと表

右の表は、円グラフをマウスでホバーすると表示されます。

「身についたかどうか」は、出題頻度の調整にも使われます。身についていないショートカットキーは出題頻度が自動的に高まります。

この仕組みにより、手間をかけることなく、苦手なショートカットキーを重点的に練習できるようになります。

※ 出題頻度の調整は、未回答のショートカットキーがなくなった後に開始されます。それまで、未回答のショートカットキーが最優先で出題されます。
※ 正解判定の結果はブラウザの localStorage に保存されます。

身につけたいショートカットキーに絞って練習できる

公式ドキュメントのショートカットキーの中には「すでに覚えている」「興味がない」といったものも含まれているかもしれません。

そのようなショートカットキーに対し、R キーを押して「次から出題しない」と設定できます。

f:id:AudioStakes:20220331155540g:plain
「次から出題しない」と設定したとき

これにより、身につけたいショートカットキーに絞って練習できるようになります。

「キーボードから手を離さず作業できるようになりたい」という方々に使ってほしい

Shortype は「キーボードから手を離さず作業できるようになりたい」というモチベーションで作り始めました。

僕自身が Shortype を使ってみた結果、たしかに「ショートカットキーが身についた」という実感があります。以前より、キーボードから手を離さず作業できるようになりました。

同じようなモチベーションを持つ方々に、使ってもらえたら嬉しいです。

これからやりたいこと

Shortype の開発は version 1.0.0 のリリースを1つの区切りとしています。しかし、より多くの方々に Shortype を使ってもらえるように、時間を見つけて改善していきたいと考えています。

今のところ、次のような改善案があります。

練習できるツールを増やしたい

VS CodemacOS のショートカットキーなど、個人的に普段の開発作業で扱うツールも練習できるようにしたいと考えています。

「出題しない」としたショートカットキーを個別に戻せるようにしたい

現状は、「出題しないリストを空にする」という機能で「出題しない」としたショートカットキーを一括で戻すことができます。

「個別に戻したい」というケースもあると思うため、対応したいと考えています。

最後に

Shortype の開発にあたり、毎日の朝会で進捗内容1つ1つに親身なフィードバックをくださった @darashi さんと @snoozer05 さん、丁寧なデザインレビューでアプリの見た目を見違えるほど良くしていただいた @machida さん、データ設計やコードレビューでとても勉強になる改善案を教えていただいた @yoshitsugu さん、進捗報告会や日報・Discord 等でコメント・リアクションしていただいたみなさま、本当にありがとうございます。

自作サービス開発にチャレンジしたことで、とてもたのしく、学びのある日々を過ごせました。

Shortype を使ってみて何か気づいたことがある方は、 GitHub の Issue  や Twitter にご連絡いただけますと、励みになります。

ショートカットキーが身につくアプリ「Shortype」のプロトタイプをリリースしました

はじめに

はじめまして、えにしテックの AudioStakes(佐藤大介)と申します。

現在フィヨルドブートキャンプに参加しており、その課題としてタイトルのとおりのアプリ Shortype を自作しています。

普段の作業でついマウスに手を伸ばしがちなので、「キーボードから手を離さず作業できるようになりたい」というモチベーションから Shortype を作ろうと考えました。

この記事では、はじめに Shortype のプロトタイプを紹介し、その後に「技術的な詳細」「これまでやってきたこと」「これからやること」を説明します。

2022/04/01追記: プロトタイプに磨きをかけた version 1.0.0 のリリース記事を公開しました。

audiostakes.hatenablog.com

Shortype のプロトタイプ

f:id:AudioStakes:20220308113605g:plain
Shortype のプロトタイプのデモ動画

shortype.vercel.app

macOSGoogle Chrome のショートカットキーを練習できます。

操作はショートカットキーを入力するだけです。

※ 右下の黒いオーバーレイに実際にタイプしたキーが表示されています(keycastr を使用)。

※ 現在開発中のため、アプリの内容は今後変更されます。

動作環境

解決したいことは「ショートカットキーが身につかない」問題

これまで、自分が使うツールのショートカットキーを調べて「これは便利なショートカットキー!」と思うことは多々あったものの、それらを身につける前に忘れてしまい、結局マウスで操作するということを繰り返してきました。

このようなことを課題に感じており、ショートカットキーが身につくまで練習できるアプリがあれば解決できるのでは?と考え、Shortype を作り始めました。

実際に試してみて、Chrome のショートカットキーに関しては8割ほど覚えることができたので、プロトタイプとしては期待どおりの成果が得られていると思います。

実装に関する簡単な説明

使っている技術

  • Vite v2.8.6
  • Vue v3.2.31
  • TypeScript v4.6.2
  • Tailwind CSS v3.0.23
  • Vercel (デプロイ先)

どれも今回初めて使っています。Vue 2 を使って「メモを CRUD できるアプリ」を作成したことがあるので、その経験を基にわからないことは調べながら実装を進めています。

感想としては、開発体験がとても良く、チャレンジしてみて良かったと思っています。

実装した処理の流れ

  1. ショートカットキーを出題
  2. 押されたキーを判別し、画面に表示 & 正解かどうか判定
  3. 正解判定の結果を表示
    • 正解のときは ✅ を表示
    • 不正解のときは正解を表示
  4. 正解のキーが押されたら、次のショートカットキーを出題

特に苦労した実装は「押されたキーの判別」

概要

押されたキーの判別は「キーを画面に表示するため」と「正解かどうか判定するため」に必要です。

キーの判別を JavaScript で行うためには KeyboardEvent (キーボードによるユーザーの操作を示すイベント)を使うとよさそう、と考えていました。

しかし、KeyboardEvent のプロパティの値は「押されている修飾キー(command, shift など)の状態」や「クライアントのキーボードレイアウト」によって異なり、うまく判別できないことがあります。

試行錯誤した結果、KeyboardEventKeyboard API を組み合わせることにしました。現在は期待どおりにキーを判別できるようになっていると思います。

KeyboardEvent のみでは判別できないことがある

はじめは前述のとおり、押されたキーの判別に KeyboardEvent のプロパティの値のみを使おうと考えました。

検討したプロパティは、key , code, keyCode, which の4つです。

それぞれ次の理由により、使用に適していないと判断しました。

KeyboardEvent.key

修飾キーの状態によって、返り値が次のように変化する。

  • (修飾なし) a → a
  • shift + a → A
  • option + a → å
  • shift + option + a → Å

KeyboardEvent.code

クライアントのキーボードレイアウトによって、返り値が異なる。

たとえば code の返り値がKeyQ のとき、次のようになる。

  • QWERTY キーボード → Q キーが押されたことを示す
  • Dvorak キーボード → ' キーが押されたことを示す
  • AZERTY キーボード → A キーが押されたことを示す

KeyboardEvent.keyCode, KeyboardEvent.which

修飾キーの状態やキーボードのレイアウトの影響を受けないように見えるものの、現在は Deprecated (非推奨)とされている。

※ なお、JavaScript で実装された「ショートカットキーを追加できるライブラリ Mousetrap」では、keyCodewhichを使って押されたキーを判別しているようでした。

Keyboard API を組み合わせると期待どおり判別できた

他の方法を調べているうちに Keyboard API にたどり着き、説明を読んでいると使えそうな気がしてきました。

以下は、MDN の Keyboard API のページで紹介されているサンプルコードです。

if (navigator.keyboard) {
  var keyboard = navigator.keyboard;
  keyboard.getLayoutMap()
  .then(keyboardLayoutMap => {
    var upKey = keyboardLayoutMap.get('KeyW');
    window.alert('Press ' + upKey + ' to move up.');
  });
} else {
  // Do something else.
}

このコードでは、クライアントのキーボードレイアウトに対応する KeyboardLayoutMap を取得し、その get メソッドに KeyW (すなわち KeyboardEvent.code の値)を渡すことで、 KeyW に対応する KeyboardEvent.key の値を取得しています。

これを利用し、次のようなコードを実行すると「修飾キーの状態」や「キーボードレイアウト」の影響を受けずに押されたキーの値を取得できるようになります。

document.addEventListener('keydown', (keyboardEvent) => {
  navigator.keyboard.getLayoutMap()
    .then(keyboardLayoutMap => {
      const pressedKey = keyboardLayoutMap.get(keyboardEvent.code)
      console.log(pressedKey)
    })
})

この方法を試してみた結果、押されているキーを期待どおりに判別できるようになりました。

Keyboard API は2022/03/07現在 Experimental (実験的)という定義の、比較的新しい技術のようです。サポートしているブラウザは少ないものの、使い心地はとても良いです。

※ 上記のコードを試す際は、Keyboard API をサポートしているブラウザ Google Chrome, Microsoft Edge, Opera のいずれかをご使用ください。

KeyboardLayoutMap.get()undefined を返す場合もあります。その対応方法は割愛します。

プロトタイプでリリースした理由

フィヨルドブートキャンプでは、自作サービスの課題として「どんなサービスを作るかを考える」ところから「Web サービスをリリースする」ところまで取り組みます。

その作業期間は決められていないものの、諸々の都合により約8週間と決めて取り組むことにしました。しかし、リリースまでの作業には未経験のものも多く、作業全体の見通しを立てることができていませんでした。

そのため、先にリリースまで行って提出可能な状態を作り、期限の心配から解放された状態でプロダクトを磨いていこうと考えました。

※ この考え方は、WEB+DB PRESS Vol.73 の特集「たのしい開発実況中継~追体験して見つける日々の開発へのヒント~」から得た受け売りです。

gihyo.jp

もし順番どおりに作業を進めていたら、リリース関連作業でトラブルが生じ、提出に間に合わなくなっていたかもしれません。

たとえば、自作サービスの提出要件に「リリースブログの記事の作成」が含まれているものの、ブログ記事を書いて公開した経験はありませんでした。そのため、その素振りとしてこの記事を書いて公開することに決めました。

実際やってみて、この記事の作成に3日間以上かかっており(プロトタイプの機能の実装期間が6日間だったことを踏まえると、かなり時間がかかっています)、文章を見直す際も数日経ってから見直した方が修正箇所に気づきやすいということがわかったので、最後にリリース記事を書くときは余裕を持って作成し始めようと思いました。

これまでやってきたこと

全体の作業期間8週間のうち、この記事の公開までの約5週間で次のようなものを作成してきました。

インセプションデッキ

インセプションデッキとは、「どのようなプロダクトを、なぜ、どのように作ろうとしているのか」を手軽に伝えられるようにするためのツールです。詳しくは、アジャイルサムライの第II部「アジャイルな方向づけ」をご確認ください。

shop.ohmsha.co.jp

今回は、次のようなものを作成していきました。

  • エレベーターピッチ
  • パッケージデザイン
  • やらないことリスト
  • 夜も眠れない問題
  • 期間を見極める
  • 何を諦めるのか

これらの作成を経て、自作するプロダクトの解像度を高めることができました。

ペーパープロトタイプ

ペーパープロトタイプは、プロダクトに必要なページを紙に書き出したものです。 Figma を使って作成しました。

最初のペーパープロトタイプは、インセプションデッキのうち「エレベーターピッチ」のみを作った状態で、次のようなものを作成しました。

f:id:AudioStakes:20220308114230p:plain
はじめに作成したペーパープロトタイプ

他の方からのフィードバックや、インセプションデッキを作り進めていく中で、このペーパープロトタイプには余計な画面や機能が多いことに気づきました。

そのため余計なものを取り除き、次のように作り直しました。

f:id:AudioStakes:20220308114309p:plain
作り直した後のペーパープロトタイプ

プロダクトの価値をユーザーへ届けやすくなったように思います。

作業計画

「プロトタイプでリリースした理由」の項目で紹介しました「WEB+DB PRESS Vol.73 の特集『たのしい開発実況中継~追体験して見つける日々の開発へのヒント~』」を参考にして計画を立てました。

早い段階から提出可能な状態を作ることを念頭に置いた計画にしています。

f:id:AudioStakes:20220308114338p:plain
プロトタイプ作成以降の計画

もし上記の記事を読んでいなかったら、3月末は泣く泣く機能を削りながら提出に間に合わせていたと思います。

「期限のある方」や「期限はないけれど短期間で満足できるものを作りたい方」には一読をオススメします。

カンバン

GitHub のプロジェクトボードを作成し、タスクを Issue として追加しました。

Issue はアジャイルサムライのユーザストーリーを参考に「<達成したいゴール>をしたい。なぜなら<理由>だからだ。」という形式で作成しました。

プロトタイプ

前述のとおりです。

リリースするために必要な未経験の作業

リリースに必要な作業にはロゴの作成や OGP の設定など、未経験な作業が多く含まれていました。それらの作業にどれくらい時間がかかるか予想もつかなかったため、2日間というタイムボックスを切って取り組みました。

プロトタイプのデザインの改善

「未経験の作業」と同様、作業時間の予想がつかなかったため、1日というタイムボックスを切ってできる範囲で改善してみました。

デプロイ

社内で相談してみた結果、Vercel が手軽ということがわかったため Vercel を使ってデプロイしました。実際やってみるとアカウント登録とリポジトリの設定のみでデプロイされ、本当に手軽でした。

プロトタイプのリリースブログの作成

この記事を作成しました。

解決したいことは解決できた?

Shortype で解決したいことは「ショートカットキーが身につかない」という問題でした。

僕自身が(動作確認としてですが)試してみた結果、今では8割ほど正解できるようになりました。

少なくとも Chrome に関しては目論見どおりの成果が得られ、解決できそうです。

ただ、現在の Shortype には課題がまだあるように思います。たとえば次のような課題です。今後これらに取り組んでいきたいと思います。

Google Chrome のショートカットキーしか練習できない

Google Chrome を選んだ理由は、課題となる(出題には工夫が必要となる)ショートカットキーを見つけやすいと考えたためです。

個人的には VSCodemacOS の Terminal など、普段の開発で扱うツールのショートカットキーを練習したいものの、プロトタイプでは練習できません。

出題できないショートカットキーがある

プロトタイプでは 次に該当するショートカットキーは出題できていません。

  • 入力するとショートカットキー本来の機能が実行されてしまう(JavaScript で無効化できなかった一部のショートカットキー)
  • 操作に対応するショートカットキーが複数ある(すなわち回答が複数ある)
  • キー入力以外にも、画面のクリック等の追加操作を必要とする

少なくともショートカットキーを確認できるように、たとえば「回答不要」として出題するなどして、身につけられるようにしたいです。

「すでに身についた」もしくは「興味のない」ショートカットキーが繰り返し出題される

初見のときは「これ知ってる!」や「これ知らなかった〜」と興味をもてるものの、見慣れてくると「すでに身についた」もしくは「興味のない」ショートカットキーへの回答が段々と手間に感じてきます。

できるだけ「身につけたい」かつ「身についてない」ショートカットキーが出題されてほしいです。

これからやること

予定していた作業期間の約8週間のうち、すでに5週間以上が過ぎました。そのためすぐにでも開発を進めて前述の課題を解決していきたいものの、プロトタイプでは品質を気にしていなかったためテストもなく、新機能を追加しにくいコードになっています。

そのため、まず先にテストを追加し、リファクタリングして品質を改善していく予定です。またその際、プロトタイプを触りながら、追加したい機能やその優先順位を考えていきます。

その後に、前述の課題や新たに気づいた課題を解決できるように、開発を進めていく予定です。

最後に

以上、Shortype のプロトタイプ・やってきたこと・これからやることを紹介しました。

プロトタイプの作成過程でご意見をくださった、えにしテック及びフィヨルドブートキャンプのみなさま、本当にありがとうございます。

残り3週間弱、できることは限られていますので、大事と思える課題から順に解決していき、自分なりに納得するものを改めてリリースしたいと思います。