LoginSignup
55
59

More than 5 years have passed since last update.

Electron と React でPomodoro Timerアプリを作ってみる

Posted at

はじめに

React.js, JSX, ElectronでPomodoro Technique(ポモドーロテクニック)を実践できるタイマーアプリを作ってみました。

https://github.com/massa142/pomodoro

pomodoro_timer.png

作った理由

PHPカンファレンス2015でのKenji Akiyamaさんの発表資料を見て、「Electron面白そう!ちょっと試してみよ」となったためです。
Electronからクロスプラットフォーム・アプリケーションの歴史を考える

ただ作りたいものがパッと思いつかなかったので、Akiyamaさんと同じPomodoro Technique用のタイマーアプリをReact.jsで作ってみることにしました。

Pomodoro Techniqueとは

1.達成しようとするタスクを選ぶ
2.キッチンタイマーで25分を設定する
3.タイマーが鳴るまでタスクに集中する
4.少し休憩する(5分程度でOK)
5.ステップ2~4を4回繰り返したら、少し長めに休憩する

今日から始める生産性アップ術。ポモドーロ・テクニック再入門ガイド

rebuild.fm ep.93でもちょっと話題にあがってました。
http://rebuild.fm/93/

環境構築

ElectronもReactも今回初めて触ったので開発環境整えるのどうしようかなーと思ってたら、@Quramyさんが「ぼくのかんがえたさいきょうのElectron」開発環境を作ってくれていました。
ありがたくこのboilerplateを使わせて頂きました。

内部構成

.
├── README.md
├── bower.json
├── bower_components
├── dist
├── gulpfile.js
├── node_modules
├── package.json
├── release
└── src
    ├── app.js
    ├── assets
    │   └── images
    │       ├── electron.svg
    │       └── electron2.svg
    ├── browser
    │   └── menu
    │       └── appMenu.js
    ├── renderer
    │   ├── bootstrap.js
    │   ├── components
    │   │   └── main.jsx
    │   └── index.html
    └── styles
        └── main.scss

main.jsx

'use strict';

import React from 'react';
import notifier from 'node-notifier';

export class Main extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      isStart: false,
      isBreak: false,
      time: this.props.duration
    }
    this.handleStartClicked = ::this.handleStartClicked;
    this.handleResetClicked = ::this.handleResetClicked;
    this.tick = ::this.tick;
  }

  handleStartClicked() {
    if (!this.state.isStart) {
      this.interval = setInterval(this.tick, 1000);
      this.setState({isStart: true});
    } else {
      clearInterval(this.interval);
      this.setState({isStart: false});
    }
  }

  handleResetClicked() {
    this.reset();
  }

  tick() {
    this.setState({time: this.state.time - 1});
    if (this.state.time === 0) {
      this.finishEvent();
    }
  }

  finishEvent() {
    if (this.state.isBreak) {
      this.reset();
      this.notify('Break is over!');
    } else {
      this.break();
      this.notify('Good work!');
    }
  }

  break() {
    this.setState({
      isStart: true,
      isBreak: true,
      time: this.props.breakTime
    });
  }

  reset() {
    clearInterval(this.interval);
    this.setState({
      isStart: false,
      isBreak: false,
      time: this.props.duration
    });
  }

  notify(message) {
    notifier.notify({
      'title': 'Pomodoro Timer',
      'message': message
    });
  }

  converter = {
    s2m(s) {
      let minutes = Math.floor(s / 60);
      let seconds = s % 60;
      return ('0' + minutes.toString()).slice(-2) + ':' + ('0' + seconds.toString()).slice(-2);
    }
  };

  render() {
    return (
      <div className="container">
        <div className="jumbotron main">
          <h2>Pomodoro Timer</h2>
          <img src={this.state.isBreak ? "../assets/images/electron2.svg" : "../assets/images/electron.svg"} alt="" width="128px"></img>
          <h2>{this.converter.s2m(this.state.time)}</h2>
          <div>
            <button type="button" className="btn btn-primary" onClick={this.handleStartClicked}>
              {this.state.isStart ? "Pause" : "Start"}
            </button>
            <button type="button" className="btn btn-warning" onClick={this.handleResetClicked}>Reset</button>
          </div>
        </div>
      </div>
    );
  }
}

Main.defaultProps = {
  duration: 1500,
  breakTime: 300
};

感想

55
59
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
55
59