mirror of
https://github.com/balzack/databag.git
synced 2025-02-14 12:39:17 +00:00
supporting blocking contacts
This commit is contained in:
parent
d3782750ea
commit
87da47a00d
@ -21,7 +21,7 @@ export const Colors = {
|
||||
|
||||
itemDivider: '#eeeeee',
|
||||
|
||||
connected: '#44cc44',
|
||||
connected: '#4488FF',
|
||||
connecting: '#dd88ff',
|
||||
requested: '#4488ff',
|
||||
pending: '#22aaaa',
|
||||
|
@ -84,6 +84,13 @@ export function useCardContext() {
|
||||
cards.current.set(cardId, card);
|
||||
}
|
||||
}
|
||||
const setCardBlocked = (cardId, blocked) => {
|
||||
let card = cards.current.get(cardId);
|
||||
if (card) {
|
||||
card.blocked = blocked;
|
||||
cards.current.set(cardId, card);
|
||||
}
|
||||
}
|
||||
const clearCardChannels = (cardId) => {
|
||||
let card = cards.current.get(cardId);
|
||||
if (card) {
|
||||
@ -385,6 +392,18 @@ export function useCardContext() {
|
||||
setCardCloseMessage: async (server, message) => {
|
||||
return await setCardCloseMessage(server, message);
|
||||
},
|
||||
setCardBlocked: async (cardId) => {
|
||||
const { guid } = session.current;
|
||||
setCardBlocked(cardId, true);
|
||||
await store.actions.setCardItemBlocked(guid, cardId);
|
||||
updateState({ cards: cards.current });
|
||||
},
|
||||
clearCardBlocked: async (cardId) => {
|
||||
const { guid } = session.current;
|
||||
setCardBlocked(cardId, false);
|
||||
await store.actions.clearCardItemBlocked(guid, cardId);
|
||||
updateState({ cards: cards.current });
|
||||
}
|
||||
}
|
||||
|
||||
return { state, actions }
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useEffect, useState, useRef, useContext } from 'react';
|
||||
import SQLite from "react-native-sqlite-storage";
|
||||
|
||||
const DATABAG_DB = 'databag_v033.db';
|
||||
const DATABAG_DB = 'databag_v034.db';
|
||||
|
||||
export function useStoreContext() {
|
||||
const [state, setState] = useState({});
|
||||
@ -14,8 +14,8 @@ export function useStoreContext() {
|
||||
const initSession = async (guid) => {
|
||||
await db.current.executeSql(`CREATE TABLE IF NOT EXISTS channel_${guid} (channel_id text, revision integer, detail_revision integer, topic_revision integer, detail text, summary text, offsync integer, read_revision integer, unique(channel_id))`);
|
||||
await db.current.executeSql(`CREATE TABLE IF NOT EXISTS channel_topic_${guid} (channel_id text, topic_id text, revision integer, detail_revision integer, detail text, unique(channel_id, topic_id))`);
|
||||
await db.current.executeSql(`CREATE TABLE IF NOT EXISTS card_${guid} (card_id text, revision integer, detail_revision integer, profile_revision integer, detail text, profile text, notified_view integer, notified_article integer, notified_profile integer, notified_channel integer, offsync integer, unique(card_id))`);
|
||||
await db.current.executeSql(`CREATE TABLE IF NOT EXISTS card_channel_${guid} (card_id text, channel_id text, revision integer, detail_revision integer, topic_revision integer, detail text, summary text, offsync integer, read_revision integer, unique(card_id, channel_id))`);
|
||||
await db.current.executeSql(`CREATE TABLE IF NOT EXISTS card_${guid} (card_id text, revision integer, detail_revision integer, profile_revision integer, detail text, profile text, notified_view integer, notified_article integer, notified_profile integer, notified_channel integer, offsync integer, blocked integer, unique(card_id))`);
|
||||
await db.current.executeSql(`CREATE TABLE IF NOT EXISTS card_channel_${guid} (card_id text, channel_id text, revision integer, detail_revision integer, topic_revision integer, detail text, summary text, offsync integer, blocked integer, read_revision integer, unique(card_id, channel_id))`);
|
||||
await db.current.executeSql(`CREATE TABLE IF NOT EXISTS card_channel_topic_${guid} (card_id text, channel_id text, topic_id text, revision integer, detail_revision integer, detail text, unique(card_id, channel_id, topic_id))`);
|
||||
}
|
||||
|
||||
@ -106,6 +106,12 @@ export function useStoreContext() {
|
||||
clearCardItemOffsync: async (guid, cardId) => {
|
||||
await db.current.executeSql(`UPDATE card_${guid} set offsync=? where card_id=?`, [0, cardId]);
|
||||
},
|
||||
setCardItemBlocked: async (guid, cardId) => {
|
||||
await db.current.executeSql(`UPDATE card_${guid} set blocked=? where card_id=?`, [1, cardId]);
|
||||
},
|
||||
clearCardItemBlocked: async (guid, cardId) => {
|
||||
await db.current.executeSql(`UPDATE card_${guid} set blocked=? where card_id=?`, [0, cardId]);
|
||||
},
|
||||
setCardItemDetail: async (guid, cardId, revision, detail) => {
|
||||
await db.current.executeSql(`UPDATE card_${guid} set detail_revision=?, detail=? where card_id=?`, [revision, encodeObject(detail), cardId]);
|
||||
},
|
||||
@ -127,6 +133,7 @@ export function useStoreContext() {
|
||||
notifiedProfile: values[0].notified_profile,
|
||||
notifiedChannel: values[0].notified_channel,
|
||||
offsync: values[0].offsync,
|
||||
blocked: values[0].blocked,
|
||||
};
|
||||
},
|
||||
getCardItemView: async (guid, cardId) => {
|
||||
@ -141,7 +148,7 @@ export function useStoreContext() {
|
||||
};
|
||||
},
|
||||
getCardItems: async (guid) => {
|
||||
const values = await getAppValues(db.current, `SELECT card_id, revision, detail_revision, profile_revision, detail, profile, notified_view, notified_profile, notified_article, notified_channel FROM card_${guid}`, []);
|
||||
const values = await getAppValues(db.current, `SELECT card_id, revision, detail_revision, profile_revision, detail, profile, offsync, blocked, notified_view, notified_profile, notified_article, notified_channel FROM card_${guid}`, []);
|
||||
return values.map(card => ({
|
||||
cardId: card.card_id,
|
||||
revision: card.revision,
|
||||
@ -153,6 +160,8 @@ export function useStoreContext() {
|
||||
notifiedProfile: card.notified_profile,
|
||||
notifiedArticle: card.notified_article,
|
||||
notifiedChannel: card.notified_channel,
|
||||
offsync: card.offsync,
|
||||
blocked: card.blocked,
|
||||
}));
|
||||
},
|
||||
|
||||
@ -238,7 +247,7 @@ export function useStoreContext() {
|
||||
};
|
||||
},
|
||||
getCardChannelItems: async (guid) => {
|
||||
const values = await getAppValues(db.current, `SELECT card_id, channel_id, read_revision, revision, detail_revision, topic_revision, detail, summary FROM card_channel_${guid}`, []);
|
||||
const values = await getAppValues(db.current, `SELECT card_id, channel_id, read_revision, revision, blocked, detail_revision, topic_revision, detail, summary FROM card_channel_${guid}`, []);
|
||||
return values.map(channel => ({
|
||||
cardId: channel.card_id,
|
||||
channelId: channel.channel_id,
|
||||
@ -248,6 +257,7 @@ export function useStoreContext() {
|
||||
topicRevision: channel.topic_revision,
|
||||
detail: decodeObject(channel.detail),
|
||||
summary: decodeObject(channel.summary),
|
||||
blocked: channel.blocked,
|
||||
}));
|
||||
},
|
||||
clearCardChannelItems: async (guid, cardId) => {
|
||||
|
@ -21,7 +21,7 @@ export function CardItem({ item, openContact }) {
|
||||
<Text style={styles.handle} numberOfLines={1} ellipsizeMode={'tail'}>{ item.handle }</Text>
|
||||
</View>
|
||||
{ item.status === 'connected' && (
|
||||
<View style={styles.confirmed} />
|
||||
<View style={styles.connected} />
|
||||
)}
|
||||
{ item.status === 'requested' && (
|
||||
<View style={styles.requested} />
|
||||
|
@ -37,6 +37,8 @@ export function useCards() {
|
||||
name: profile.name,
|
||||
handle: `${profile.handle}@${profile.node}`,
|
||||
status: detail.status,
|
||||
offsync: item.offsync,
|
||||
blocked: item.blocked,
|
||||
updated: detail.statusUpdated,
|
||||
logo: profile.imageSet ? card.actions.getCardLogo(item.cardId, profile.revision) : 'avatar',
|
||||
}
|
||||
@ -47,7 +49,7 @@ export function useCards() {
|
||||
const items = cards.map(setCardItem);
|
||||
const filtered = items.filter(item => {
|
||||
if (!state.filter) {
|
||||
return true;
|
||||
return !item.blocked;
|
||||
}
|
||||
const lower = state.filter.toLowerCase();
|
||||
if (item.name) {
|
||||
|
@ -130,7 +130,9 @@ export function useChannels() {
|
||||
useEffect(() => {
|
||||
let merged = [];
|
||||
card.state.cards.forEach((card, cardId, map) => {
|
||||
merged.push(...Array.from(card.channels.values()));
|
||||
if (!card.blocked) {
|
||||
merged.push(...Array.from(card.channels.values()));
|
||||
}
|
||||
});
|
||||
merged.push(...Array.from(channel.state.channels.values()));
|
||||
|
||||
|
@ -232,9 +232,6 @@ export function Contact({ contact, closeContact }) {
|
||||
<TouchableOpacity style={styles.button} onPress={saveContact}>
|
||||
<Text style={styles.buttonText}>Save Contact</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.button} onPress={blockContact}>
|
||||
<Text style={styles.buttonText}>Block Contact</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
|
@ -154,7 +154,12 @@ export function useContact(contact, close) {
|
||||
}
|
||||
});
|
||||
},
|
||||
blockContact: async () => {},
|
||||
blockContact: async () => {
|
||||
await applyAction(async () => {
|
||||
await card.actions.setCardBlocked(state.cardId);
|
||||
close();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
|
@ -7,6 +7,8 @@ import Ionicons from '@expo/vector-icons/AntDesign';
|
||||
import Colors from 'constants/Colors';
|
||||
import ImagePicker from 'react-native-image-crop-picker'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { BlockedTopics } from './blockedTopics/BlockedTopics';
|
||||
import { BlockedContacts } from './blockedContacts/BlockedContacts';
|
||||
|
||||
export function Profile() {
|
||||
|
||||
@ -127,11 +129,59 @@ export function Profile() {
|
||||
</TouchableOpacity>
|
||||
<Switch style={styles.visibleSwitch} value={state.searchable} onValueChange={setVisible} trackColor={styles.switch}/>
|
||||
</View>
|
||||
<TouchableOpacity style={styles.link} onPress={actions.showBlockedCards}>
|
||||
<Text style={styles.linkText}>Manage Blocked Contacts</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.link} onPress={actions.showBlockedChannels}>
|
||||
<Text style={styles.linkText}>Manager Blocked Topics</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.logout} onPress={logout}>
|
||||
<Ionicons name="logout" size={14} color={Colors.white} />
|
||||
<Text style={styles.logoutText}>Logout</Text>
|
||||
</TouchableOpacity>
|
||||
</SafeAreaView>
|
||||
<Modal
|
||||
animationType="fade"
|
||||
transparent={true}
|
||||
visible={state.blockedCards}
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
onRequestClose={actions.hideBlockedCards}
|
||||
>
|
||||
<View style={styles.editWrapper}>
|
||||
<View style={styles.editContainer}>
|
||||
<Text style={styles.editHeader}>Blocked Contacts:</Text>
|
||||
<View style={styles.editList}>
|
||||
<BlockedContacts />
|
||||
</View>
|
||||
<View style={styles.editControls}>
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideBlockedCards}>
|
||||
<Text>Close</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
<Modal
|
||||
animationType="fade"
|
||||
transparent={true}
|
||||
visible={state.blockedChannels}
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
onRequestClose={actions.hideBlockedChannels}
|
||||
>
|
||||
<View style={styles.editWrapper}>
|
||||
<View style={styles.editContainer}>
|
||||
<Text style={styles.editHeader}>Blocked Topics:</Text>
|
||||
<View style={styles.editList}>
|
||||
<BlockedTopics />
|
||||
</View>
|
||||
<View style={styles.editControls}>
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideBlockedChannels}>
|
||||
<Text>Close</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
<Modal
|
||||
animationType="fade"
|
||||
transparent={true}
|
||||
|
@ -117,9 +117,15 @@ export const styles = StyleSheet.create({
|
||||
maxWidth: 400,
|
||||
},
|
||||
editHeader: {
|
||||
fontSize: 20,
|
||||
fontSize: 18,
|
||||
paddingBottom: 16,
|
||||
},
|
||||
editList: {
|
||||
width: '100%',
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.lightgrey,
|
||||
borderRadius: 2,
|
||||
},
|
||||
inputField: {
|
||||
width: '100%',
|
||||
borderWidth: 1,
|
||||
@ -132,7 +138,7 @@ export const styles = StyleSheet.create({
|
||||
flexDirection: 'row',
|
||||
},
|
||||
input: {
|
||||
fontSize: 16,
|
||||
fontSize: 14,
|
||||
flexGrow: 1,
|
||||
},
|
||||
editControls: {
|
||||
@ -140,6 +146,16 @@ export const styles = StyleSheet.create({
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
close: {
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.lightgrey,
|
||||
borderRadius: 4,
|
||||
padding: 8,
|
||||
marginTop: 8,
|
||||
width: 72,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
cancel: {
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.lightgrey,
|
||||
@ -170,6 +186,12 @@ export const styles = StyleSheet.create({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
link: {
|
||||
marginTop: 16,
|
||||
},
|
||||
linkText: {
|
||||
color: Colors.primary,
|
||||
},
|
||||
saveText: {
|
||||
color: Colors.white,
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
import { FlatList, View, Alert, TouchableOpacity, Text } from 'react-native';
|
||||
import { styles } from './BlockedContacts.styled';
|
||||
import { useBlockedContacts } from './useBlockedContacts.hook';
|
||||
import { Logo } from 'utils/Logo';
|
||||
|
||||
export function BlockedContacts() {
|
||||
|
||||
const { state, actions } = useBlockedContacts();
|
||||
|
||||
const unblock = (cardId) => {
|
||||
Alert.alert(
|
||||
'Unblocking Contact',
|
||||
'Confirm?',
|
||||
[
|
||||
{ text: "Cancel", onPress: () => {}, },
|
||||
{ text: "Unblock", onPress: () => actions.unblock(cardId) },
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
const BlockedItem = ({ item }) => {
|
||||
return (
|
||||
<TouchableOpacity style={styles.item} onPress={() => unblock(item.cardId)}>
|
||||
<Logo src={item.logo} width={32} height={32} radius={6} />
|
||||
<View style={styles.detail}>
|
||||
<Text style={styles.name} numberOfLines={1} ellipsizeMode={'tail'}>{ item.name }</Text>
|
||||
<Text style={styles.handle} numberOfLines={1} ellipsizeMode={'tail'}>{ item.handle }</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{ state.cards.length === 0 && (
|
||||
<Text style={styles.default}>No Blocked Contacts</Text>
|
||||
)}
|
||||
{ state.cards.length !== 0 && (
|
||||
<FlatList
|
||||
data={state.cards}
|
||||
renderItem={({item}) => <BlockedItem item={item} />}
|
||||
keyExtractor={item => item.cardId}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,43 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { Colors } from 'constants/Colors';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: Colors.white,
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
justifyContent: 'center',
|
||||
fontSize: 14,
|
||||
height: 200,
|
||||
},
|
||||
default: {
|
||||
textAlign: 'center',
|
||||
color: Colors.grey,
|
||||
},
|
||||
item: {
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
height: 48,
|
||||
paddingLeft: 16,
|
||||
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,
|
||||
},
|
||||
});
|
@ -0,0 +1,53 @@
|
||||
import { useState, useEffect, useContext } from 'react';
|
||||
import { CardContext } from 'context/CardContext';
|
||||
|
||||
export function useBlockedContacts() {
|
||||
|
||||
const [state, setState] = useState({
|
||||
cards: [],
|
||||
});
|
||||
|
||||
const card = useContext(CardContext);
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
}
|
||||
|
||||
const setCardItem = (item) => {
|
||||
const { profile } = item;
|
||||
return {
|
||||
cardId: item.cardId,
|
||||
name: profile.name,
|
||||
handle: `${profile.handle}@${profile.node}`,
|
||||
blocked: item.blocked,
|
||||
logo: profile.imageSet ? card.actions.getCardLogo(item.cardId, item.revision) : 'avatar',
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const cards = Array.from(card.state.cards.values());
|
||||
const items = cards.map(setCardItem);
|
||||
const filtered = items.filter(item => {
|
||||
return item.blocked;
|
||||
});
|
||||
filtered.sort((a, b) => {
|
||||
if (a.name === b.name) {
|
||||
return 0;
|
||||
}
|
||||
if (!a.name || (a.name < b.name)) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
updateState({ cards: filtered });
|
||||
}, [card]);
|
||||
|
||||
const actions = {
|
||||
unblock: async (cardId) => {
|
||||
await card.actions.clearCardBlocked(cardId);
|
||||
}
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
import { Text } from 'react-native';
|
||||
|
||||
export function BlockedTopics() {
|
||||
return <Text>TOPICS</Text>
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ export function useProfile() {
|
||||
available: true,
|
||||
showPassword: false,
|
||||
showConfirm: false,
|
||||
blockedChannels: false,
|
||||
blockedCards: false,
|
||||
});
|
||||
|
||||
const app = useContext(AppContext);
|
||||
@ -60,6 +62,18 @@ export function useProfile() {
|
||||
setProfileImage: async (data) => {
|
||||
await profile.actions.setProfileImage(data);
|
||||
},
|
||||
showBlockedChannels: () => {
|
||||
updateState({ blockedChannels: true });
|
||||
},
|
||||
hideBlockedChannels: () => {
|
||||
updateState({ blockedChannels: false });
|
||||
},
|
||||
showBlockedCards: () => {
|
||||
updateState({ blockedCards: true });
|
||||
},
|
||||
hideBlockedCards: () => {
|
||||
updateState({ blockedCards: false });
|
||||
},
|
||||
showLoginEdit: () => {
|
||||
updateState({ showLoginEdit: true });
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user