mirror of
https://github.com/logos-messaging/OpChan.git
synced 2026-01-02 12:53:10 +00:00
clean up the share button(s)
This commit is contained in:
parent
244119bb05
commit
df2efac6c3
@ -27,6 +27,7 @@ import { ModerationToggle } from './ui/moderation-toggle';
|
||||
import { sortCells, SortOption } from '@/lib/utils/sorting';
|
||||
import { Cell } from '@/types/forum';
|
||||
import { usePending } from '@/hooks/usePending';
|
||||
import { ShareButton } from './ui/ShareButton';
|
||||
|
||||
// Empty State Component
|
||||
const EmptyState: React.FC<{ canCreateCell: boolean }> = ({
|
||||
@ -125,6 +126,11 @@ const CellItem: React.FC<{ cell: Cell }> = ({ cell }) => {
|
||||
{cell.activeMemberCount || 0} members
|
||||
</span>
|
||||
</div>
|
||||
<ShareButton
|
||||
size='sm'
|
||||
url={`${window.location.origin}/cell/${cell.id}`}
|
||||
title={cell.name}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -18,6 +18,7 @@ import {
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui/tooltip';
|
||||
import { ShareButton } from '@/components/ui/ShareButton';
|
||||
|
||||
interface CommentCardProps {
|
||||
comment: Comment;
|
||||
@ -126,13 +127,20 @@ const CommentCard: React.FC<CommentCardProps> = ({
|
||||
</span>
|
||||
<PendingBadge id={comment.id} />
|
||||
</div>
|
||||
<BookmarkButton
|
||||
isBookmarked={isBookmarked}
|
||||
loading={bookmarkLoading}
|
||||
onClick={handleBookmark}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
/>
|
||||
<div className="flex items-center gap-2">
|
||||
<ShareButton
|
||||
size='sm'
|
||||
url={`${window.location.origin}/post/${postId}#comment-${comment.id}`}
|
||||
title={comment.content.substring(0, 50) + (comment.content.length > 50 ? '...' : '')}
|
||||
/>
|
||||
<BookmarkButton
|
||||
isBookmarked={isBookmarked}
|
||||
loading={bookmarkLoading}
|
||||
onClick={handleBookmark}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm break-words mb-2">
|
||||
|
||||
@ -15,7 +15,7 @@ import { AuthorDisplay } from '@/components/ui/author-display';
|
||||
import { BookmarkButton } from '@/components/ui/bookmark-button';
|
||||
import { LinkRenderer } from '@/components/ui/link-renderer';
|
||||
import { usePending, usePendingVote } from '@/hooks/usePending';
|
||||
import { useToast } from '@/components/ui/use-toast';
|
||||
import { ShareButton } from '@/components/ui/ShareButton';
|
||||
|
||||
interface PostCardProps {
|
||||
post: Post;
|
||||
@ -32,7 +32,6 @@ const PostCard: React.FC<PostCardProps> = ({ post, commentCount = 0 }) => {
|
||||
loading: bookmarkLoading,
|
||||
toggleBookmark,
|
||||
} = usePostBookmark(post, post.cellId);
|
||||
const { toast } = useToast();
|
||||
|
||||
// ✅ Get pre-computed cell data
|
||||
const cell = cellsWithStats.find(c => c.id === post.cellId);
|
||||
@ -71,33 +70,6 @@ const PostCard: React.FC<PostCardProps> = ({ post, commentCount = 0 }) => {
|
||||
await toggleBookmark();
|
||||
};
|
||||
|
||||
const handleShare = async (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const postUrl = `${window.location.origin}/post/${post.id}`;
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(postUrl);
|
||||
toast({
|
||||
title: 'Link copied!',
|
||||
description: 'Post link has been copied to your clipboard.',
|
||||
});
|
||||
} catch {
|
||||
// Fallback for older browsers
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = postUrl;
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textArea);
|
||||
|
||||
toast({
|
||||
title: 'Link copied!',
|
||||
description: 'Post link has been copied to your clipboard.',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="thread-card mb-2">
|
||||
@ -207,14 +179,11 @@ const PostCard: React.FC<PostCardProps> = ({ post, commentCount = 0 }) => {
|
||||
syncing…
|
||||
</span>
|
||||
)}
|
||||
<button
|
||||
onClick={handleShare}
|
||||
className="hover:text-cyber-accent transition-colors flex items-center gap-1"
|
||||
title="Copy link"
|
||||
>
|
||||
<Clipboard size={14} />
|
||||
Share
|
||||
</button>
|
||||
<ShareButton
|
||||
size='sm'
|
||||
url={`${window.location.origin}/post/${post.id}`}
|
||||
title={post.title}
|
||||
/>
|
||||
</div>
|
||||
<BookmarkButton
|
||||
isBookmarked={isBookmarked}
|
||||
|
||||
@ -27,6 +27,7 @@ import { BookmarkButton } from './ui/bookmark-button';
|
||||
import { LinkRenderer } from './ui/link-renderer';
|
||||
import CommentCard from './CommentCard';
|
||||
import { usePending, usePendingVote } from '@/hooks/usePending';
|
||||
import { ShareButton } from './ui/ShareButton';
|
||||
|
||||
const PostDetail = () => {
|
||||
const { postId } = useParams<{ postId: string }>();
|
||||
@ -243,6 +244,11 @@ const PostDetail = () => {
|
||||
variant="ghost"
|
||||
showText={true}
|
||||
/>
|
||||
<ShareButton
|
||||
size='lg'
|
||||
url={`${window.location.origin}/post/${post.id}`}
|
||||
title={post.title}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm whitespace-pre-wrap break-words">
|
||||
<LinkRenderer text={post.content} />
|
||||
|
||||
@ -14,6 +14,7 @@ import { Input } from '@/components/ui/input';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { LinkRenderer } from '@/components/ui/link-renderer';
|
||||
import { ShareButton } from '@/components/ui/ShareButton';
|
||||
import {
|
||||
ArrowLeft,
|
||||
MessageSquare,
|
||||
@ -324,6 +325,15 @@ const PostList = () => {
|
||||
className="text-xs"
|
||||
showBadge={false}
|
||||
/>
|
||||
<ShareButton
|
||||
url={`${window.location.origin}/post/${post.id}`}
|
||||
title={post.title}
|
||||
description={post.content}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="text-cyber-neutral"
|
||||
showText={false}
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
{canModerate(cell.id) && !post.moderated && (
|
||||
|
||||
81
src/components/ui/ShareButton.tsx
Normal file
81
src/components/ui/ShareButton.tsx
Normal file
@ -0,0 +1,81 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Share2 } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useToast } from '../ui/use-toast';
|
||||
|
||||
interface ShareButtonProps {
|
||||
url: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
size?: 'sm' | 'lg';
|
||||
variant?: 'default' | 'ghost' | 'outline';
|
||||
className?: string;
|
||||
showText?: boolean;
|
||||
}
|
||||
|
||||
export function ShareButton({
|
||||
url,
|
||||
title,
|
||||
description = 'Check out this post',
|
||||
size = 'sm',
|
||||
variant = 'ghost',
|
||||
className,
|
||||
showText = false,
|
||||
}: ShareButtonProps) {
|
||||
const { toast } = useToast();
|
||||
|
||||
const sizeClasses = {
|
||||
sm: 'h-8 w-10',
|
||||
lg: 'h-10 whitespace-nowrap px-4',
|
||||
};
|
||||
|
||||
const iconSize = {
|
||||
sm: 14,
|
||||
lg: 18,
|
||||
};
|
||||
|
||||
const handleShare = async (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(url);
|
||||
toast({
|
||||
title: 'Link copied!',
|
||||
description: 'Link has been copied to your clipboard.',
|
||||
});
|
||||
} catch {
|
||||
// Fallback for older browsers
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = url;
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textArea);
|
||||
|
||||
toast({
|
||||
title: 'Link copied!',
|
||||
description: 'Link has been copied to your clipboard.',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant={variant}
|
||||
size={size}
|
||||
onClick={handleShare}
|
||||
className={cn(
|
||||
sizeClasses[size],
|
||||
'transition-colors duration-200 text-cyber-neutral hover:text-cyber-light',
|
||||
className
|
||||
)}
|
||||
title="Copy link"
|
||||
>
|
||||
<Share2 size={iconSize[size]} />
|
||||
{showText && (
|
||||
<span className="ml-2 text-xs">Share</span>
|
||||
)}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user