Skip to content

Commit

Permalink
more
Browse files Browse the repository at this point in the history
  • Loading branch information
shprink committed Jun 23, 2017
1 parent 60ced0e commit e25831d
Show file tree
Hide file tree
Showing 29 changed files with 407 additions and 212 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -31,7 +31,7 @@
"angularfire2": "^4.0.0-rc.0",
"date-fns": "^1.28.5",
"firebase": "^4.0.0",
"ionic-angular": "^3.4.2",
"ionic-angular": "nightly",
"ionicons": "3.0.0",
"lodash": "^4.17.4",
"rxjs": "5.1.1",
Expand Down
28 changes: 28 additions & 0 deletions server/index.js
Expand Up @@ -103,13 +103,41 @@ app.post('/api/tweet', (req, res) => {
});
});

app.post('/api/retweet', (req, res) => {
var client = getTwitterClient(req);
client.post(`statuses/retweet/${req.body.id}`, Object.assign({ trim_user: false }, req.body || {}), function (error, body, response) {
(!error) ? res.status(200).json(body) : res.status(400).json(error);
});
});

app.post('/api/unretweet', (req, res) => {
var client = getTwitterClient(req);
client.post(`statuses/unretweet/${req.body.id}`, Object.assign({ trim_user: false }, req.body || {}), function (error, body, response) {
(!error) ? res.status(200).json(body) : res.status(400).json(error);
});
});

app.post('/api/mentions', (req, res) => {
var client = getTwitterClient(req);
client.get('statuses/mentions_timeline', req.body, function (error, body, response) {
(!error) ? res.status(200).json(body) : res.status(400).json(error);
});
});

app.post('/api/favorite', (req, res) => {
var client = getTwitterClient(req);
client.post('favorites/create', Object.assign({ include_entities: true }, req.body || {}), function (error, body, response) {
(!error) ? res.status(200).json(body) : res.status(400).json(error);
});
});

app.post('/api/unfavorite', (req, res) => {
var client = getTwitterClient(req);
client.post('favorites/destroy', Object.assign({ include_entities: true }, req.body || {}), function (error, body, response) {
(!error) ? res.status(200).json(body) : res.status(400).json(error);
});
});

