diff --git a/app/mobile/src/session/profile/blockedMessages/BlockedMessages.jsx b/app/mobile/src/session/profile/blockedMessages/BlockedMessages.jsx
new file mode 100644
index 00000000..4160eaf4
--- /dev/null
+++ b/app/mobile/src/session/profile/blockedMessages/BlockedMessages.jsx
@@ -0,0 +1,47 @@
+import { FlatList, View, Alert, TouchableOpacity, Text } from 'react-native';
+import { styles } from './BlockedMessages.styled';
+import { useBlockedMessages } from './useBlockedMessages.hook';
+import { Logo } from 'utils/Logo';
+
+export function BlockedMessages() {
+
+ const { state, actions } = useBlockedMessages();
+
+ const unblock = (cardId, channelId, topicId) => {
+ Alert.alert(
+ 'Unblocking Message',
+ 'Confirm?',
+ [
+ { text: "Cancel", onPress: () => {}, },
+ { text: "Unblock", onPress: () => actions.unblock(cardId, channelId, topicId) },
+ ],
+ );
+ };
+
+ const BlockedItem = ({ item }) => {
+ return (
+ unblock(item.cardId, item.channelId, item.topicId)}>
+
+ { item.name }
+ { item.timestamp }
+
+
+ )
+ }
+
+ return (
+
+ { state.messages.length === 0 && (
+ No Blocked Messages
+ )}
+ { state.messages.length !== 0 && (
+ }
+ keyExtractor={item => item.id}
+ />
+ )}
+
+ );
+}
+
diff --git a/app/mobile/src/session/profile/blockedMessages/BlockedMessages.styled.js b/app/mobile/src/session/profile/blockedMessages/BlockedMessages.styled.js
new file mode 100644
index 00000000..c29efdcb
--- /dev/null
+++ b/app/mobile/src/session/profile/blockedMessages/BlockedMessages.styled.js
@@ -0,0 +1,46 @@
+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: 32,
+ paddingLeft: 16,
+ alignItems: 'center',
+ borderBottomWidth: 1,
+ borderColor: Colors.itemDivider,
+ },
+ detail: {
+ paddingLeft: 12,
+ display: 'flex',
+ flexDirection: 'row',
+ justifyContent: 'center',
+ width: '100%',
+ },
+ name: {
+ color: Colors.text,
+ fontSize: 14,
+ flexGrow: 1,
+ flexShrink: 1,
+ minWidth: 0,
+ },
+ created: {
+ color: Colors.text,
+ fontSize: 12,
+ paddingRight: 16,
+ },
+});
diff --git a/app/mobile/src/session/profile/blockedMessages/useBlockedMessages.hook.js b/app/mobile/src/session/profile/blockedMessages/useBlockedMessages.hook.js
new file mode 100644
index 00000000..4254ed5c
--- /dev/null
+++ b/app/mobile/src/session/profile/blockedMessages/useBlockedMessages.hook.js
@@ -0,0 +1,110 @@
+import { useState, useEffect, useContext } from 'react';
+import { StoreContext } from 'context/StoreContext';
+import { ChannelContext } from 'context/ChannelContext';
+import { CardContext } from 'context/CardContext';
+import { ProfileContext } from 'context/ProfileContext';
+import { ConversationContext } from 'context/ConversationContext';
+import moment from 'moment';
+
+export function useBlockedMessages() {
+
+ const [state, setState] = useState({
+ messages: []
+ });
+
+ const store = useContext(StoreContext);
+ const card = useContext(CardContext);
+ const channel = useContext(ChannelContext);
+ const profile = useContext(ProfileContext);
+ const conversation = useContext(ConversationContext);
+
+ const updateState = (value) => {
+ setState((s) => ({ ...s, ...value }));
+ }
+
+ const setItem = (item) => {
+ let name, nameSet
+ if (item.detail.guid === profile.state.profile.guid) {
+ const identity = profile.state.profile;
+ if (identity.name) {
+ name = identity.name;
+ }
+ else {
+ name = `${identity.handle}@${identity.node}`;
+ }
+ nameSet = true;
+ }
+ else {
+ const contact = card.actions.getByGuid(item.detail.guid);
+ if (contact) {
+ if (contact?.profile?.name) {
+ name = contact.profile.name;
+ }
+ else {
+ name = `${contact.profile.handle}@${contact.profile.node}`;
+ }
+ nameSet = true;
+ }
+ else {
+ name = 'unknown';
+ nameSet = false;
+ }
+ }
+
+ let timestamp;
+ const date = new Date(item.detail.created * 1000);
+ const now = new Date();
+ const offset = now.getTime() - date.getTime();
+ if(offset < 86400000) {
+ timestamp = moment(date).format('h:mma');
+ }
+ else if (offset < 31449600000) {
+ timestamp = moment(date).format('M/DD');
+ }
+ else {
+ timestamp = moment(date).format('M/DD/YYYY');
+ }
+
+ const { cardId, channelId, topicId } = item;
+ return { name, nameSet, timestamp, cardId, channelId, topicId, id: `${cardId}:${channelId}:${topicId}` };
+ };
+
+ const loadBlocked = async () => {
+ const channelTopics = await channel.actions.getTopicBlocked();
+ const cardChannelTopics = await card.actions.getChannelTopicBlocked();
+ const topics = [ ...channelTopics, ...cardChannelTopics ];
+ const sorted = topics.sort((a, b) => {
+ const aTimestamp = a?.detail?.created;
+ const bTimestamp = b?.detail?.created;
+ if (aTimestamp === bTimestamp) {
+ return 0;
+ }
+ if (aTimestamp == null || aTimestamp < bTimestamp) {
+ return 1;
+ }
+ return -1;
+ });
+ updateState({ messages: sorted.map(setItem) });
+ }
+
+ useEffect(() => {
+ loadBlocked();
+ }, []);
+
+ const actions = {
+ unblock: async (cardId, channelId, topicId) => {
+ const id = `${cardId}:${channelId}:${topicId}`;
+ if (cardId) {
+ card.actions.clearChannelTopicBlocked(cardId, channelId, topicId);
+ }
+ else {
+ channel.actions.clearTopicBlocked(channelId, topicId);
+ }
+ conversation.actions.unblockTopic(cardId, channelId, topicId);
+ updateState({ messages: state.messages.filter(item => item.id !== id) });
+ }
+ };
+
+ return { state, actions };
+}
+