refactoring profile screen

This commit is contained in:
Roland Osborne 2023-02-22 13:16:31 -08:00
parent afc8c45721
commit d7ea1806c1
7 changed files with 124 additions and 63 deletions

View File

@ -0,0 +1,20 @@
export function getCardByGuid(cards, guid) {
let card = null;
cards.forEach((value, key, map) => {
if(value?.data?.cardProfile?.guid === guid) {
card = value;
}
});
return card;
}
export function getProfileByGuid(cards, guid) {
const card = getCardByGuid(cards, guid);
if (card?.data?.cardProfile) {
const { name, handle, imageSet, node } = card.data.cardProfile;
const cardId = card.id;
return { cardId, name, handle, imageSet, node }
}
return {};
}

View File

@ -191,23 +191,24 @@ export function ProfileBody() {
</TouchableOpacity> </TouchableOpacity>
<Switch style={styles.enableSwitch} value={state.pushEnabled} onValueChange={setNotifications} trackColor={styles.switch}/> <Switch style={styles.enableSwitch} value={state.pushEnabled} onValueChange={setNotifications} trackColor={styles.switch}/>
</View> </View>
{ state.sealable && (
<TouchableOpacity style={styles.link} onPress={actions.showSealEdit}> <TouchableOpacity style={styles.logout} activeOpacity={1} onPress={logout}>
<Ionicons name="setting" size={14} color={Colors.primary} /> <Ionicons name="logout" size={14} color={Colors.primary} />
<Text style={styles.linkText}>Sealed Topics</Text> <Text style={styles.logoutText}>Logout</Text>
</TouchableOpacity> </TouchableOpacity>
)}
<TouchableOpacity style={styles.logout} onPress={actions.showLoginEdit}> <TouchableOpacity style={styles.logout} onPress={actions.showLoginEdit}>
<Ionicons name="lock" size={16} color={Colors.primary} /> <Ionicons name="lock" size={16} color={Colors.primary} />
<Text style={styles.logoutText}>Change Login</Text> <Text style={styles.logoutText}>Change Login</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={styles.logout} activeOpacity={1} onPress={logout}>
<Ionicons name="logout" size={16} color={Colors.primary} />
<Text style={styles.logoutText}>Logout</Text>
</TouchableOpacity>
{ state.sealable && (
<TouchableOpacity style={styles.logout} onPress={actions.showEditSeal}>
<Ionicons name="setting" size={14} color={Colors.primary} />
<Text style={styles.logoutText}>Sealed Topics</Text>
</TouchableOpacity>
)}
<TouchableOpacity style={styles.delete} activeOpacity={1} onPress={actions.showDelete}> <TouchableOpacity style={styles.delete} activeOpacity={1} onPress={actions.showDelete}>
<Ionicons name="delete" size={16} color={Colors.alert} /> <Ionicons name="delete" size={16} color={Colors.alert} />
<Text style={styles.deleteText}>Delete Account</Text> <Text style={styles.deleteText}>Delete Account</Text>
@ -369,7 +370,7 @@ export function ProfileBody() {
<TouchableOpacity onPress={() => actions.setSealable(!state.sealable)} activeOpacity={1}> <TouchableOpacity onPress={() => actions.setSealable(!state.sealable)} activeOpacity={1}>
<Text style={styles.sealableText}>Enable Sealed Topics</Text> <Text style={styles.sealableText}>Enable Sealed Topics</Text>
</TouchableOpacity> </TouchableOpacity>
<Switch style={styles.sealableSwitch} value={state.sealable} onValueChange={actions.setSealable} trackColor={styles.switch}/> <Switch style={styles.enableSwitch} value={state.sealable} onValueChange={actions.setSealable} trackColor={styles.switch}/>
</View> </View>
{ state.sealMode === 'unlocking' && ( { state.sealMode === 'unlocking' && (
<> <>

View File

@ -31,7 +31,7 @@ export const styles = StyleSheet.create({
color: Colors.alert, color: Colors.alert,
}, },
logout: { logout: {
marginTop: 16, marginTop: 8,
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
@ -43,7 +43,7 @@ export const styles = StyleSheet.create({
color: Colors.primary, color: Colors.primary,
}, },
delete: { delete: {
marginTop: 16, marginTop: 8,
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
@ -213,6 +213,7 @@ export const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
width: '100%', width: '100%',
marginTop: 8,
}, },
enableText: { enableText: {
color: Colors.primary, color: Colors.primary,

View File

@ -40,11 +40,11 @@ export function useBlockedContacts() {
return 1; return 1;
}); });
updateState({ cards: filtered }); updateState({ cards: filtered });
}, [card]); }, [card.state]);
const actions = { const actions = {
unblock: async (cardId) => { unblock: async (cardId) => {
await card.actions.clearCardBlocked(cardId); await card.actions.clearCardFlag(cardId);
} }
}; };

View File

@ -3,7 +3,7 @@ import { StoreContext } from 'context/StoreContext';
import { ChannelContext } from 'context/ChannelContext'; import { ChannelContext } from 'context/ChannelContext';
import { CardContext } from 'context/CardContext'; import { CardContext } from 'context/CardContext';
import { ProfileContext } from 'context/ProfileContext'; import { ProfileContext } from 'context/ProfileContext';
import { ConversationContext } from 'context/ConversationContext'; import { getCardByGuid } from 'context/cardUtil';
import moment from 'moment'; import moment from 'moment';
export function useBlockedMessages() { export function useBlockedMessages() {
@ -16,15 +16,14 @@ export function useBlockedMessages() {
const card = useContext(CardContext); const card = useContext(CardContext);
const channel = useContext(ChannelContext); const channel = useContext(ChannelContext);
const profile = useContext(ProfileContext); const profile = useContext(ProfileContext);
const conversation = useContext(ConversationContext);
const updateState = (value) => { const updateState = (value) => {
setState((s) => ({ ...s, ...value })); setState((s) => ({ ...s, ...value }));
} }
const setItem = (item) => { const setTopicItem = (cardId, channelId, topic) => {
let name, nameSet let name, nameSet
if (item.detail.guid === profile.state.identity.guid) { if (topic.detail.guid === profile.state.identity.guid) {
const identity = profile.state.identity; const identity = profile.state.identity;
if (identity.name) { if (identity.name) {
name = identity.name; name = identity.name;
@ -35,13 +34,13 @@ export function useBlockedMessages() {
nameSet = true; nameSet = true;
} }
else { else {
const contact = card.actions.getByGuid(item.detail.guid); const contact = getCardByGuid(card.state.cards, topic.detail.guid);
if (contact) { if (contact) {
if (contact?.profile?.name) { if (contact?.card?.profile?.name) {
name = contact.profile.name; name = contact.card.profile.name;
} }
else { else {
name = `${contact.profile.handle}@${contact.profile.node}`; name = `${contact.card.profile.handle}@${contact.card.profile.node}`;
} }
nameSet = true; nameSet = true;
} }
@ -52,7 +51,7 @@ export function useBlockedMessages() {
} }
let timestamp; let timestamp;
const date = new Date(item.detail.created * 1000); const date = new Date(topic.detail.created * 1000);
const now = new Date(); const now = new Date();
const offset = now.getTime() - date.getTime(); const offset = now.getTime() - date.getTime();
if(offset < 86400000) { if(offset < 86400000) {
@ -65,28 +64,54 @@ export function useBlockedMessages() {
timestamp = moment(date).format('M/DD/YYYY'); timestamp = moment(date).format('M/DD/YYYY');
} }
const { cardId, channelId, topicId } = item; const { topicId } = topic;
return { name, nameSet, timestamp, cardId, channelId, topicId, id: `${cardId}:${channelId}:${topicId}` }; return { name, nameSet, timestamp, cardId, channelId, topicId, id: `${cardId}:${channelId}:${topicId}` };
}; };
const loadBlocked = async () => { const loadBlocked = async () => {
//TODO const channels = [];
} channel.state.channels.forEach((channelItem, channelId, map) => {
channels.push({ channelId });
});
card.state.cards.forEach((cardItem, cardId, map) => {
cardItem.channels.forEach((channelItem, channelId, map) => {
channels.push({ cardId, channelId });
});
});
for(let i = 0; i < channels.length; i++) {
const merged = [];
let topics;
const { cardId, channelId } = channels[i];
if (cardId) {
topics = await card.actions.getTopicItems(cardId, channelId);
}
else {
topics = await channel.actions.getTopicItems(channelId);
}
topics.forEach((topic) => {
if (topic.blocked) {
merged.push(setTopicItem(cardId, channelId, topic));
}
});
}
updateState({ messages: merged });
};
useEffect(() => { useEffect(() => {
loadBlocked(); loadBlocked();
}, []); }, []);
const actions = { const actions = {
unblock: async (cardId, channelId, topicId) => { unblock: async (cardId, channelId, topicId) => {
const id = `${cardId}:${channelId}:${topicId}`; const id = `${cardId}:${channelId}:${topicId}`;
if (cardId) { if (cardId) {
card.actions.clearChannelTopicBlocked(cardId, channelId, topicId); card.actions.clearChannelTopicFlag(cardId, channelId, topicId);
} }
else { else {
channel.actions.clearTopicBlocked(channelId, topicId); channel.actions.clearTopicFlag(channelId, topicId);
} }
conversation.actions.unblockTopic(cardId, channelId, topicId);
updateState({ messages: state.messages.filter(item => item.id !== id) }); updateState({ messages: state.messages.filter(item => item.id !== id) });
} }
}; };

View File

@ -2,6 +2,7 @@ import { useState, useEffect, useContext } from 'react';
import { CardContext } from 'context/CardContext'; import { CardContext } from 'context/CardContext';
import { ChannelContext } from 'context/ChannelContext'; import { ChannelContext } from 'context/ChannelContext';
import { ProfileContext } from 'context/ProfileContext'; import { ProfileContext } from 'context/ProfileContext';
import { getCardByGuid } from 'context/cardUtil';
import moment from 'moment'; import moment from 'moment';
export function useBlockedTopics() { export function useBlockedTopics() {
@ -30,7 +31,7 @@ export function useBlockedTopics() {
const setChannelItem = (item) => { const setChannelItem = (item) => {
let timestamp; let timestamp;
const date = new Date(item.detail.created * 1000); const date = new Date(item.channel.detail.created * 1000);
const now = new Date(); const now = new Date();
const offset = now.getTime() - date.getTime(); const offset = now.getTime() - date.getTime();
if(offset < 86400000) { if(offset < 86400000) {
@ -43,20 +44,6 @@ export function useBlockedTopics() {
timestamp = moment(date).format('M/DD/YYYY'); timestamp = moment(date).format('M/DD/YYYY');
} }
let contacts = [];
if (item.cardId) {
contacts.push(card.state.cards.get(item.cardId));
}
if (item?.detail?.members) {
const profileGuid = profile.state.identity.guid;
item.detail.members.forEach(guid => {
if (profileGuid !== guid) {
const contact = getCard(guid);
contacts.push(contact);
}
})
}
let subject; let subject;
if (item?.detail?.data) { if (item?.detail?.data) {
try { try {
@ -68,14 +55,28 @@ export function useBlockedTopics() {
} }
} }
if (!subject) { if (!subject) {
let contacts = [];
if (item.cardId) {
contacts.push(card.state.cards.get(item.cardId));
}
if (item.channel.detail?.members) {
const profileGuid = profile.state.identity.guid;
item.channel.detail.members.forEach(guid => {
if (profileGuid !== guid) {
const contact = getCardByGuid(card.state.cards, guid);
contacts.push(contact);
}
})
}
if (contacts.length) { if (contacts.length) {
let names = []; let names = [];
for (let contact of contacts) { for (let contact of contacts) {
if (contact?.profile?.name) { if (contact?.card?.profile?.name) {
names.push(contact.profile.name); names.push(contact.card.profile.name);
} }
else if (contact?.profile?.handle) { else if (contact?.card?.profile?.handle) {
names.push(contact?.profile?.handle); names.push(contact.card.profile.handle);
} }
} }
subject = names.join(', '); subject = names.join(', ');
@ -86,33 +87,39 @@ export function useBlockedTopics() {
} }
return { return {
id: `${item.cardId}:${item.channelId}`, id: `${item.cardId}:${item.channel.channelId}`,
cardId: item.cardId, cardId: item.cardId,
channelId: item.channelId, channelId: item.channel.channelId,
name: subject, name: subject,
blocked: item.blocked,
created: timestamp, created: timestamp,
} }
}; };
useEffect(() => { useEffect(() => {
let merged = []; let merged = [];
card.state.cards.forEach((card, cardId, map) => { card.state.cards.forEach((cardItem, cardId, map) => {
merged.push(...Array.from(card.channels.values())); cardItem.channels.forEach((channelItem) => {
if (channelItem.blocked) {
merged.push({ cardId, channel: channelItem });
}
});
});
channel.state.channels.forEach((channelItem, channelId, map) => {
if (channelItem.blocked) {
marged.push({ channel: channelItem });
}
}); });
merged.push(...Array.from(channel.state.channels.values()));
const items = merged.map(setChannelItem); const items = merged.map(setChannelItem);
const filtered = items.filter(item => item.blocked); updateState({ channels: items });
updateState({ channels: filtered }); }, [card.state, channel.state]);
}, [card, channel]);
const actions = { const actions = {
unblock: async (cardId, channelId) => { unblock: async (cardId, channelId) => {
if (cardId) { if (cardId) {
await card.actions.clearChannelBlocked(cardId, channelId); await card.actions.clearChannelFlag(cardId, channelId);
} }
else { else {
await channel.actions.clearBlocked(channelId); await channel.actions.clearChannelFlag(channelId);
} }
} }
}; };

View File

@ -1,6 +1,7 @@
import { useState, useEffect, useRef, useContext } from 'react'; import { useState, useEffect, useRef, useContext } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { ProfileContext } from 'context/ProfileContext'; import { ProfileContext } from 'context/ProfileContext';
import { AccountContext } from 'context/AccountContext';
import { AppContext } from 'context/AppContext'; import { AppContext } from 'context/AppContext';
export function useProfile() { export function useProfile() {
@ -27,6 +28,7 @@ export function useProfile() {
}); });
const app = useContext(AppContext); const app = useContext(AppContext);
const account = useContext(AccountContext);
const profile = useContext(ProfileContext); const profile = useContext(ProfileContext);
const navigate = useNavigate(); const navigate = useNavigate();
@ -39,7 +41,12 @@ export function useProfile() {
const imageSource = image ? profile.state.imageUrl : 'avatar'; const imageSource = image ? profile.state.imageUrl : 'avatar';
updateState({ name, handle, node, location, description, imageSource, editHandle: handle, updateState({ name, handle, node, location, description, imageSource, editHandle: handle,
editName: name, editLocation: location, editDescription: description }); editName: name, editLocation: location, editDescription: description });
}, [profile]); }, [profile.state]);
useEffect(() => {
const { sealable } = account.state.status || {};
updateState({ sealable });
}, [account.state]);
useEffect(() => { useEffect(() => {
const { loggingOut, status } = app.state; const { loggingOut, status } = app.state;