Electron で Live Dwango Reader（旧 Live Door Reader）クライアントを作ってみる、その三


その三です。徐々にアプリっぽくなってきたかな？というった感じですが、どうでしょうか。[レポジトリはこちら](https://github.com/k0sukey/Electron-LDR)。

![スクリーンショット 2015-09-24 13.47.07.png](https://qiita-image-store.s3.amazonaws.com/0/47686/500ae8b2-04bf-45b1-a49d-23cb2c22e17a.png)

## ソートとフィルタを追加した

フィード一覧のサイドバーにソートの変更とフィルタ（検索ボックス）を追加しました。React のコンポーネントを作るレベルではないかなと思い、ベタに HTML を書いて、onchange で監視しています。

ソート・フィルタの変更で毎回データを取得するのもアレですし、データ取得と画面描画を分けました。こういうとき React は楽ですね。フィルタリングしてソートした JSON をレンダーに渡すだけで終わっちゃいます。

## キーボードショートカット（と LDR API）を増量

* ```p``` ： ピンの付け外し
* ```c``` ： 本文の表示・非表示
* ```f``` ： フィルタ（検索ボックス）に移動
* ```b``` ： ブラウザで開く

キーボードショートカットのフィルタの移動が少々面倒でした。キーボードショートカットには [mousetrap](https://github.com/ccampbell/mousetrap) を利用しています。「f」キーでテキストボックスへフォーカスをあてると「f」が入力されてしまうんですよね。これを回避するため、キー入力時に ```_.defer(function(){});``` でフォーカスメソッドを一瞬遅延させています。

```js
mousetrap.bind('f', function(){
	_.defer(function(){
		document.getElementById('filter').focus();
	});
});
```

## 設定を追加した

![スクリーンショット 2015-09-24 13.49.31.png](https://qiita-image-store.s3.amazonaws.com/0/47686/f56d59a1-df83-9ecb-765b-27900da08b24.png)

Mac のよくある設定っぽくしていますが、Windows / Linux でマッチするかの確認まではしていません...。

設定は app/data/setting.json に書き出しているのですが、このファイルを [watchr](https://github.com/bevry/watchr) で監視しています。例えば、フォントの切り替えはこんな感じですね。

```js
watchr.watch({
	path: path.join(__dirname, '..', 'data', 'setting.json'),
	listener: function(){
		var setting = Setting.get();
		document.getElementsByTagName('body')[0].style.fontFamily = setting.fontfamily;
	}
});
```

初期値 5,007 msec でポーリングしているそうで、少々の遅延を感じますがインターバルを短くするとパフォーマンスに影響が出てきそうなので、初期値のままにしてあります。

また、設定ファイルの app/data/setting.json ですが、```require``` で読み込んでいるため内容を変更してもキャッシュが効いてしまい、読み込み側では内容が書き換わっていません。この問題を回避するため、app/data/setting.json を ```require``` する直前に必ずキャッシュを削除するようにしてあります。

```js
delete require.cache[path.join(__dirname, 'data', 'setting.json')];
return require('./data/setting');
```

話はそれますが、```require``` の中身ってどうなっているのか普段あまり意識しませんよね？中身を見てみると結構面白いので、ぜひ一度下記のコードを動かしてみると良いと思います。実は ```require``` 自体をラップすることもできるんですよね。コードカバレッジツールの [nyc](https://github.com/bcoe/nyc) が参考になります。

```js
console.log(require('util').inspect(require));
```

## ログアウトを追加した

ログインできるようにあったらログアウトも必要でしょ、ってことでログアウトできるようになりました。処理自体はクッキーを削除して、```app.emit('ready');``` しているだけです。一点だけ変更があります。ready イベント内でアプリのメインウィンドウが ```null``` でない場合、スプラッシュウィンドウを開いたらメインウィンドウを閉じる処理を追加してあります。

また、スプラッシュと認証ウィンドウの HTML を分けていましたが、（HTML の読み込みのチラツキも気に入らなかったので）一本化しました。起動時はログインフォームを ```visibility: hidden;``` にしていて、```onload``` したら ```visibility: visible;``` するだけです。

## ピンの全て削除を追加した

元々は読んでフィードを消化することに特化していたので、実装する予定はなかったのですが、まあ、メニューに押し込んだので良しとします。

## ブラウザで開くを追加した

個人的にはあまり使いませんが、誰かが幸せになれるかと思いまして。規定のブラウザに指定されているブラウザで元記事を開くために、[opener](https://github.com/domenic/opener) を使っています。使い方は簡単、こんな感じです。

```js
var opener = require('opener');
opener('https://www.google.com');
```

## 課題

1. パッケージ化すると、```Cannot read property 'firstChild' of undefined``` 問題。コマンドラインから起動する分には問題ないのですが、まだ解決できていません。配布できないです...
2. インジケータを付けたい。ログイン時やフィード読み込み時など、通信の進捗を表示させたいと考えています。FontAwesome の力を借りようかと思います
3. アプリ終了時の状態保存。ブラウザ版でもタブ自体を再読込してよくやってしまうのですが、起動時に前回終了時の直前までの状態を保存できたら良いなと考えております。フィード一覧と記事一覧のコンポーネントをまたがることになるので、ちょっと時間がかかるかな？といったところです
4. 元記事を開いた直後はスクロールできない。一度ポインタで元記事をクリックしないとスクロールできない問題です。解決方法が全くわかりません...。

## まとめ

はやく GitHub の Releases にアプリを起きたいのですが、課題 1 をクリアしないとなんともできないです...。機能的にはソコソコ拡充できてきたので、今後は課題の消化をしていこうかと思います。