add reporting of users and content required by android

This commit is contained in:
balzack 2022-10-31 00:32:27 -07:00
parent 126866e5fa
commit 16c8b7dd71
11 changed files with 168 additions and 5 deletions

View File

@ -0,0 +1,14 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function addFlag(server, guid, channel, topic) {
if (channel) {
const param = topic ? `&topic=${topic}` : '';
const flag = await fetchWithTimeout(`https://${server}/account/flag/${guid}?channel=${channel}${param}`, { method: 'POST' } );
checkResponse(flag);
}
else {
const flag = await fetchWithTimeout(`https://${server}/account/flag/${guid}`, { method: 'POST' } );
checkResponse(flag);
}
}

View File

@ -1,6 +1,7 @@
import { useState, useRef, useContext } from 'react'; import { useState, useRef, useContext } from 'react';
import { StoreContext } from 'context/StoreContext'; import { StoreContext } from 'context/StoreContext';
import { UploadContext } from 'context/UploadContext'; import { UploadContext } from 'context/UploadContext';
import { addFlag } from 'api/addFlag';
import { getCard } from 'api/getCard'; import { getCard } from 'api/getCard';
import { getCards } from 'api/getCards'; import { getCards } from 'api/getCards';
import { getCardProfile } from 'api/getCardProfile'; import { getCardProfile } from 'api/getCardProfile';
@ -567,6 +568,14 @@ export function useCardContext() {
const { detail, profile } = getCardEntry(cardId); const { detail, profile } = getCardEntry(cardId);
return await removeContactChannelTopic(profile.node, `${profile.guid}.${detail.token}`, channelId, topicId); return await removeContactChannelTopic(profile.node, `${profile.guid}.${detail.token}`, channelId, topicId);
}, },
addChannelReport: async (cardId, channelId) => {
const { detail, profile } = getCardEntry(cardId);
return await addFlag(profile.node, profile.guid, channelId);
},
addChannelTopicReport: async (cardId, channelId, topicId) => {
const { detail, profile } = getCardEntry(cardId);
return await addFlag(profile.node, profile.guid, channelId, topicId);
},
resync: (cardId) => { resync: (cardId) => {
resync.current.push(cardId); resync.current.push(cardId);
sync(); sync();

View File

@ -15,6 +15,7 @@ import { getChannelTopicAssetUrl } from 'api/getChannelTopicAssetUrl';
import { setChannelSubject } from 'api/setChannelSubject'; import { setChannelSubject } from 'api/setChannelSubject';
import { setChannelCard } from 'api/setChannelCard'; import { setChannelCard } from 'api/setChannelCard';
import { clearChannelCard } from 'api/clearChannelCard'; import { clearChannelCard } from 'api/clearChannelCard';
import { addFlag } from 'api/addFlag';
export function useChannelContext() { export function useChannelContext() {
const [state, setState] = useState({ const [state, setState] = useState({
@ -280,6 +281,14 @@ export function useChannelContext() {
const { server, appToken } = session.current; const { server, appToken } = session.current;
return await removeChannelTopic(server, appToken, channelId, topicId); return await removeChannelTopic(server, appToken, channelId, topicId);
}, },
addReport: async (channelId) => {
const { server, guid } = session.current;
return await addFlag(server, guid, channelId);
},
addTopicReport: async (channelId, topicId) => {
const { server, guid } = session.current;
return await addFlag(server, guid, channelId, topicId);
},
setCard: async (channelId, cardId) => { setCard: async (channelId, cardId) => {
const { server, appToken } = session.current; const { server, appToken } = session.current;
return await setChannelCard(server, appToken, channelId, cardId); return await setChannelCard(server, appToken, channelId, cardId);

View File

@ -454,6 +454,28 @@ export function useConversationContext() {
await channel.actions.clearCard(channelId, id); await channel.actions.clearCard(channelId, id);
} }
}, },
addReport: async () => {
if (conversationId.current) {
const { cardId, channelId } = conversationId.current;
if (cardId) {
return await card.actions.addChannelReport(cardId, channelId);
}
else {
return await channel.actions.addReport(channelId);
}
}
},
addTopicReport: async(topicId) => {
if (conversationId.current) {
const { cardId, channelId } = conversationId.current;
if (cardId) {
return await card.actions.addChannelTopicReport(cardId, channelId, topicId);
}
else {
return await channel.actions.addTopicReport(channelId, topicId);
}
}
},
setBlocked: async () => { setBlocked: async () => {
if (conversationId.current) { if (conversationId.current) {
const { cardId, channelId } = conversationId.current; const { cardId, channelId } = conversationId.current;

View File

@ -154,6 +154,21 @@ export function Contact({ contact, closeContact }) {
); );
} }
const reportContact = () => {
Alert.alert(
"Report Contact",
"Confirm?",
[
{ text: "Cancel",
onPress: () => {},
},
{ text: "Report", onPress: () => {
setContact(actions.reportContact);
}}
]
);
}
const connectContact = () => { const connectContact = () => {
setContact(actions.connectContact); setContact(actions.connectContact);
} }
@ -194,6 +209,9 @@ export function Contact({ contact, closeContact }) {
<TouchableOpacity style={styles.button} onPress={blockContact}> <TouchableOpacity style={styles.button} onPress={blockContact}>
<Text style={styles.buttonText}>Block Contact</Text> <Text style={styles.buttonText}>Block Contact</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={reportContact}>
<Text style={styles.buttonText}>Report Contact</Text>
</TouchableOpacity>
</> </>
)} )}
{ state.status === 'connecting' && ( { state.status === 'connecting' && (
@ -207,6 +225,9 @@ export function Contact({ contact, closeContact }) {
<TouchableOpacity style={styles.button} onPress={blockContact}> <TouchableOpacity style={styles.button} onPress={blockContact}>
<Text style={styles.buttonText}>Block Contact</Text> <Text style={styles.buttonText}>Block Contact</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={reportContact}>
<Text style={styles.buttonText}>Report Contact</Text>
</TouchableOpacity>
</> </>
)} )}
{ state.status === 'confirmed' && ( { state.status === 'confirmed' && (
@ -220,6 +241,9 @@ export function Contact({ contact, closeContact }) {
<TouchableOpacity style={styles.button} onPress={blockContact}> <TouchableOpacity style={styles.button} onPress={blockContact}>
<Text style={styles.buttonText}>Block Contact</Text> <Text style={styles.buttonText}>Block Contact</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={reportContact}>
<Text style={styles.buttonText}>Report Contact</Text>
</TouchableOpacity>
</> </>
)} )}
{ state.status === 'pending' && ( { state.status === 'pending' && (
@ -236,6 +260,9 @@ export function Contact({ contact, closeContact }) {
<TouchableOpacity style={styles.button} onPress={blockContact}> <TouchableOpacity style={styles.button} onPress={blockContact}>
<Text style={styles.buttonText}>Block Contact</Text> <Text style={styles.buttonText}>Block Contact</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={reportContact}>
<Text style={styles.buttonText}>Report Contact</Text>
</TouchableOpacity>
</> </>
)} )}
{ state.status === 'requested' && ( { state.status === 'requested' && (
@ -255,6 +282,9 @@ export function Contact({ contact, closeContact }) {
<TouchableOpacity style={styles.button} onPress={blockContact}> <TouchableOpacity style={styles.button} onPress={blockContact}>
<Text style={styles.buttonText}>Block Contact</Text> <Text style={styles.buttonText}>Block Contact</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={reportContact}>
<Text style={styles.buttonText}>Report Contact</Text>
</TouchableOpacity>
</> </>
)} )}
{ state.status == null && ( { state.status == null && (
@ -265,6 +295,9 @@ export function Contact({ contact, closeContact }) {
<TouchableOpacity style={styles.button} onPress={saveContact}> <TouchableOpacity style={styles.button} onPress={saveContact}>
<Text style={styles.buttonText}>Save Contact</Text> <Text style={styles.buttonText}>Save Contact</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={reportContact}>
<Text style={styles.buttonText}>Report Contact</Text>
</TouchableOpacity>
</> </>
)} )}
</View> </View>

View File

@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom';
import { CardContext } from 'context/CardContext'; import { CardContext } from 'context/CardContext';
import { useWindowDimensions } from 'react-native' import { useWindowDimensions } from 'react-native'
import { getListingMessage } from 'api/getListingMessage'; import { getListingMessage } from 'api/getListingMessage';
import { addFlag } from 'api/addFlag';
import config from 'constants/Config'; import config from 'constants/Config';
export function useContact(contact, close) { export function useContact(contact, close) {
@ -177,6 +178,9 @@ export function useContact(contact, close) {
close(); close();
}); });
}, },
reportContact: async () => {
await addFlag(state.node, state.guid);
},
resync: () => { resync: () => {
card.actions.resync(contact.card); card.actions.resync(contact.card);
}, },

View File

@ -83,7 +83,8 @@ export function ConversationBody() {
inverted={true} inverted={true}
renderItem={({item}) => <TopicItem item={item} focused={item.topicId === state.focus} renderItem={({item}) => <TopicItem item={item} focused={item.topicId === state.focus}
focus={() => actions.setFocus(item.topicId)} hosting={state.host == null} focus={() => actions.setFocus(item.topicId)} hosting={state.host == null}
remove={actions.removeTopic} update={actions.editTopic} block={actions.blockTopic} />} remove={actions.removeTopic} update={actions.editTopic} block={actions.blockTopic}
report={actions.reportTopic} />}
keyExtractor={item => item.topicId} keyExtractor={item => item.topicId}
/> />
{ !state.init && ( { !state.init && (

View File

@ -15,7 +15,7 @@ import Carousel from 'react-native-snap-carousel';
import GestureRecognizer from 'react-native-swipe-gestures'; import GestureRecognizer from 'react-native-swipe-gestures';
import avatar from 'images/avatar.png'; import avatar from 'images/avatar.png';
export function TopicItem({ item, focused, focus, hosting, remove, update, block }) { export function TopicItem({ item, focused, focus, hosting, remove, update, block, report }) {
const { state, actions } = useTopicItem(item, hosting); const { state, actions } = useTopicItem(item, hosting);
@ -45,6 +45,32 @@ export function TopicItem({ item, focused, focus, hosting, remove, update, block
); );
} }
const reportMessage = () => {
Alert.alert(
"Report Message",
"Confirm?",
[
{ text: "Cancel",
onPress: () => {},
},
{ text: "Report",
onPress: async () => {
try {
await report(item.topicId);
}
catch (err) {
console.log(err);
Alert.alert(
'Failed to Report Message',
'Please try again.'
)
}
},
}
]
);
}
const hideMessage = () => { const hideMessage = () => {
Alert.alert( Alert.alert(
"Blocking Message", "Blocking Message",
@ -155,9 +181,16 @@ export function TopicItem({ item, focused, focus, hosting, remove, update, block
<AntIcons name="edit" size={24} color={Colors.white} /> <AntIcons name="edit" size={24} color={Colors.white} />
</TouchableOpacity> </TouchableOpacity>
)} )}
{ !state.editable && (
<TouchableOpacity style={styles.icon} onPress={hideMessage}> <TouchableOpacity style={styles.icon} onPress={hideMessage}>
<MatIcons name="block-helper" size={18} color={Colors.white} /> <MatIcons name="block-helper" size={18} color={Colors.white} />
</TouchableOpacity> </TouchableOpacity>
)}
{ !state.editable && (
<TouchableOpacity style={styles.icon} onPress={reportMessage}>
<MatIcons name="flag-outline" size={18} color={Colors.white} />
</TouchableOpacity>
)}
{ state.deletable && ( { state.deletable && (
<TouchableOpacity style={styles.icon} onPress={erase}> <TouchableOpacity style={styles.icon} onPress={erase}>
<MatIcons name="delete-outline" size={24} color={Colors.white} /> <MatIcons name="delete-outline" size={24} color={Colors.white} />

View File

@ -89,6 +89,9 @@ export function useConversation() {
blockTopic: async (topicId) => { blockTopic: async (topicId) => {
await conversation.actions.blockTopic(topicId); await conversation.actions.blockTopic(topicId);
}, },
reportTopic: async (topicId) => {
await conversation.actions.addTopicReport(topicId);
},
resync: () => { resync: () => {
conversation.actions.resync(); conversation.actions.resync();
}, },

View File

@ -82,6 +82,33 @@ export function DetailsBody({ channel, clearConversation }) {
); );
} }
const report = () => {
Alert.alert(
"Report Topic",
"Confirm?",
[
{ text: "Cancel",
onPress: () => {},
},
{ text: "Report",
onPress: async () => {
try {
await actions.report();
}
catch (err) {
console.log(err);
Alert.alert(
'Failed to Report Topic',
'Please try again.'
)
}
},
}
]
);
}
return ( return (
<View style={styles.body}> <View style={styles.body}>
<View style={styles.details}> <View style={styles.details}>
@ -112,6 +139,11 @@ export function DetailsBody({ channel, clearConversation }) {
<TouchableOpacity style={styles.button} onPress={block}> <TouchableOpacity style={styles.button} onPress={block}>
<Text style={styles.buttonText}>Block Topic</Text> <Text style={styles.buttonText}>Block Topic</Text>
</TouchableOpacity> </TouchableOpacity>
{ state.hostId && (
<TouchableOpacity style={styles.button} onPress={report}>
<Text style={styles.buttonText}>Report Topic</Text>
</TouchableOpacity>
)}
{ !state.hostId && ( { !state.hostId && (
<TouchableOpacity style={styles.button} onPress={actions.showEditMembers}> <TouchableOpacity style={styles.button} onPress={actions.showEditMembers}>
<Text style={styles.buttonText}>Edit Membership</Text> <Text style={styles.buttonText}>Edit Membership</Text>

View File

@ -61,6 +61,9 @@ export function useDetails() {
block: async() => { block: async() => {
await conversation.actions.setBlocked(); await conversation.actions.setBlocked();
}, },
report: async() => {
await conversation.actions.addReport();
},
}; };
return { state, actions }; return { state, actions };