Verified Commit 07cb4b35 authored by staltz's avatar staltz

Click an account in the Accounts screen to go to Profile

parent e8c3e9c5
......@@ -4,14 +4,15 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import {Component} from 'react';
import {PureComponent} from 'react';
import {h} from '@cycle/react';
import {Text, View, TouchableNativeFeedback, StyleSheet} from 'react-native';
import {Msg} from 'ssb-typescript';
import {FeedId} from 'ssb-typescript';
import {Dimensions} from '../global-styles/dimens';
import {Palette} from '../global-styles/palette';
import {Typography} from '../global-styles/typography';
import Avatar from './Avatar';
import React = require('react');
export const styles = StyleSheet.create({
row: {
......@@ -56,35 +57,19 @@ export const styles = StyleSheet.create({
},
});
export type Props = {
type AccountProps = {
name: string;
imageUrl: string;
imageUrl?: string;
id: string;
onPress?: (ev: {msg: Msg}) => void;
onPress?: () => void;
};
export default class ListItemAccounts extends Component<Props> {
// private _onPress() {
// const {onPress} = this.props;
// if (onPress) {
// onPress({msg});
// }
// }
public shouldComponentUpdate(nextProps: Props) {
const prevProps = this.props;
return (
nextProps.id !== prevProps.id ||
nextProps.name !== prevProps.name ||
nextProps.imageUrl !== prevProps.imageUrl
);
}
class Account extends PureComponent<AccountProps> {
public render() {
const {name, imageUrl} = this.props;
const {name, imageUrl, onPress} = this.props;
const touchableProps = {
background: TouchableNativeFeedback.SelectableBackground(),
// onPress: () => this._onPress(),
onPress,
};
const authorNameText = h(
......@@ -111,3 +96,25 @@ export default class ListItemAccounts extends Component<Props> {
]);
}
}
export type Props = {
accounts: Array<{name: string; imageUrl: string; id: string}>;
onPressAccount?: (ev: {id: FeedId}) => void;
};
export default class AccountsList extends PureComponent<Props> {
public render() {
const {onPressAccount} = this.props;
return h(
React.Fragment,
this.props.accounts.map(({id, name, imageUrl}) =>
h<AccountProps>(Account, {
name,
imageUrl,
id,
onPress: () => onPressAccount && onPressAccount({id}),
}),
),
);
}
}
......@@ -395,11 +395,11 @@ export class SSBSource {
);
}
public liteAbout$(ids: Array<FeedId>): Stream<Array<About>> {
public liteAbout$(ids: Array<FeedId>): Stream<Array<AboutAndExtras>> {
return this.api$
.map(async api => {
const aboutSocialValue = api.sbot.async.aboutSocialValue[0];
const abouts: Array<About> = [];
const abouts: Array<AboutAndExtras> = [];
for (const id of ids) {
// Fetch name
const [, result1] = await runAsync<string>(aboutSocialValue)({
......
......@@ -5,27 +5,25 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import xs, {Stream} from 'xstream';
import {
Command,
PopCommand,
NavSource,
PushCommand,
} from 'cycle-native-navigation';
import {Msg, MsgId, About} from 'ssb-typescript';
import sampleCombine from 'xstream/extra/sampleCombine';
import {Command, PopCommand, NavSource} from 'cycle-native-navigation';
import {MsgId, About, FeedId} from 'ssb-typescript';
import {SSBSource, Likes} from '../../drivers/ssb';
import {ReactSource, h} from '@cycle/react';
import {ReactElement} from 'react';
import {Dimensions} from '../../global-styles/dimens';
import {navOptions as rawMessageScreenNavOptions} from '../raw-msg';
import {navOptions as profileScreenNavOptions} from '../profile';
import {Screens} from '../..';
import {StyleSheet, ScrollView, RefreshControl} from 'react-native';
import {Reducer, StateSource} from '@cycle/state';
import ListItemAccount, {
Props as ListProps,
} from '../../components/ListItemAccount';
import AccountsList, {Props as ListProps} from '../../components/AccountsList';
import {Palette} from '../../global-styles/palette';
export type Props = {msgKey: MsgId; likes: Likes};
export type Props = {
selfFeedId: FeedId;
msgKey: MsgId;
likes: Likes;
};
export type Sources = {
props: Stream<Props>;
......@@ -43,6 +41,7 @@ export type Sinks = {
export type State = {
likers: Array<About>;
selfFeedId: FeedId;
};
export const styles = StyleSheet.create({
......@@ -69,36 +68,39 @@ export const navOptions = {
export type Actions = {
goBack$: Stream<any>;
goToRawMsg$: Stream<Msg>;
goToProfile$: Stream<{id: FeedId}>;
};
function navigation(actions: Actions) {
function navigation(actions: Actions, state$: Stream<State>) {
const pop$ = actions.goBack$.mapTo({
type: 'pop',
} as PopCommand);
const toRawMsg$ = actions.goToRawMsg$.map(
msg =>
const toProfile$ = actions.goToProfile$.compose(sampleCombine(state$)).map(
([ev, state]) =>
({
type: 'push',
layout: {
component: {
name: Screens.RawMessage,
passProps: {msg},
options: rawMessageScreenNavOptions,
name: Screens.Profile,
passProps: {
selfFeedId: state.selfFeedId,
feedId: ev.id,
},
options: profileScreenNavOptions,
},
},
} as PushCommand),
} as Command),
);
return xs.merge(pop$, toRawMsg$);
return xs.merge(pop$, toProfile$);
}
function intent(navSource: NavSource, reactSource: ReactSource) {
return {
goBack$: navSource.backPress(),
goToRawMsg$: reactSource.select('accounts').events('pressMsg'),
goToProfile$: reactSource.select('accounts').events('pressAccount'),
};
}
......@@ -117,35 +119,34 @@ export function accounts(sources: Sources): Sinks {
colors: [Palette.backgroundBrand],
}),
},
likers.map(like => {
return h(ListItemAccount, {
name: like.name,
imageUrl: like.imageUrl,
id: like.id,
// onPress: onPressMsg
} as ListProps);
}),
[h(AccountsList, {sel: 'accounts', accounts: likers} as ListProps)],
);
});
const command$ = navigation(actions);
const command$ = navigation(actions, sources.state.stream);
const initialReducer$ = xs.of(function initialReducer(prev: State): State {
if (prev) return prev;
else return {likers: []};
});
const propsReducer$ = sources.props.map(
props =>
function propsReducer(prev?: State): State {
if (prev) {
return {...prev, selfFeedId: props.selfFeedId};
} else {
return {likers: [], selfFeedId: props.selfFeedId};
}
},
);
const aboutsReducer$ = sources.props
.filter(props => !!props.likes)
.map(props => sources.ssb.liteAbout$(props.likes!))
.flatten()
.map(abouts => {
return function propsReducer(): State {
return {likers: abouts};
return function propsReducer(prev: State): State {
return {...prev, likers: abouts};
};
});
const reducer$ = xs.merge(initialReducer$, aboutsReducer$);
const reducer$ = xs.merge(propsReducer$, aboutsReducer$);
return {
screen: vdom$,
......
......@@ -42,14 +42,17 @@ export default function navigation(
} as Command),
);
const toAccounts$ = actions.goToAccounts$.map(
props =>
const toAccounts$ = actions.goToAccounts$.compose(sampleCombine(state$)).map(
([ev, state]) =>
({
type: 'push',
layout: {
component: {
name: Screens.Accounts,
passProps: props,
passProps: {
...ev,
selfFeedId: state.selfFeedId,
},
options: accountsScreenNavOptions,
},
},
......
......@@ -81,14 +81,17 @@ export default function navigation(
} as Command),
);
const toAccounts$ = actions.goToAccounts$.map(
props =>
const toAccounts$ = actions.goToAccounts$.compose(sampleCombine(state$)).map(
([ev, state]) =>
({
type: 'push',
layout: {
component: {
name: Screens.Accounts,
passProps: props,
passProps: {
...ev,
selfFeedId: state.selfFeedId,
},
options: accountsScreenNavOptions,
},
},
......
......@@ -26,14 +26,17 @@ export default function navigation(
navSource: NavSource,
state$: Stream<State>,
): Stream<Command> {
const toAccounts$ = actions.goToAccounts$.map(
props =>
const toAccounts$ = actions.goToAccounts$.compose(sampleCombine(state$)).map(
([ev, state]) =>
({
type: 'push',
layout: {
component: {
name: Screens.Accounts,
passProps: props,
passProps: {
...ev,
selfFeedId: state.selfFeedId,
},
options: accountsScreenNavOptions,
},
},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment