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

思っていたよりたくさんの方たちに見ていただいたようで、とにかく圧倒的にデザインがダサくて恥ずかしかったので、ちょっとだけバージョンアップしました。あと、前回のは Electron 成分が少なめでしたので、今回はちょっぴり増量しています。[レポジトリはこちら](https://github.com/k0sukey/Electron-LDR)。

## 圧倒的にダサかったデザインをなんとかした

Slack っぽくしてみました。ちょっとは今風になったかもしれないです。

![capture1.png](https://qiita-image-store.s3.amazonaws.com/0/47686/9d1d8102-08d5-6815-de46-9227a749e99a.png)

そもそもデザインセンスもないですし、HTML / CSS は 3〜4 年くらいまともに触っていないので、どなたかやってやるよ！って方がいらっしゃいましたらぜひ...。限界に近いです。

## 認証をどうにかする

アクセストークンをインスペクタから引っこ抜いて〜、とか自分でもやっていられないレベルだったので作りました。結果的に、スプラッシュスクリーンのようなものもできあがりました。

**よくあるエントリーポイントのウィンドウを作る流れ**

こんな感じですよね。認証をいれるのは index.html で HTML を作っていっても良いのですが、非常に面倒そうだった（HTML 辛い）のでウィンドウ自体をもう一つ増やしました。

```js
var window = null;

app.on('ready', function(){
    window = new BrowserWindow({
        title: 'Electron-LDR',
        width: 1024,
        height: 768
    });

    window.on('closed', function(){
        window = null;
    });

    window.loadUrl('file://' + path.join(__dirname, 'app', 'html', 'index.html'));
});
```

**スプラッシュスクリーンぽいものを挟んだ流れ**

```js
var window = null,
    splash = null;

app.on('ready', function(){
    splash = new BrowserWindow({
        width: 640,
        height: 480,
        frame: false,
        transparent: true
    });

    splash.on('closed', function(){
        splash = null;
    });

    splash.on('authorize', function(){
        window = new BrowserWindow({
            title: 'Electron-LDR',
            width: 1024,
            height: 768
        });

        window.on('closed', function(){
            window = null;
        });

        window.loadUrl('file://' + path.join(__dirname, 'app', 'html', 'index.html'));

        splash.close();
    });

    splash.webContents.once('did-finish-load', function(){
        setTimeout(function(){
            if (Cookie.exists()) {
                var cookies = Cookie.get();

                if (cookies === '') {
                    splash.loadUrl('file://' + path.join(__dirname, 'app', 'html', 'authorize.html'));
                    return;                 
                }

                splash.emit('authorize');
            } else {
                splash.loadUrl('file://' + path.join(__dirname, 'app', 'html', 'authorize.html'));
            }
        }, 1000);
    });

    splash.loadUrl('file://' + path.join(__dirname, 'app', 'html', 'boot.html'));
});
```

![スクリーンショット 2015-09-16 16.17.11.png](https://qiita-image-store.s3.amazonaws.com/0/47686/9102036f-3956-91d6-a90c-fce4246e4212.png)

起動時は ```splash``` という名前のウィンドウが開かれます。```frame: false``` の ```transparent: true``` にすると、縁と影がないウィンドウを作ることができます。そのままでは縁がないのでウィンドウを動かすことができませんので、CSS に ```body { -webkit-app-region: drag; }``` を追加してあげると動かすことができるようになります。app/html/boot.html ですね。で、この boot.html の読み込みが完了したら認証に入ります。

```splash.webContents.once('did-finish-load', function(){});``` のところですね。did-finish-load は onload なイベントです。認証していなかったら app/html/authorize.html を読み込みたいので once なイベント待ちになります。on ですと authorize.html が読み込まれたら、このイベントハンドラがまた動いちゃいますからね。ただ、boot.html から authorize.html の切り替わりにチカっとするのを何とかしたいところです。

せっかくスプラッシュスクリーンを作ったので、```setTimeout(function(){}, 1000);``` で 1 秒間だけアピールしておきます。クッキー持っていると一瞬で消えちゃいますので...。

認証自体はとりあえずクッキーを持っているかいないか、です。持っていなかったら ```splash``` ウィンドウに authorize.html を読み込みます。フォームが追加されただけですが。```splash``` ウィンドウは authorized というイベントハンドラが待ち受けていますので、認証が通過したら emit してあげます。Electron のウィンドウは Node.js の EventEmitter を継承しているそうなので、こういうとき楽ですね。

```frame: false``` で ```body { -webkit-app-region: drag; }``` なので、そのままだとフォームパーツを触ることができません。フォームパーツだけ ```-webkit-app-region: no-drag;``` するのを忘れずに。

認証自体は特に難しいことをやっているわけではありませんし、（ソースコードを見るとわかると思いますが）変なところにアカウント情報を POST しているわけでもないです。認証できたらクッキーを書き出して、authorized イベントを emit して終わりです。

```js
var livedoorid = document.getElementById('livedoorid').value,
    password = document.getElementById('password').value;

if (livedoorid === '' || password === '') {
    return;
}

request.post('https://member.livedoor.com/login/index', {
    form: {
        livedoor_id: livedoorid,
        password: password,
        auto_login: 1
    }
}, function(error, response, body){
    if (error || body !== '') {
        return;
    }

    Cookie.set(response.headers['set-cookie']);
    remote.getCurrentWindow().emit('authorized');
});
```

authorized イベントハンドラは今までのウィンドウを作っていたような流れになりますが、```window.loadUrl('file://' + path.join(__dirname, 'app', 'html', 'index.html'));``` した後に、```splash.close();```を追加してます。後始末ですね。

## 既読化

いい加減自分で使っていてイライラしたので既読化するようにしました。

## サイドバーの開閉

ショートカットを追加しました。本家と同じ ```z``` です。

## コンポーネントのライフサイクルをちゃんと意識した

React です。フィード一覧の更新や記事の読み込みは、とにかく render していただけでしたが、ちゃんと ```React.unmountComponentAtNode();``` してあげたり、componentDidMount / componentWillUnmount イベントでキーボードショートカットの bind / unbind するようにしてあります。

## まとめ

そこそこ使えるようになってきたと思います。というか、自分で実際に使っています。アイコンとかもデフォルトなのでなんとかしたいなあ、と思っています。