diff --git a/lib/shared/threads/protocols/dm-thread-protocol.js b/lib/shared/threads/protocols/dm-thread-protocol.js
--- a/lib/shared/threads/protocols/dm-thread-protocol.js
+++ b/lib/shared/threads/protocols/dm-thread-protocol.js
@@ -910,6 +910,10 @@
description:
'Comm DMs are end-to-end encrypted and stored locally on your ' +
'device for maximum privacy.',
+ topLevelThread: {
+ type: 'label',
+ label: 'Local DM',
+ },
},
supportsEncryptedMultimedia: true,
diff --git a/lib/shared/threads/protocols/farcaster-thread-protocol.js b/lib/shared/threads/protocols/farcaster-thread-protocol.js
--- a/lib/shared/threads/protocols/farcaster-thread-protocol.js
+++ b/lib/shared/threads/protocols/farcaster-thread-protocol.js
@@ -956,6 +956,10 @@
'Farcaster Direct Casts are the native messaging protocol in ' +
'Farcaster. They are not end-to-end encrypted, and the Farcaster ' +
'team can see the contents of your messages.',
+ topLevelThread: {
+ type: 'label',
+ label: 'Farcaster',
+ },
},
supportsEncryptedMultimedia: false,
diff --git a/lib/shared/threads/protocols/keyserver-thread-protocol.js b/lib/shared/threads/protocols/keyserver-thread-protocol.js
--- a/lib/shared/threads/protocols/keyserver-thread-protocol.js
+++ b/lib/shared/threads/protocols/keyserver-thread-protocol.js
@@ -713,6 +713,9 @@
"Genesis chats are a legacy chat type hosted on Ashoat's keyserver. " +
'They are not end-to-end encrypted, and Ashoat can see the contents ' +
'of your messages.',
+ topLevelThread: {
+ type: 'keyserverAdmin',
+ },
},
supportsEncryptedMultimedia: true,
diff --git a/lib/shared/threads/thread-spec.js b/lib/shared/threads/thread-spec.js
--- a/lib/shared/threads/thread-spec.js
+++ b/lib/shared/threads/thread-spec.js
@@ -503,6 +503,9 @@
+threadAncestorLabel: (ancestorPath: React.Node) => React.Node,
+protocolIcon: 'lock' | 'server' | 'farcaster',
+description: string,
+ +topLevelThread:
+ | { +type: 'keyserverAdmin' }
+ | { +type: 'label', +label: 'Farcaster' | 'Local DM' },
},
+supportsEncryptedMultimedia: boolean,
+supportsSendingVideos: boolean,
diff --git a/native/chat/parent-thread-header.react.js b/native/chat/parent-thread-header.react.js
--- a/native/chat/parent-thread-header.react.js
+++ b/native/chat/parent-thread-header.react.js
@@ -9,8 +9,8 @@
import { useNavigateToThread } from './message-list-types.js';
import Button from '../components/button.react.js';
-import CommunityPill from '../components/community-pill.react.js';
import ThreadVisibility from '../components/thread-visibility.react.js';
+import TopLevelThreadPill from '../components/top-level-thread-pill.react.js';
import { useColors, useStyles } from '../themes/colors.js';
type Props = {
@@ -38,7 +38,7 @@
<>
within
>
);
diff --git a/native/components/community-pill.react.js b/native/components/community-pill.react.js
deleted file mode 100644
--- a/native/components/community-pill.react.js
+++ /dev/null
@@ -1,68 +0,0 @@
-// @flow
-
-import * as React from 'react';
-import { StyleSheet, View } from 'react-native';
-
-import { useKeyserverAdmin } from 'lib/shared/user-utils.js';
-import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-
-import CommIcon from './comm-icon.react.js';
-import Pill from './pill.react.js';
-import ThreadPill from './thread-pill.react.js';
-import { useColors } from '../themes/colors.js';
-
-const threadPillRoundCorners = { left: false, right: true };
-
-type Props = {
- +community: ThreadInfo,
-};
-function CommunityPill(props: Props): React.Node {
- const { community } = props;
-
- const keyserverAdmin = useKeyserverAdmin(community);
- const keyserverOperatorUsername = keyserverAdmin?.username;
-
- const colors = useColors();
- const keyserverOperatorLabel: ?React.Node = React.useMemo(() => {
- if (!keyserverOperatorUsername) {
- return undefined;
- }
- const icon = (
-
- );
- return (
-
- );
- }, [
- colors.codeBackground,
- colors.panelForegroundLabel,
- keyserverOperatorUsername,
- ]);
-
- return (
-
- {keyserverOperatorLabel}
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flexDirection: 'row',
- },
-});
-
-export default CommunityPill;
diff --git a/native/components/thread-ancestors.react.js b/native/components/thread-ancestors.react.js
--- a/native/components/thread-ancestors.react.js
+++ b/native/components/thread-ancestors.react.js
@@ -9,8 +9,8 @@
import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
import Button from './button.react.js';
-import CommunityPill from './community-pill.react.js';
import ThreadPill from './thread-pill.react.js';
+import TopLevelThreadPill from './top-level-thread-pill.react.js';
import { useNavigateToThread } from '../chat/message-list-types.js';
import { useSelector } from '../redux/redux-utils.js';
import { useColors, useStyles } from '../themes/colors.js';
@@ -47,7 +47,7 @@
const isLastThread = idx === ancestorThreads.length - 1;
const pill =
idx === 0 ? (
-
+
) : (
);
diff --git a/native/components/thread-icon.react.js b/native/components/thread-icon.react.js
--- a/native/components/thread-icon.react.js
+++ b/native/components/thread-icon.react.js
@@ -2,12 +2,13 @@
import EntypoIcon from '@expo/vector-icons/Entypo.js';
import * as React from 'react';
-import { StyleSheet } from 'react-native';
+import { StyleSheet, View } from 'react-native';
import { threadTypeIsSidebar } from 'lib/shared/threads/thread-specs.js';
import { threadTypes, type ThreadType } from 'lib/types/thread-types-enum.js';
import SWMansionIcon from './swmansion-icon.react.js';
+import FarcasterLogo from '../vectors/farcaster-logo.react.js';
type Props = {
+threadType: ThreadType,
@@ -31,12 +32,30 @@
);
} else if (threadType === threadTypes.GENESIS_PERSONAL) {
return ;
+ } else if (
+ threadType === threadTypes.FARCASTER_GROUP ||
+ threadType === threadTypes.FARCASTER_PERSONAL
+ ) {
+ return (
+
+
+
+ );
} else {
return ;
}
}
const styles = StyleSheet.create({
+ farcasterIcon: {
+ alignItems: 'center',
+ backgroundColor: '#855DCD',
+ borderRadius: 9,
+ height: 18,
+ justifyContent: 'center',
+ opacity: 0.7,
+ width: 18,
+ },
sidebarIcon: {
paddingTop: 2,
},
diff --git a/native/components/top-level-thread-pill.react.js b/native/components/top-level-thread-pill.react.js
new file mode 100644
--- /dev/null
+++ b/native/components/top-level-thread-pill.react.js
@@ -0,0 +1,107 @@
+// @flow
+
+import * as React from 'react';
+import { StyleSheet, View } from 'react-native';
+
+import { threadSpecs } from 'lib/shared/threads/thread-specs.js';
+import { useKeyserverAdmin } from 'lib/shared/user-utils.js';
+import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
+
+import CommIcon from './comm-icon.react.js';
+import Pill from './pill.react.js';
+import SWMansionIcon from './swmansion-icon.react.js';
+import ThreadPill from './thread-pill.react.js';
+import { useColors } from '../themes/colors.js';
+import FarcasterLogo from '../vectors/farcaster-logo.react.js';
+
+const threadPillRoundCorners = { left: false, right: true };
+
+type Props = {
+ +threadInfo: ThreadInfo,
+};
+function TopLevelThreadPill(props: Props): React.Node {
+ const { threadInfo } = props;
+
+ const keyserverAdmin = useKeyserverAdmin(threadInfo);
+ const keyserverOperatorUsername = keyserverAdmin?.username;
+
+ const colors = useColors();
+ const keyserverOperatorLabel: ?React.Node = React.useMemo(() => {
+ const topLevelThreadConfig =
+ threadSpecs[threadInfo.type].protocol().presentationDetails
+ .topLevelThread;
+
+ let label;
+ let icon;
+ if (topLevelThreadConfig.type === 'keyserverAdmin') {
+ if (!keyserverOperatorUsername) {
+ return undefined;
+ }
+ icon = (
+
+ );
+ label = keyserverOperatorUsername;
+ } else if (topLevelThreadConfig.label === 'Local DM') {
+ label = 'Local DM';
+ icon = (
+
+ );
+ } else {
+ label = 'Farcaster';
+ icon = (
+
+
+
+ );
+ }
+
+ return (
+
+ );
+ }, [
+ colors.codeBackground,
+ colors.panelForegroundLabel,
+ keyserverOperatorUsername,
+ threadInfo.type,
+ ]);
+
+ return (
+
+ {keyserverOperatorLabel}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flexDirection: 'row',
+ },
+ farcasterIcon: {
+ alignItems: 'center',
+ backgroundColor: '#855DCD',
+ borderRadius: 9,
+ height: 18,
+ justifyContent: 'center',
+ opacity: 0.7,
+ width: 18,
+ },
+});
+
+export default TopLevelThreadPill;