refactored details page

This commit is contained in:
Roland Osborne 2023-09-25 14:35:09 -07:00
parent 408a16f018
commit fa2927d5ba
7 changed files with 159 additions and 73 deletions

View File

@ -109,6 +109,7 @@ const Strings = [
actionDelete: 'Delete',
actionBlock: 'Block',
actionReport: 'Report',
actionLeave: 'Leave',
// contact list page
add: 'Add',
@ -137,6 +138,10 @@ const Strings = [
members: 'Members',
editSubject: 'Edit Subject',
topicMembers: 'Topic Members',
leaveTopic: 'Leave Topic',
deleteTopic: 'Delete Topic',
blockTopic: 'Block Topic',
reportTopic: 'Report Topic',
},
{
visibleRegistry: 'Visible dans le Registre',
@ -271,6 +276,10 @@ const Strings = [
members: 'Membres',
editSubject: 'Modifier le Title',
topicMembers: 'Membres du Sujet',
leaveTopic: 'Quitter le Sujet',
deleteTopic: 'Supprimer le Sujet',
blockTopic: 'Bloquer le Sujet',
reportTopic: 'Signaler le Sujet',
},
{
visibleRegistry: 'Visible en el Registro',
@ -405,6 +414,10 @@ const Strings = [
members: 'Miembros',
editSubject: 'Editar Título',
topicMembers: 'Miembros del Tema',
leaveTopic: 'Dejar el Tema',
deleteTopic: 'Borrar el Tema',
blockTopic: 'Bloquer el Tema',
reportTopic: 'Reportar el Tema',
},
{
visibleRegistry: 'Sichtbar in der Registrierung',
@ -539,6 +552,10 @@ const Strings = [
members: 'Mitglieder',
editSubject: 'Titel bearbeiten',
topicMembers: 'Themenmitglieder',
leaveTopic: 'Verlasse das Thema',
deleteTopic: 'Das Thema Löschen',
blockTopic: 'Blockiere das Thema',
reportTopic: 'Das Thema Melden',
}
];

View File

@ -39,7 +39,7 @@ export function useChannels() {
const setChannelItem = async (loginTimestamp, cardId, channelId, item) => {
const timestamp = item.summary.lastTopic.created;
const { readRevision, topicRevision } = item;
const { readRevision, topicRevision, blocked } = item;
// decrypt subject and message
let locked = false;
@ -113,7 +113,7 @@ export function useChannels() {
const updated = (loginTimestamp < timestamp) && (readRevision < topicRevision);
return { cardId, channelId, subject, message, logo, timestamp, updated, locked, unlocked };
return { cardId, channelId, subject, message, logo, timestamp, updated, locked, unlocked, blocked };
}
useEffect(() => {
@ -176,7 +176,6 @@ export function useChannels() {
items.push({ loginTimestamp, channelId, channelItem: item });
});
card.state.cards.forEach((cardItem, cardId) => {
cardItem.channels.forEach((channelItem, channelId) => {
items.push({ loginTimestamp, cardId, channelId, channelItem });
});
@ -187,6 +186,9 @@ export function useChannels() {
channels.push(await setChannelItem(loginTimestamp, cardId, channelId, channelItem));
}
const filtered = channels.filter(item => {
if (item.blocked) {
return false;
}
if (!filter.current) {
return true;
}

View File

@ -1,4 +1,5 @@
import { ActivityIndicator, KeyboardAvoidingView, FlatList, Alert, Modal, View, Text, Switch, TouchableOpacity, TextInput } from 'react-native';
import { useState } from 'react';
import { styles } from './Details.styled';
import { useDetails } from './useDetails.hook';
import { Logo } from 'utils/Logo';
@ -11,7 +12,8 @@ import { InputField } from 'utils/InputField';
export function Details({ channel, clearConversation }) {
const { state, actions } = useDetails();
const [busy, setBusy] = useState(false);
const { state, actions } = useDetails(clearConversation);
const toggle = async (cardId, selected) => {
try {
@ -58,6 +60,27 @@ export function Details({ channel, clearConversation }) {
}
}
const promptAction = (prompt, action) => {
prompt(async () => {
if (!busy) {
try {
setBusy(true);
await action();
setBusy(false);
}
catch (err) {
console.log(err);
setBusy(false);
Alert.alert(
state.strings.error,
state.strings.tryAgain,
);
throw err;
}
}
});
}
const remove = () => {
Alert.alert(
"Removing Topic",
@ -164,45 +187,6 @@ export function Details({ channel, clearConversation }) {
</View>
<View style={styles.controls}>
{ !state.hostId && (
<TouchableOpacity style={styles.button} onPress={remove}>
{ state.deleteBusy && (
<ActivityIndicator color={Colors.white} />
)}
{ !state.deleteBusy && (
<Text style={styles.buttonText}>Delete Topic</Text>
)}
</TouchableOpacity>
)}
{ state.hostId && (
<TouchableOpacity style={styles.button} onPress={remove}>
{ state.deleteBusy && (
<ActivityIndicator color={Colors.white} />
)}
{ !state.deleteBusy && (
<Text style={styles.buttonText}>Leave Topic</Text>
)}
</TouchableOpacity>
)}
<TouchableOpacity style={styles.button} onPress={block}>
{ state.blockBusy && (
<ActivityIndicator color={Colors.white} />
)}
{ !state.blockBusy && (
<Text style={styles.buttonText}>Block Topic</Text>
)}
</TouchableOpacity>
{ state.hostId && (
<TouchableOpacity style={styles.button} onPress={report}>
<Text style={styles.buttonText}>Report Topic</Text>
</TouchableOpacity>
)}
{ !state.hostId && !state.locked && (
<TouchableOpacity style={styles.button} onPress={actions.showEditMembers}>
<Text style={styles.buttonText}>Edit Membership</Text>
</TouchableOpacity>
)}
<View style={styles.notify}>
<TouchableOpacity onPress={() => setNotifications(!state.notification)} activeOpacity={1}>
<Text style={styles.notifyText}>{ state.strings.enableNotifications }</Text>
@ -211,7 +195,42 @@ export function Details({ channel, clearConversation }) {
<Switch style={styles.switch} value={state.notification} onValueChange={setNotifications} trackColor={styles.track}/>
)}
</View>
</View>
<View style={styles.control}>
{ busy && (
<ActivityIndicator animating={true} color={Colors.text} size={'large'} />
)}
{ !busy && (
<View style={styles.drawerActions}>
{ !state.hostId && !state.locked && (
<TouchableOpacity style={styles.action} activeOpacity={1} onPress={actions.showEditMembers}>
<MatIcons name="account-group-outline" style={styles.actionIcon} size={44} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.members }</Text>
</TouchableOpacity>
)}
{ !state.hostId && (
<TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => promptAction(actions.deletePrompt, actions.removeTopic)}>
<MatIcons name="text-box-remove-outline" style={styles.actionIcon} size={44} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.delete }</Text>
</TouchableOpacity>
)}
{ state.hostId && (
<TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => promptAction(actions.leavePrompt, actions.removeTopic)}>
<MatIcons name="text-box-minus-outline" style={styles.actionIcon} size={44} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.leave }</Text>
</TouchableOpacity>
)}
<TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => promptAction(actions.blockPrompt, actions.blockTopic)}>
<MatIcons name="comment-remove-outline" style={styles.actionIcon} size={44} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionBlock }</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => promptAction(actions.reportPrompt, actions.reportTopic)}>
<MatIcons name="comment-alert-outline" style={styles.actionIcon} size={44} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionReport }</Text>
</TouchableOpacity>
</View>
)}
</View>
<View style={styles.members}>

View File

@ -249,4 +249,38 @@ export const styles = StyleSheet.create({
width: '100%',
},
},
control: {
width: '100%',
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
paddingTop: 12,
},
drawerActions: {
display: 'flex',
flexDirection: 'row',
alignItems: 'flex-end',
justifyContent: 'center',
width: '80%',
borderRadius: 8,
paddingTop: 8,
paddingBottom: 8,
},
actionList: {
alignItems: 'flex-end',
},
action: {
display: 'flex',
alignItems: 'center',
paddingRight: 12,
paddingLeft: 12,
paddingBottom: 12,
},
actionIcon: {
},
actionLabel: {
color: Colors.linkText,
fontSize: 10,
},
})

View File

@ -14,7 +14,7 @@ export function MemberItem({ item, hostId, toggle }) {
return (
<TouchableOpacity style={styles.container} activeOpacity={1} onPress={select}>
<Logo src={item.logo} width={32} height={32} radius={6} />
<Logo src={item.logo} width={48} height={48} 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 File

@ -6,7 +6,7 @@ export const styles = StyleSheet.create({
width: '100%',
display: 'flex',
flexDirection: 'row',
height: 48,
height: 64,
alignItems: 'center',
borderBottomWidth: 1,
borderColor: Colors.itemDivider,

View File

@ -8,9 +8,10 @@ import { getChannelSubjectLogo } from 'context/channelUtil';
import { getCardByGuid } from 'context/cardUtil';
import { getChannelSeals, isUnsealed, getContentKey, updateChannelSubject } from 'context/sealUtil';
import { getLanguageStrings } from 'constants/Strings';
import { DisplayContext } from 'context/DisplayContext';
import moment from 'moment';
export function useDetails() {
export function useDetails(clear) {
const [state, setState] = useState({
strings: getLanguageStrings(),
@ -38,6 +39,7 @@ export function useDetails() {
const account = useContext(AccountContext);
const conversation = useContext(ConversationContext);
const profile = useContext(ProfileContext);
const display = useContext(DisplayContext);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
@ -200,41 +202,53 @@ export function useDetails() {
await conversation.actions.setChannelSubject('superbasic', subject);
}
},
remove: async () => {
if (!state.deleteBusy) {
try {
updateState({ deleteBusy: true });
await conversation.actions.removeChannel();
updateState({ deleteBusy: false });
}
catch(err) {
console.log(err);
updateState({ deleteBusy: false });
throw new Error("delete failed");
}
}
removeTopic: async () => {
await conversation.actions.removeChannel();
clear();
},
block: async() => {
if (!state.deleteBusy) {
try {
updateState({ blockBusy: true });
await conversation.actions.setChannelFlag();
updateState({ blockBusy: false });
}
catch(err) {
console.log(err);
updateState({ blockBusy: false });
throw new Error("block failed");
}
}
blockTopic: async() => {
await conversation.actions.setChannelFlag();
clear();
},
report: async() => {
reportTopic: async() => {
await conversation.actions.addChannelAlert();
},
setNotifications: async (notification) => {
await conversation.actions.setNotifications(notification);
updateState({ notification });
},
deletePrompt: (action) => {
display.actions.showPrompt({
title: state.strings.deleteTopic,
centerButtons: true,
ok: { label: state.strings.confirmDelete, action, failed: () => {}},
cancel: { label: state.strings.cancel },
});
},
leavePrompt: (action) => {
display.actions.showPrompt({
title: state.strings.leaveTopic,
centerButtons: true,
ok: { label: state.strings.leave, action, failed: () => {}},
cancel: { label: state.strings.cancel },
});
},
blockPrompt: (action) => {
display.actions.showPrompt({
title: state.strings.blockTopic,
centerButtons: true,
ok: { label: state.strings.confirmBlock, action, failed: () => {}},
cancel: { label: state.strings.cancel },
});
},
reportPrompt: (action) => {
display.actions.showPrompt({
title: state.strings.reportTopic,
centerButtons: true,
ok: { label: state.strings.confirmReport, action, failed: () => {}},
cancel: { label: state.strings.cancel },
});
},
};
return { state, actions };