From 55debaba7c1224d12e9df119e632e313e37b331f Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Fri, 23 Sep 2022 11:09:51 -0700 Subject: [PATCH] rendering card items --- app/mobile/src/session/cards/Cards.jsx | 19 ++++-- app/mobile/src/session/cards/Cards.styled.js | 2 +- .../src/session/cards/cardItem/CardItem.jsx | 33 ++++++++- .../session/cards/cardItem/CardItem.styled.js | 61 +++++++++++++++++ .../cards/cardItem/useCardItem.hook.js | 17 +++++ app/mobile/src/session/cards/useCards.hook.js | 68 ++++++++++++++++++- app/mobile/src/session/channels/Channels.jsx | 6 +- .../src/session/channels/Channels.styled.js | 2 +- .../channels/channelItem/ChannelItem.jsx | 2 +- .../channelItem/ChannelItem.styled.js | 2 + .../src/session/channels/useChannels.hook.js | 25 ++++++- app/mobile/src/session/profile/Profile.jsx | 4 +- 12 files changed, 223 insertions(+), 18 deletions(-) create mode 100644 app/mobile/src/session/cards/cardItem/CardItem.styled.js create mode 100644 app/mobile/src/session/cards/cardItem/useCardItem.hook.js diff --git a/app/mobile/src/session/cards/Cards.jsx b/app/mobile/src/session/cards/Cards.jsx index 0ddcdade..c208bba6 100644 --- a/app/mobile/src/session/cards/Cards.jsx +++ b/app/mobile/src/session/cards/Cards.jsx @@ -13,13 +13,20 @@ export function Cards() { { state.tabbed && ( - - - + { state.sorting && ( + + + + )} + { !state.sorting && ( + + + + )} - - + + diff --git a/app/mobile/src/session/cards/Cards.styled.js b/app/mobile/src/session/cards/Cards.styled.js index 2e64d7b8..4f2e3991 100644 --- a/app/mobile/src/session/cards/Cards.styled.js +++ b/app/mobile/src/session/cards/Cards.styled.js @@ -48,7 +48,7 @@ export const styles = StyleSheet.create({ textAlign: 'center', padding: 4, color: Colors.text, - fontSize: 16, + fontSize: 14, }, icon: { paddingLeft: 8, diff --git a/app/mobile/src/session/cards/cardItem/CardItem.jsx b/app/mobile/src/session/cards/cardItem/CardItem.jsx index 69a9006b..8e6cdcd4 100644 --- a/app/mobile/src/session/cards/cardItem/CardItem.jsx +++ b/app/mobile/src/session/cards/cardItem/CardItem.jsx @@ -1,4 +1,35 @@ +import { Text, TouchableOpacity, View } from 'react-native'; +import { Logo } from 'utils/Logo'; +import { styles } from './CardItem.styled'; +import { useCardItem } from './useCardItem.hook'; + export function CardItem({ item }) { - return <>; + + const { state, actions } = useCardItem(item); + + return ( + + + + { item.name } + { item.handle } + + { item.status === 'connected' && ( + + )} + { item.status === 'requested' && ( + + )} + { item.status === 'connecting' && ( + + )} + { item.status === 'pending' && ( + + )} + { item.status === 'confirmed' && ( + + )} + + ); } diff --git a/app/mobile/src/session/cards/cardItem/CardItem.styled.js b/app/mobile/src/session/cards/cardItem/CardItem.styled.js new file mode 100644 index 00000000..fc3c6610 --- /dev/null +++ b/app/mobile/src/session/cards/cardItem/CardItem.styled.js @@ -0,0 +1,61 @@ +import { StyleSheet } from 'react-native'; +import { Colors } from 'constants/Colors'; + +export const styles = StyleSheet.create({ + container: { + width: '100%', + display: 'flex', + flexDirection: 'row', + height: 48, + alignItems: 'center', + borderBottomWidth: 1, + borderColor: Colors.itemDivider, + }, + detail: { + paddingLeft: 12, + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + flexGrow: 1, + flexShrink: 1, + }, + name: { + color: Colors.text, + fontSize: 14, + }, + handle: { + color: Colors.text, + fontSize: 12, + }, + connected: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.connected, + }, + requested: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.requested, + }, + connecting: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.connecting, + }, + pending: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.pending, + }, + confirmed: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.confirmed, + }, +}) + diff --git a/app/mobile/src/session/cards/cardItem/useCardItem.hook.js b/app/mobile/src/session/cards/cardItem/useCardItem.hook.js new file mode 100644 index 00000000..cb8796b5 --- /dev/null +++ b/app/mobile/src/session/cards/cardItem/useCardItem.hook.js @@ -0,0 +1,17 @@ +import { useState, useEffect, useRef, useContext } from 'react'; +import { useWindowDimensions } from 'react-native'; + +export function useCardItem(item) { + + const [state, setState] = useState({}); + + const updateState = (value) => { + setState((s) => ({ ...s, ...value })); + } + + const actions = { + }; + + return { state, actions }; +} + diff --git a/app/mobile/src/session/cards/useCards.hook.js b/app/mobile/src/session/cards/useCards.hook.js index c053cff1..0239f4d9 100644 --- a/app/mobile/src/session/cards/useCards.hook.js +++ b/app/mobile/src/session/cards/useCards.hook.js @@ -9,6 +9,8 @@ export function useCards() { const [state, setState] = useState({ tabbed: null, cards: [], + filter: null, + sorting: false, }); const dimensions = useWindowDimensions(); @@ -27,10 +29,74 @@ export function useCards() { } }, [dimensions]); + const setCardItem = (item) => { + const { profile, detail } = item; + + return { + cardId: item.cardId, + name: profile.name, + handle: `${profile.handle}@${profile.node}`, + status: detail.status, + updated: detail.statusUpdated, + logo: profile.imageSet ? card.actions.getCardLogo(item.cardId, profile.revision) : 'avatar', + } + }; + useEffect(() => { - }, [card]); + const cards = Array.from(card.state.cards.values()); + const items = cards.map(setCardItem); + const filtered = items.filter(item => { + if (!state.filter) { + return true; + } + const lower = state.filter.toLowerCase(); + if (item.name) { + if (item.name.toLowerCase().includes(lower)) { + return true; + } + } + if (item.handle) { + if (item.handle.toLowerCase().includes(lower)) { + return true; + } + } + return false; + }) + if (state.sorting) { + filtered.sort((a, b) => { + if (a.name === b.name) { + return 0; + } + if (!a.name || (a.name < b.name)) { + return -1; + } + return 1; + }); + } + else { + filtered.sort((a, b) => { + if (a.updated === b.updated) { + return 0; + } + if (!a.updated || (a.updated < b.updated)) { + return 1; + } + return -1; + }); + } + updateState({ cards: filtered }); + }, [card, state.filter, state.sorting]); const actions = { + setFilter: (filter) => { + updateState({ filter }); + }, + sort: () => { + updateState({ sorting: true }); + }, + unsort: () => { + updateState({ sorting: false }); + }, }; return { state, actions }; diff --git a/app/mobile/src/session/channels/Channels.jsx b/app/mobile/src/session/channels/Channels.jsx index 3b2c5c9d..6d9515d8 100644 --- a/app/mobile/src/session/channels/Channels.jsx +++ b/app/mobile/src/session/channels/Channels.jsx @@ -15,9 +15,9 @@ export function Channels() { <> - - + + diff --git a/app/mobile/src/session/channels/Channels.styled.js b/app/mobile/src/session/channels/Channels.styled.js index 58616e86..f414fe00 100644 --- a/app/mobile/src/session/channels/Channels.styled.js +++ b/app/mobile/src/session/channels/Channels.styled.js @@ -38,7 +38,7 @@ export const styles = StyleSheet.create({ textAlign: 'center', padding: 4, color: Colors.text, - fontSize: 16, + fontSize: 14, }, icon: { paddingLeft: 8, diff --git a/app/mobile/src/session/channels/channelItem/ChannelItem.jsx b/app/mobile/src/session/channels/channelItem/ChannelItem.jsx index a957aa35..7ab21cd6 100644 --- a/app/mobile/src/session/channels/channelItem/ChannelItem.jsx +++ b/app/mobile/src/session/channels/channelItem/ChannelItem.jsx @@ -9,7 +9,7 @@ export function ChannelItem({ item }) { return ( - + { item.subject } { item.message } diff --git a/app/mobile/src/session/channels/channelItem/ChannelItem.styled.js b/app/mobile/src/session/channels/channelItem/ChannelItem.styled.js index ac7682c1..72057e87 100644 --- a/app/mobile/src/session/channels/channelItem/ChannelItem.styled.js +++ b/app/mobile/src/session/channels/channelItem/ChannelItem.styled.js @@ -21,9 +21,11 @@ export const styles = StyleSheet.create({ }, subject: { color: Colors.text, + fontSize: 14, }, message: { color: Colors.disabled, + fontSize: 12, }, dot: { width: 8, diff --git a/app/mobile/src/session/channels/useChannels.hook.js b/app/mobile/src/session/channels/useChannels.hook.js index dda4bf24..bca44a31 100644 --- a/app/mobile/src/session/channels/useChannels.hook.js +++ b/app/mobile/src/session/channels/useChannels.hook.js @@ -13,6 +13,7 @@ export function useChannels() { topic: null, channels: [], tabbed: null, + filter: null, }); const items = useRef([]); @@ -133,7 +134,22 @@ export function useChannels() { }); merged.push(...Array.from(channel.state.channels.values())); - merged.sort((a, b) => { + const items = merged.map(setChannelEntry); + + const filtered = items.filter(item => { + if (!state.filter) { + return true; + } + const lower = state.filter.toLowerCase(); + if (item.subject) { + if (item.subject.toLowerCase().includes(lower)) { + return true; + } + } + return false; + }); + + const sorted = filtered.sort((a, b) => { const aCreated = a?.summary?.lastTopic?.created; const bCreated = b?.summary?.lastTopic?.created; if (aCreated === bCreated) { @@ -145,13 +161,16 @@ export function useChannels() { return -1; }); - updateState({ channels: merged.map(item => setChannelEntry(item)) }); - }, [channel, card]); + updateState({ channels: sorted }); + }, [channel, card, state.filter]); const actions = { setTopic: (topic) => { updateState({ topic }); }, + setFilter: (filter) => { + updateState({ filter }); + }, }; return { state, actions }; diff --git a/app/mobile/src/session/profile/Profile.jsx b/app/mobile/src/session/profile/Profile.jsx index 23aac9c6..d9a969d0 100644 --- a/app/mobile/src/session/profile/Profile.jsx +++ b/app/mobile/src/session/profile/Profile.jsx @@ -107,7 +107,9 @@ export function Profile() { - Visible in Registry + setVisible(!state.searchable)} activeOpacity={1}> + Visible in Registry +