みずぴー日記

人間の再起動ボタンはハワイのビーチにある

 💫Tumblotte 0.1.0

💫Tumblrクライアントを作りはじめた - みずぴー日記 で書いたTumblrクライントをリリースした。

テキスト主体のブログを書きやすくすることを目指している。 そのためMarkdownのライブプレビュー機能などを実装しているが、Reblog機能などは実装していない。

f:id:mzp:20160117134517p:plain

機能

  • Tumblrへの投稿・更新
  • Markdownのライブプレビュー
  • 既存の投稿記事の取得
  • 投稿先のブログの切り替え
  • 投稿した記事をWebブラウザで開く

前回から、基本的には変わっていない。エラー処理などをだいぶまともにした。

実装していない機能

自分があまり使わないので実装してない。必要になったら実装する。

  • MacOS X以外のサポート
  • Text以外の記事

ダウンロード

https://github.com/mzp/tumblotte/releases/tag/0.1.0

前回からの変更点

dmgの作成

インストールするときに使うdmgを作った。以下のような /Applications へのコピーを促すような背景画像も作成した。

f:id:mzp:20160117134813p:plain

コード署名の追加

*.app を作るときにコード署名をするようにした。

細かい修正

自分で使っていて気になった部分をいくつか修正した。

  • 常にライブプレビューを行なうとレスポンスが悪いので、300ms以上キー入力がなかったときにプレビューを更新するようにした。(debounce)
  • メインメニューの項目を整理した。
  • ライセンスとしてMITライセンスを採用した。

 ⌨AquaSKK 4.3.4: US配列におけるAZIKの動作改善

