(tabRefs.current[index] = el)}
className={cn(
- `w-fit text-center py-2 px-6 my-1 font-semibold whitespace-nowrap clickable cursor-pointer rounded-lg shrink-0`,
+ `text-center py-2 px-6 font-semibold whitespace-nowrap clickable cursor-pointer rounded-lg`,
value === tab.value ? '' : 'text-muted-foreground'
)}
onClick={() => {
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index fecc7a3..c222128 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -26,6 +26,25 @@ export function truncateText(text: string, maxWords: number): string {
return words.slice(0, maxWords).join(' ') + '...'
}
+/**
+ * Remove emoji characters from a string
+ * This regex covers most emoji ranges including:
+ * - Emoticons (đ-đ)
+ * - Misc Symbols & Pictographs (đ-đŋ)
+ * - Transport & Map Symbols (đ-đŋ)
+ * - Enclosed characters (âī¸, Šī¸, etc.)
+ * - Regional indicator symbols (flags)
+ * - And other emoji ranges
+ */
+export function removeEmojis(text: string): string {
+ if (!text) return ''
+
+ // Comprehensive emoji regex pattern covering major emoji Unicode ranges
+ const emojiRegex = /[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{1F900}-\u{1F9FF}]|[\u{1F018}-\u{1F270}]|[\u{238C}-\u{2454}]|[\u{20D0}-\u{20FF}]|[\u{FE00}-\u{FE0F}]|[\u{FE20}-\u{FE2F}]|[\u{E0020}-\u{E007F}]/gu
+
+ return text.replace(emojiRegex, '').trim().replace(/\s+/g, ' ')
+}
+
export function isSafari() {
if (typeof window === 'undefined' || !window.navigator) return false
const ua = window.navigator.userAgent
diff --git a/src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx b/src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx
index 8297675..5cc6163 100644
--- a/src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx
+++ b/src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx
@@ -141,9 +141,10 @@ export default function CreateThreadDialog({
if (dynamicTopics) {
// Add dynamic main topics first
dynamicTopics.mainTopics.forEach(dynamicTopic => {
+ const isGroupsTopic = dynamicTopic.id === 'groups'
combined.push({
id: dynamicTopic.id,
- label: `${dynamicTopic.label} (${dynamicTopic.count}) đĨ`,
+ label: `${dynamicTopic.label} (${dynamicTopic.count}) ${isGroupsTopic ? 'đĨ' : 'đĨ'}`,
icon: Hash // Use Hash icon for dynamic topics
})
})
diff --git a/src/pages/primary/DiscussionsPage/ThreadCard.tsx b/src/pages/primary/DiscussionsPage/ThreadCard.tsx
index ad02328..f083230 100644
--- a/src/pages/primary/DiscussionsPage/ThreadCard.tsx
+++ b/src/pages/primary/DiscussionsPage/ThreadCard.tsx
@@ -10,6 +10,7 @@ import Username from '@/components/Username'
import UserAvatar from '@/components/UserAvatar'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { extractAllTopics, extractGroupInfo } from '@/lib/discussion-topics'
+import { removeEmojis } from '@/lib/utils'
interface ThreadCardProps {
thread: NostrEvent
@@ -33,9 +34,10 @@ export default function ThreadCard({
const { t } = useTranslation()
const { isSmallScreen } = useScreenSize()
- // Extract title from tags
+ // Extract title from tags and remove emojis
const titleTag = thread.tags.find(tag => tag[0] === 'title' && tag[1])
- const title = titleTag?.[1] || t('Untitled')
+ const rawTitle = titleTag?.[1] || t('Untitled')
+ const title = removeEmojis(rawTitle) || t('Untitled')
// Get topic info
const topicTag = thread.tags.find(tag => tag[0] === 't' && tag[1])
@@ -67,10 +69,11 @@ export default function ThreadCard({
// Vote counts are no longer displayed, keeping variables for potential future use
- // Get content preview
- const contentPreview = thread.content.length > 250
- ? thread.content.substring(0, 250) + '...'
- : thread.content
+ // Get content preview - remove emojis first, then truncate
+ const contentWithoutEmojis = removeEmojis(thread.content)
+ const contentPreview = contentWithoutEmojis.length > 250
+ ? contentWithoutEmojis.substring(0, 250) + '...'
+ : contentWithoutEmojis
return (
diff --git a/src/pages/primary/DiscussionsPage/index.tsx b/src/pages/primary/DiscussionsPage/index.tsx
index f97419d..51dd2c8 100644
--- a/src/pages/primary/DiscussionsPage/index.tsx
+++ b/src/pages/primary/DiscussionsPage/index.tsx
@@ -904,15 +904,19 @@ const DiscussionsPage = forwardRef((_, ref) => {
className="w-full sm:w-auto px-3 py-2 bg-white dark:bg-gray-800 text-black dark:text-white border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
>
- {availableTopics.map(({ topic, count, isDynamic, isMainTopic, isSubtopic }) => (
-
- ))}
+ {availableTopics.map(({ topic, count, isDynamic, isMainTopic, isSubtopic }) => {
+ const isGroupsTopic = topic === 'groups'
+ return (
+
+ )
+ })}
{/* Time Span Dropdown */}
@@ -949,13 +953,15 @@ const DiscussionsPage = forwardRef((_, ref) => {
{Array.from(groupedEvents.entries()).map(([mainTopic, group]) => {
const topicInfo = availableTopics.find(t => t.topic === mainTopic)
const isDynamicMain = topicInfo?.isDynamic && topicInfo?.isMainTopic
+ const isGroupsTopic = mainTopic === 'groups'
return (
{/* Main Topic Header */}
- {isDynamicMain && đĨ}
+ {isGroupsTopic && đĨ}
+ {isDynamicMain && !isGroupsTopic && đĨ}
{mainTopic} ({group.entries.length + Array.from(group.subtopics.values()).reduce((sum, events) => sum + events.length, 0)} {group.entries.length + Array.from(group.subtopics.values()).reduce((sum, events) => sum + events.length, 0) === 1 ? t('thread') : t('threads')})
{isDynamicMain && Main Topic}