Skip to content
This repository has been archived by the owner on Apr 7, 2023. It is now read-only.

Commit

Permalink
Revenge relative time
Browse files Browse the repository at this point in the history
  • Loading branch information
k0kubun committed Mar 20, 2016
1 parent b03bf17 commit ca42935
Show file tree
Hide file tree
Showing 13 changed files with 80 additions and 22 deletions.
5 changes: 5 additions & 0 deletions src/actions/tabs.js
Original file line number Diff line number Diff line change
@@ -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 }
}
3 changes: 2 additions & 1 deletion src/components/retweet.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -23,7 +24,7 @@ export default class Retweet extends Tweet {
<i className='retweet_icon fa fa-retweet' />
</div>
<div className='right_box'>
<TweetHeader tweet={this.props.tweet.retweeted_status} />
<TweetHeader tweet={this.props.tweet.retweeted_status} now={this.props.now} />
<div className='tweet_body' dangerouslySetInnerHTML={this.autolinkedText(this.props.tweet.retweeted_status)} />
<div className='retweeted_by_wrapper'>
<span className='retweeted_by'>Retweeted by</span>
Expand Down
16 changes: 2 additions & 14 deletions src/components/time.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -62,12 +54,8 @@ export default class Time extends React.Component {
render() {
return(
<time {...this.props} dateTime={this.getDateTime()} title={this.getAbsoluteTime()}>
{this.getAbsoluteTime()}
{this.getDisplayedTime()}
</time>
);
}

update() {
this.forceUpdate();
}
}
3 changes: 2 additions & 1 deletion src/components/tweet-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -13,7 +14,7 @@ export default class TweetHeader extends React.Component {
<span className='user_name'>{this.props.tweet.user.name}</span>
<span className='screen_name'>{this.props.tweet.user.screen_name}</span>
</div>
<Time className='created_at' time={this.props.tweet.created_at} />
<Time className='created_at' time={this.props.tweet.created_at} now={this.props.now} />
</div>
);
}
Expand Down
2 changes: 2 additions & 0 deletions src/components/tweet-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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}
/>
)}
</ul>
Expand Down
3 changes: 2 additions & 1 deletion src/components/tweet.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -50,7 +51,7 @@ export default class Tweet extends React.Component {
<img className='user_icon' src={this.largeProfileImage(this.props.tweet.user)} />
</div>
<div className='right_box'>
<TweetHeader tweet={this.props.tweet} />
<TweetHeader tweet={this.props.tweet} now={this.props.now} />
<div className='tweet_body' dangerouslySetInnerHTML={this.autolinkedText(this.props.tweet)} />
</div>
<div className='right_widget'>
Expand Down
5 changes: 4 additions & 1 deletion src/containers/tweet-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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 {
Expand All @@ -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}
/>
);
}
Expand Down
6 changes: 4 additions & 2 deletions src/containers/tweet-list-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -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] || [],
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
Expand Down
2 changes: 2 additions & 0 deletions src/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -19,6 +20,7 @@ const rootReducer = combineReducers({
editorFocused,
inReplyTo,
listsByUserId,
nowsByUserId,
searchQueryByUserId,
selectedTabByUserId,
selectedTweetIdsByUserId,
Expand Down
17 changes: 17 additions & 0 deletions src/reducers/nows-by-user-id.js
Original file line number Diff line number Diff line change
@@ -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;
}
}
8 changes: 8 additions & 0 deletions src/utils/ipc-action.js
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
26 changes: 26 additions & 0 deletions src/utils/time-refresher.js
Original file line number Diff line number Diff line change
@@ -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(),
)
);
}
}

0 comments on commit ca42935

Please sign in to comment.