US配列 + AZIKにおいて、x[ の入力を行なえるようにした。

ダウンロード

https://github.com/codefirst/aquaskk/releases/tag/4.3.4

変更内容

US配列 + AZIKでは [ がかなモードの切り替えに使われる。 そのため、[ に割り当てられている の変換が行なえない。

ddskkでは x[ で 元の [ を代用できるようにして、この問題を解決していた。(参考: SKK Manual: AZIK)

AquaSKKでもこの方式を採用することにした。

余談

🎍新年

f:id:mzp:20160109104544p:plain

Copyright(C) 2014-2016 という部分を更新したので、新年を迎えた感じになった。

状態遷移機械

変換の動作は、専用の状態遷移機械記述ライブラリで定義されている。 このライブラリに関するドキュメントは Generic State Machine Library for C++ しか残っておらず、苦労した。

分かったことをメモしておく。

  • 状態は関数で表現され、遷移のルールはその関数の中身で表現される。
  • 定義は複数のファイルにまたがって行なわれるが、CPPを用いて1つのファイルに結合された上でコンパイルされる。
  • 状態はSubStateを持てる。たとえば、かな変換状態のSubStateとしてひらかな変換状態、カタカナ変換状態、半角カナ変換状態なのが定義されていた。

 💫Tumblrクライアントを作りはじめた

記事の投稿に特化したTumblrクライアントを作りはじめた。

f:id:mzp:20160103203837p:plain

レポジトリ

https://github.com/mzp/tumblotte

動機

TumblrはリブログするだけのWebサービスでもなく、高機能なブログサービスでもあることに気がついた。

  • Markdownで書ける。
  • 独自ドメインでの運用もできる。
  • 複数のブログも管理できる。
  • テーマも多数存在する。

しかし、TumblrのWebUIは長文を書くのには向いていないので、Tumblrのクライアントを作りはじめた。

ElectronやReact.js等のJavaScriptまわりの技術にキャッチアップしたかった、という理由もある。

機能

  • Tumblrへの投稿・更新
  • Markdownのライブプレビュー
  • 既存の投稿記事の取得
  • 投稿先のブログの切り替え
  • 投稿した記事をWebブラウザで開く

Kobitoを意識しながら作りはじめた。 が、インターネットが不自由な環境で作っていたので、思ったよりUIが似ていない。

名前の由来

どういう名前にするか相談したときに、Charlotteの一挙放送をしていたので、こうなった。

知見

  • ElectronでOAuth認証をする方法は Electron. oAuth authentication with GitHubを参考にした。
  • Tumblrに投稿にするにはtumblrを使っている。しかし、いくつか機能が不足していたので、自分でforkして拡張した。mzp/node-tumblr
    • tumblrwksを使ったほうがよかったかもしれない。
  • "electron boilerplate" で検索したら、5つくらいでてきてツラかった。 結局、boilerplateは使わずに自分で書いた。

画像で見る開発の流れ

開発開始直後(2015/12/30)

f:id:mzp:20160103215512p:plain

PureCSSのEmail layoutをざっくりあてた直後。まだ表示ができるだけで、投稿等はできない。

基本機能完成(2015/12/31)

f:id:mzp:20160103215848p:plain

ライブプレビュー機能Tumblrへの投稿機能を付けた。

UIの調整(2016/1/1)

f:id:mzp:20160103220331p:plain

FontAwesomeを使って、各ボタンにアイコンを割り当てていった。

ログイン機能(2016/1/2)

f:id:mzp:20160103220524p:plain

ここまでAccessTokenは固定だったので、ログイン機能をつけた。ログイン画面をどうするか迷ったあげく、結局ボタン1個だけを配置した。

投稿先ブログの切り替え(2016/1/3)

f:id:mzp:20160103220954p:plain

投稿先のブログを切り替えれるようにした。

代償

⚠️AquaSKK with iCloud

☁️AquaSKKのiCloud対応 - みずぴー日記の内容を整理した上で、パッケージを作成した。 自分で試すためのが主な目的なので、他の人が利用することはあまり想定していない。

Release iCloud対応(1) · codefirst/aquaskk · GitHub

f:id:mzp:20151228204112p:plain

注意点

  • 今後、データの持ち方を変える可能性がある。 その際は、同期データがすべて消失する。
  • ローカルのユーザ辞書が破壊される可能性がある。実際、開発中に二度ほど破壊した。
  • その他、予期しない動作をするかもしれない。

何かあったらiCloud対応PRに書いてほしい。 対応できるかどうかは分からない。

リリースするまでに解決しなければいけない課題

ビルドに必要な証明書の管理

iCloudに接続するために、AquaSKKにひもづいた証明書が必要となった。 その証明書は、ローカルにしか存在していないので、以下のような問題が生じる。

  • AquaSKKのビルドを他の人ができない。 そのためチーム開発が困難になる。
  • TravisCI上でビルドを行なえない。

FlickSKKとの共有をどうするか

FlickSKKのビルドは@が自分のIDで行なっているので、AquaSKKiCloud領域にはアクセスできない。

辞書の形式はほぼ同一なので、なんとか共有できるようにした。個人アカウントの制約のようなものなので、起業したほうがいいかもしれない。

x86対応

iCloud対応のために用いているCloudKitがx86_64バイナリしかないため、x86に対応できない。

最近のOS Xx86では動かないようだし、対応をやめてもいいと思っている。

前回からの変更内容

レコードIDの変更

前回は見出し語は重複しないものとして、見出し語をレコードIDとして用いていた。

しかし、以下のように見出し語が重複している場合もありえるので、見出し語をレコードIDとして用いるのをやめた。

;; okuri-ari entries.
わるi /悪/
;; okuri-nasi entries.
わるi /悪/

同期用スレッドの統一

前回は、ローカルの辞書をiCloudに送信するスレッドと、iCloudから取得したデータをローカルの辞書にマージするスレッドを別々にしていた。

そのせいでコードが複雑化していたため、すべて1つのスレッドで行なうようにした。

コードの整理

今後メンテナンスすることを考えて、コードを整理した。

  • コピペですませていた部分を共通化した。
  • Objectvie-CとC++の部分を増やし、Objective-C++部分を減らした。

キーボード二刀流を初めて三ヶ月弱が経過した

f:id:mzp:20151224212839j:plain

キーボード二刀流というのはこういうやつ。 肩凝りが改善するという話だったので初めてみて、三ヶ月弱が経過した。

要約

肩凝りは特に改善も悪化もしていない。

所感

  • 初めて最初の3時間くらいは違和感があった。すぐ慣れる。
  • たまに手をホームポジションに戻すのをミスったりする。
  • 机がちょっとだけ狭くなった。
  • トラックパッドをどこに置くのがいいかよくわからない。今は右手のすぐ下に置いている。
  • 使えるキーボードが2倍になったので死蔵してたキーボードが減った。よい。
  • 多少肩が楽になった気がする。
  • オフィスでも二刀流にしてたら、「この会社にはモニタを2台使ってる人も、キーボードを2台使ってる人もいるの...。こわい...。」って言われた。

🏁 AquaSKK 4.3.3: MS Excel 2016対応

Office 2016のExcelでモード切り替え時にl/L/qが入力されないようにした by zalt50 · Pull Request #38 · codefirst/aquaskk · GitHubを取り込み、AquaSKK 4.3.3をリリースした。(thx to zalt50)。

ダウンロード

https://github.com/codefirst/aquaskk/releases/tag/4.3.3

変更内容

MS Excel 2016で、l/q/Lなどによる入力モードした場合、l/q/Lなどが入力されてしまう問題が修正された。詳細は#13を参照してほしい。

余談

ちなみにExcel 2011では問題なく動くらしい。動くことを確認した人が「骨董品での動作報告はちょっと…」ってdisられていたけど。

☁️AquaSKKのiCloud対応

パッケージを作って ☁️AquaSKK with iCloud - みずぴー日記 に置いた。


AquaSKKのユーザ辞書をiCloudで同期するようにした。 自分の使っているMacBookiMacで辞書を共有できるようになった。

f:id:mzp:20151129095135p:plain

現状

cloudkitブランチに最新の内容がpushしてある。 いくつかのコーナーケースが残っているが、実用上の問題はないと思う。

もうちょっと完成度があがったら、ベータ版のインストーラとか作ると思う。

iCloudの使い方

iCloudを使う方法は4種類ある。 それぞれの特徴については[iOS 8] CloudKit を使ってみよう (1) 概要 | Developers.IOの冒頭に簡潔にまとまっている。 Appleの文書だとiCloud設計ガイド(PDF)がよい。

この4種類のどれを使うかはかなり悩んだが、今回はCloudKtiを使うことにした。

Key-value Storage
1MBまでしか保存できないので、容量が不足している。
iCloud document storage
ファイルベースを意識することになるので、単語登録したときの競合解決を実装するのが大変そう。
Core Data storage
現時点でCore Dataを用いていないので、あまり利点がなさそう。
CloudKit
iCloud上に構築されたKVSとして扱えるので、辞書データをそのまま格納できそう。 また、CloudKit dashboardで登録されたデータを確認できるので、開発が楽そう。

保存領域

CloudKitにはどのユーザでもアクセスできるpublic領域と、そのユーザしかアクセスできないprivate領域がある。 public領域の容量はアプリによって決まり、private領域の容量はユーザのアカウントによって決まる。(参考: Designing for CloudKit)

AquaSKKの辞書はprivate領域に格納するようにしたので、他のアカウントから辞書データにアクセスすることはできない。また辞書データはユーザのiCloud driveに保存される。

f:id:mzp:20151129103357p:plain

主な構造

f:id:mzp:20151129100702p:plain

SKKのエンジンが直接iCloudと通信するのを避け、中間にユーザ辞書を挟む方式を採用した。

  1. SKKのエンジンは、これまで通りユーザ辞書に対して単語の検索・登録を行なう。
  2. 同期するためのクラスがユーザ辞書を読み込み、更新分をiCloudに送信する。
  3. 定期的にiCloudの更新を確認し、更新があった場合はユーザ辞書に単語を追加する。

単語を検索するたびにiCloudと通信する方法も検討したが、ネットワーク通信ができない環境での利用を想定して断念した。

単語の削除

基本的に、iCloudから取得した単語をローカルの辞書にマージすることで、辞書の同期を実現している。 ただし、それだけでは、辞書から単語を削除しても簡単に復活してしまう。

そこで、「ユーザ操作によって削除された単語」は別枠で管理するようにし、ここに登録された単語は同期のタイミングでユーザ辞書から消すようにした。

同期状態の表示

同期状態を通知するために通知センターを利用している。

f:id:mzp:20151129095135p:plain

Dropboxのようにメニューバーに出しているアイコンで通知したかったが、InputMethodのアイコンを動的に変化させることができなったため断念した。

通知センターに用いられるアイコンはシステムにキャッシュされるらしく、AppIconを更新しても反映されなかった。 バージョンやビルド番号を更新すれば反映された。

設定画面

f:id:mzp:20151129102329p:plain

設定画面からiCloud同期の有効・無効化を切り替えれる。 無効にした場合はこれまでと同様の動作をする。

その他の知見

  • CloudKitの使い方はccabanero/ios-cloudkit-snippets · GitHubがシンプルにまとまってて、よかった。
  • テストにはL辞書にない単語を使う必要があったので、ゆるゆりの登場人物名を使っていた。 特に、同じ読みの単語がない「歳納」と、同じ読みの単語がある「赤座」の2つが便利だった。
  • AquaSKKのエンジン部はC++、CloudKitを利用する箇所はObjectvie-Cなので、Objective-C++を使うことになった。 いわゆる「文字列」に対応する型が、const char[]std::stringNSString*の3種類登場してつらかった。