diff --git a/src/actions/tabs.js b/src/actions/tabs.js index eb5032b..b16dc11 100644 --- a/src/actions/tabs.js +++ b/src/actions/tabs.js @@ -1,5 +1,10 @@ export const SELECT_TAB = 'SELECT_TAB'; +export const REFRESH_TAB_TIME = 'REFRESH_TAB_TIME'; export const selectTab = (tab, account) => { return { type: SELECT_TAB, tab, account } } + +export const refreshTabTime = (tab, account) => { + return { type: REFRESH_TAB_TIME, tab, account } +} diff --git a/src/components/retweet.js b/src/components/retweet.js index 5bf714b..fcf97bc 100644 --- a/src/components/retweet.js +++ b/src/components/retweet.js @@ -8,6 +8,7 @@ export default class Retweet extends Tweet { static propTypes = { account: PropTypes.object.isRequired, active: PropTypes.bool.isRequired, + now: PropTypes.number, tab: PropTypes.string.isRequired, tweet: PropTypes.object.isRequired, onClick: PropTypes.func.isRequired, @@ -23,7 +24,7 @@ export default class Retweet extends Tweet {
- +
Retweeted by diff --git a/src/components/time.js b/src/components/time.js index a657021..64be1a6 100644 --- a/src/components/time.js +++ b/src/components/time.js @@ -23,16 +23,8 @@ moment.locale( ); export default class Time extends React.Component { - // componentDidMount() { - // this.intervalId = setInterval(this.update.bind(this), 1000 * 60); - // } - - // componentWillUnmount() { - // clearInterval(this.intervalId); - // } - shouldComponentUpdate(nextProps, nextState) { - return false; + return this.props.now != nextProps.now; } getRelativeTime() { @@ -62,12 +54,8 @@ export default class Time extends React.Component { render() { return( ); } - - update() { - this.forceUpdate(); - } } diff --git a/src/components/tweet-header.js b/src/components/tweet-header.js index a9e5b44..fd387b1 100644 --- a/src/components/tweet-header.js +++ b/src/components/tweet-header.js @@ -4,6 +4,7 @@ import Time from '../components/time'; export default class TweetHeader extends React.Component { static propTypes = { tweet: PropTypes.object.isRequired, + now: PropTypes.number, } render() { @@ -13,7 +14,7 @@ export default class TweetHeader extends React.Component { {this.props.tweet.user.name} {this.props.tweet.user.screen_name}
-
); } diff --git a/src/components/tweet-list.js b/src/components/tweet-list.js index f26d062..cde5487 100644 --- a/src/components/tweet-list.js +++ b/src/components/tweet-list.js @@ -9,6 +9,7 @@ export default class TweetList extends React.Component { tab: PropTypes.string.isRequired, tweets: PropTypes.array.isRequired, withHeader: PropTypes.bool, + now: PropTypes.number, } render() { @@ -21,6 +22,7 @@ export default class TweetList extends React.Component { tab={this.props.tab} account={this.props.account} activeTweetId={this.props.activeTweetId} + now={this.props.now} /> )} diff --git a/src/components/tweet.js b/src/components/tweet.js index e001145..eea126f 100644 --- a/src/components/tweet.js +++ b/src/components/tweet.js @@ -9,6 +9,7 @@ export default class Tweet extends React.Component { static propTypes = { account: PropTypes.object.isRequired, active: PropTypes.bool.isRequired, + now: PropTypes.number, tab: PropTypes.string.isRequired, tweet: PropTypes.object.isRequired, onClick: PropTypes.func.isRequired, @@ -50,7 +51,7 @@ export default class Tweet extends React.Component {
- +
diff --git a/src/containers/tweet-container.js b/src/containers/tweet-container.js index 889a6b0..d496ba6 100644 --- a/src/containers/tweet-container.js +++ b/src/containers/tweet-container.js @@ -7,7 +7,8 @@ import Retweet from '../components/retweet'; export default class TweetContainer extends BaseContainer { shouldComponentUpdate(nextProps, nextState) { return (this.props.tweet.favorited != nextProps.tweet.favorited) || - ((this.props.activeTweetId === this.props.tweet.id_str) != (nextProps.activeTweetId === nextProps.tweet.id_str)); + ((this.props.activeTweetId === this.props.tweet.id_str) != (nextProps.activeTweetId === nextProps.tweet.id_str)) || + this.props.now != nextProps.now; } onClick(event) { @@ -23,6 +24,7 @@ export default class TweetContainer extends BaseContainer { tab={this.props.tab} tweet={this.props.tweet} onClick={this.onClick.bind(this)} + now={this.props.now} /> ); } else { @@ -33,6 +35,7 @@ export default class TweetContainer extends BaseContainer { tab={this.props.tab} tweet={this.props.tweet} onClick={this.onClick.bind(this)} + now={this.props.now} /> ); } diff --git a/src/containers/tweet-list-container.js b/src/containers/tweet-list-container.js index 6c3f49a..efb914f 100644 --- a/src/containers/tweet-list-container.js +++ b/src/containers/tweet-list-container.js @@ -6,11 +6,13 @@ const mapStateToProps = (state, props) => { let tweetsByTab = state.tabsByUserId[props.account.id_str] || {}; let activeTweetId = state.selectedTweetIdsByUserId[props.account.id_str] && state.selectedTweetIdsByUserId[props.account.id_str][props.tab]; + let nowByTab = state.nowsByUserId[props.account.id_str] || {}; return { - active: selectedTab === props.tab, - tweets: tweetsByTab[props.tab] || [], + active: selectedTab === props.tab, activeTweetId: activeTweetId, + now: nowByTab[props.tab], + tweets: tweetsByTab[props.tab] || [], } } diff --git a/src/index.js b/src/index.js index 90a7c92..e0777eb 100644 --- a/src/index.js +++ b/src/index.js @@ -6,10 +6,12 @@ import AppContainer from './containers/app-container'; import rootReducer from './reducers'; import IpcAction from './utils/ipc-action'; import GlobalKeyBind from './utils/global-key-bind'; +import TimeRefresher from './utils/time-refresher'; let store = createStore(rootReducer); -new IpcAction.subscribe(store); -new GlobalKeyBind.subscribe(store); +IpcAction.subscribe(store); +GlobalKeyBind.subscribe(store); +TimeRefresher.subscribe(store); if (process.env.NODE_ENV !== 'production') { //store.subscribe(() => console.log(store.getState())); diff --git a/src/reducers/index.js b/src/reducers/index.js index db1ec87..395b3e7 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -5,6 +5,7 @@ import { activeListIdByUserId } from './active-list-id-by-user-id'; import { editorFocused } from './editor-focused'; import { inReplyTo } from './in-reply-to'; import { listsByUserId } from './lists-by-user-id'; +import { nowsByUserId } from './nows-by-user-id'; import { searchQueryByUserId } from './search-query-by-user-id'; import { selectedTabByUserId } from './selected-tab-by-user-id'; import { selectedTweetIdsByUserId } from './selected-tweet-ids-by-user-id'; @@ -19,6 +20,7 @@ const rootReducer = combineReducers({ editorFocused, inReplyTo, listsByUserId, + nowsByUserId, searchQueryByUserId, selectedTabByUserId, selectedTweetIdsByUserId, diff --git a/src/reducers/nows-by-user-id.js b/src/reducers/nows-by-user-id.js new file mode 100644 index 0000000..245224b --- /dev/null +++ b/src/reducers/nows-by-user-id.js @@ -0,0 +1,17 @@ +import Actions from '../actions'; + +export const nowsByUserId = (state = {}, action) => { + switch (action.type) { + case Actions.REFRESH_TAB_TIME: + case Actions.SELECT_TAB: + return { + ...state, + [action.account.id_str]: { + ...(state[action.account.id_str] || {}), + [action.tab]: Date.now(), + } + }; + default: + return state; + } +} diff --git a/src/utils/ipc-action.js b/src/utils/ipc-action.js index e0f3222..2b91577 100644 --- a/src/utils/ipc-action.js +++ b/src/utils/ipc-action.js @@ -63,11 +63,19 @@ export default class IpcAction { ipcRenderer.on('select-next-account', (event) => { let index = this.state.nextAccountIndex(); this.dispatch(Actions.activateAccount(index)); + this.refreshTime(index); }); ipcRenderer.on('select-prev-account', (event) => { let index = this.state.prevAccountIndex(); this.dispatch(Actions.activateAccount(index)); + this.refreshTime(index); }); } + + refreshTime(index) { + let account = this.state.state.accounts[index]; + let tab = this.state.state.selectedTabByUserId[account.id_str] || 'home'; + this.dispatch(Actions.refreshTabTime(tab, account)); + } } diff --git a/src/utils/time-refresher.js b/src/utils/time-refresher.js new file mode 100644 index 0000000..0bc62a5 --- /dev/null +++ b/src/utils/time-refresher.js @@ -0,0 +1,26 @@ +import Actions from '../actions'; +import RichState from './rich-state'; + +export default class TimeRefresher { + static subscribe(store) { + new TimeRefresher(store).subscribe(); + } + + constructor(store) { + this.store = store; + } + + subscribe() { + setInterval(this.refresh.bind(this), 1000 * 60); + } + + refresh() { + let state = new RichState(this.store); + this.store.dispatch( + Actions.refreshTabTime( + state.activeTab(), + state.activeAccount(), + ) + ); + } +}