app.post('/api/messages', (req, res) => {
var client = getTwitterClient(req);
client.get('direct_messages', req.body, function (error, body, response) {
Expand Down
1 change: 1 addition & 0 deletions src/actions/index.ts
Expand Up @@ -6,3 +6,4 @@ export * from './users';
export * from './feed';
export * from './trends';
export * from './mentions';
export * from './tweet';
26 changes: 26 additions & 0 deletions src/actions/tweet.ts
@@ -0,0 +1,26 @@
import { Action } from '@ngrx/store';

export const TWEET_RETWEET = 'TWEET_RETWEET';
export const TWEET_UNRETWEET = 'TWEET_UNRETWEET';
export const TWEET_FAVORITE = 'TWEET_FAVORITE';
export const TWEET_UNFAVORITE = 'TWEET_UNFAVORITE';

export const tweetRetweet = (tweet, id): Action => ({
type: TWEET_RETWEET,
payload: { tweet, id }
});

export const tweetUnretweet = (tweet, id): Action => ({
type: TWEET_UNRETWEET,
payload: { tweet, id }
});

export const tweetFavorite = (tweet): Action => ({
type: TWEET_FAVORITE,
payload: { tweet }
});

export const tweetUnfavorite = (tweet): Action => ({
type: TWEET_UNFAVORITE,
payload: { tweet }
});
2 changes: 1 addition & 1 deletion src/app/app.component.ts
Expand Up @@ -29,7 +29,7 @@ export class MyApp {
if (this.previousAuthState !== isAuthenticated) {
console.log('isAuthenticated', isAuthenticated, )

if (isAuthenticated && !location.hash.includes('home')) {
if (isAuthenticated && !location.hash.includes('login')) {
this.nav.setRoot('HomePage');
} else if (!isAuthenticated && !location.hash.includes('login')) {
this.nav.setRoot('LoginPage');
Expand Down
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Expand Up @@ -37,6 +37,7 @@ import {
ServiceWorkerProvider,
SearchProvider,
MentionsProvider,
TweetProvider,
} from '../providers';
import { MenuComponentModule } from '../components/menu/menu.module';
import { HttpWrapper } from './http.wrapper';
Expand Down Expand Up @@ -106,6 +107,7 @@ export function provideHttp(
ServiceWorkerProvider,
SearchProvider,
MentionsProvider,
TweetProvider,
],
})
export class AppModule {}
7 changes: 4 additions & 3 deletions src/components/feed/feed.ts
@@ -1,7 +1,7 @@
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
import { InfiniteScroll, Refresher } from 'ionic-angular';

import { ITweet } from './../../reducers/feed';
import { ITweet } from './../../reducers';
/**
* Generated class for the FeedComponent component.
*
Expand All @@ -11,6 +11,7 @@ import { ITweet } from './../../reducers/feed';
@Component({
selector: 'feed',
templateUrl: 'feed.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FeedComponent {
@Input() content: ITweet[];
Expand All @@ -34,6 +35,6 @@ export class FeedComponent {
}

trackById(index, item) {
return item.id;
return item.id_str;
}
}
2 changes: 1 addition & 1 deletion src/components/og/og.ts
@@ -1,6 +1,6 @@
import { Component, Input } from '@angular/core';

import { ITweetEntitiesUrl } from './../../reducers/feed';
import { ITweetEntitiesUrl } from './../../reducers';
/**
* Generated class for the OgComponent component.
*
Expand Down
19 changes: 17 additions & 2 deletions src/components/tweet/tweet.html
Expand Up @@ -2,8 +2,23 @@
<ion-item text-wrap *ngIf="data">
<avatar item-start [user]="data.user" (click)="goToProfile()"></avatar>
<h2><span class="name">{{data.user.name}}</span> <span class="handle">@{{data.user.screen_name}}</span></h2>
<p [innerHTML]="data.text | autoLink"></p>
<p><ng-template #dynamicText></ng-template></p>
<p [innerHTML]="text"></p>
<p>
<ng-template #dynamicText></ng-template>
</p>
<media *ngIf="media" [data]="media"></media>
<og></og>
<div class="actions">
<button ion-button clear>
<ion-icon name="chatboxes" color="gray"></ion-icon>
</button>
<button ion-button clear class="retweet" [class.active]="data.retweeted" (click)="retweet()">
<ion-icon name="repeat" color="gray"></ion-icon>&nbsp;
<span *ngIf="data.retweet_count">{{ data.retweet_count }}</span>
</button>
<button ion-button clear class="favorite" [class.active]="data.favorited" (click)="favorite()">
<ion-icon name="heart" color="gray"></ion-icon>&nbsp;
<span *ngIf="data.favorite_count">{{ data.favorite_count }}</span>
</button>
</div>
</ion-item>
21 changes: 21 additions & 0 deletions src/components/tweet/tweet.scss
@@ -1,11 +1,32 @@
tweet {
.item-inner {
padding: 10px 0;
ion-label{
overflow: hidden;
flex:1;
}
}
avatar{
margin: 0 !important;
}
ion-item {
align-items: baseline !important;
}
.actions{
margin-top: 10px;
display: flex;
flex-direction: row;
justify-content: space-between;
button {
margin: 0;
font-size: 1.7rem !important;
color: color($colors, gray);
&.retweet.active {
color: color($colors, secondary)
}
&.favorite.active {
color: color($colors, danger)
}
}
}
}
19 changes: 18 additions & 1 deletion src/components/tweet/tweet.ts
@@ -1,8 +1,10 @@
import { Component, Input } from '@angular/core';
import { App } from 'ionic-angular';
import { autoLinkWithJSON } from 'twitter-text';
import _get from 'lodash/get';

import { ITweet, ITweetEntitiesMedia } from './../../reducers';
import { TweetProvider } from './../../providers';
/**
* Generated class for the TweetComponent component.
*
Expand All @@ -19,12 +21,19 @@ export class TweetComponent {

@Input() data: ITweet;

constructor(public appCtrl: App) {
constructor(
public appCtrl: App,
public tweetProvider: TweetProvider,
) {
console.log('Hello TweetComponent Component');
}

ngOnInit() {
this.media = _get(this.data, 'entities.media[0]');
this.text = autoLinkWithJSON(this.data.text, _get(this.data, 'entities'), {
hashtagUrlBase: `#/nav/${this.appCtrl.getRootNav().id}/search/%23`,
usernameUrlBase: `#/nav/${this.appCtrl.getRootNav().id}/profile/`,
});
}

goToProfile = (id, handle) => {
Expand All @@ -33,4 +42,12 @@ export class TweetComponent {
handle: this.data.user.screen_name,
});
};

retweet() {
return this.tweetProvider.retweet$(!this.data.retweeted, this.data.id_str).subscribe()
}

favorite() {
return this.tweetProvider.favorite$(!this.data.favorited, this.data.id_str).subscribe()
}
}
1 change: 0 additions & 1 deletion src/pages/feed/feed.html
Expand Up @@ -9,7 +9,6 @@
</ion-header>

<ion-content>

<feed
[content]="feed$ | async"
[isFetching]="fetching$ | async"
Expand Down
1 change: 1 addition & 0 deletions src/pages/feed/feed.ts
Expand Up @@ -70,6 +70,7 @@ export class FeedPage {
.first()
.subscribe((items: ITweet[]) => (currentLength = items.length));

console.log('loadMore', this.feedProvider.feedLength(), currentLength)
if (this.feedProvider.feedLength() > currentLength) {
this.nextPage();
infiniteScroll.complete();
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/home.html
Expand Up @@ -9,6 +9,6 @@
<ion-tab tabIcon="home" [root]="FeedPage"></ion-tab>
<ion-tab tabIcon="search" [root]="SearchTabPage"></ion-tab>
<ion-tab tabIcon="notifications" [root]="MentionsPage"></ion-tab>
<ion-tab tabIcon="chatboxes" [root]="MessagesPage"></ion-tab>
<ion-tab tabIcon="mail" [root]="MessagesPage"></ion-tab>
</ion-tabs>
</ion-content>
2 changes: 1 addition & 1 deletion src/pages/mentions/mentions.ts
Expand Up @@ -39,7 +39,7 @@ export class MentionsPage {
init() {
const hasFeed = this.mentionsProvider.hasFeed();
if (!hasFeed) {
console.log('init')
console.log('hasFeed', hasFeed)
this.mentionsProvider
.fetch$()
.first()
Expand Down
47 changes: 20 additions & 27 deletions src/providers/feed/feed.ts
Expand Up @@ -4,6 +4,7 @@ import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
import _get from 'lodash/get';
import _take from 'lodash/take';
import _without from 'lodash/without';

import { AppState, ITweet, IUsersState } from '../../reducers';
import { fetchFeed, fetchedFeed, errorFeed } from '../../actions';
Expand All @@ -27,55 +28,47 @@ export class FeedProvider {
return this.store.select(state => state.feed.fetching);
}

getFeed$(): Observable<ITweet[]> {
return Observable.combineLatest(
this.store.select(state => state.feed.list),
this.store.select(state => state.users),
(feed: ITweet[], users: IUsersState) =>
feed.map(feedItem => {
feedItem.user = _get(users, `[${feedItem.userHandle}]`);
return feedItem;
}),
);
getFeed$(): Observable<string[]> {
return this.store.select(state => state.feed.list);
}

getFeedPaginated$(
pageBSubject: BehaviorSubject<number>,
perPage: number = 10,
): Observable<ITweet[]> {
getFeedPaginated$(pageBSubject: BehaviorSubject<number>, perPage: number = 10, ): Observable<ITweet[]> {
return Observable.combineLatest(
this.store.select(state => state.feed.list),
this.store.select(state => state.tweets),
this.store.select(state => state.users),
pageBSubject,
(feed: ITweet[], users: IUsersState, page) =>
_take(feed, page * perPage).map(feedItem => {
feedItem.user = _get(users, `[${feedItem.userHandle}]`);
return feedItem;
}),
(feed: ITweet[], tweets: ITweet[], users: IUsersState, page) => _without(_take(feed, page * perPage)
.map(tweetId => {
const tweet = tweets[tweetId];
if (!tweet) return null;
tweet.user = _get(users, `[${tweet.userHandle}]`);
return tweet;
}), null)
);
}

getLastFeedItem(): ITweet {
let lastItem: ITweet;
getLastTweetId(): string {
let lastItem: string;
this.getFeed$()
.first()
.subscribe((items: ITweet[]) => (lastItem = items[items.length - 1]));
.subscribe((items: string[]) => (lastItem = items[items.length - 1]));
return lastItem;
}

hasFeed(): boolean {
let hasFeed: boolean;
this.getFeed$()
.first()
.subscribe((items: ITweet[]) => (hasFeed = items.length !== 0));
.subscribe((items: string[]) => (hasFeed = items.length !== 0));
return hasFeed;
}

feedLength(): number {
let feedLength: number;
this.getFeed$()
.first()
.subscribe((items: ITweet[]) => (feedLength = items.length));
.subscribe((items: string[]) => (feedLength = items.length));
return feedLength;
}

Expand All @@ -92,11 +85,11 @@ export class FeedProvider {
}

fetchNextPage$() {
const lastItem = this.getLastFeedItem();
if (!lastItem) return Observable.of(null);
const lastTweetId = this.getLastTweetId();
if (!lastTweetId) return Observable.of(null);
this.store.dispatch(fetchFeed());
return this.twitterProvider
.getFeed$({ max_id: lastItem.id, include_entities: true })
.getFeed$({ max_id: lastTweetId, include_entities: true })
.debounceTime(500)
.map(feed => this.store.dispatch(fetchedFeed(feed)))
.catch(error => {
Expand Down
1 change: 1 addition & 0 deletions src/providers/index.ts
Expand Up @@ -6,4 +6,5 @@ export * from './auth/auth';
export * from './trends/trends';
export * from './search/search';
export * from './mentions/mentions';
export * from './tweet/tweet';
export * from './service-worker/service-worker';

0 comments on commit e25831d

Please sign in to comment.