Browse Source

bug-fixes

imwald
Silberengel 2 months ago
parent
commit
a9ec1bf0f4
  1. 2
      src/components/Note/LiveEvent.tsx
  2. 2
      src/components/Note/LongFormArticlePreview.tsx
  3. 2
      src/components/Note/PublicationCard.tsx
  4. 2
      src/components/Note/WikiCard.tsx
  5. 11
      src/components/PostEditor/PostRelaySelector.tsx
  6. 2
      src/components/PostEditor/PostTextarea/Emoji/EmojiList.tsx
  7. 7
      src/components/PostEditor/PostTextarea/Mention/MentionList.tsx
  8. 22
      src/components/Profile/index.tsx
  9. 4
      src/components/ui/dialog.tsx
  10. 2
      src/components/ui/popover.tsx
  11. 68
      src/index.css
  12. 4
      src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx

2
src/components/Note/LiveEvent.tsx

@ -23,7 +23,7 @@ export default function LiveEvent({ event, className }: { event: Event; classNam
<Badge variant="secondary">{metadata.status}</Badge> <Badge variant="secondary">{metadata.status}</Badge>
)) ))
const titleComponent = <div className="text-xl font-semibold line-clamp-1">{metadata.title}</div> const titleComponent = <div className="text-xl font-semibold break-words min-w-0 sm:line-clamp-1">{metadata.title}</div>
const summaryComponent = metadata.summary && ( const summaryComponent = metadata.summary && (
<div className="text-base text-muted-foreground line-clamp-4">{metadata.summary}</div> <div className="text-base text-muted-foreground line-clamp-4">{metadata.summary}</div>

2
src/components/Note/LongFormArticlePreview.tsx

@ -24,7 +24,7 @@ export default function LongFormArticlePreview({
push(toNote(event.id)) push(toNote(event.id))
} }
const titleComponent = <div className="text-xl font-semibold line-clamp-2">{metadata.title}</div> const titleComponent = <div className="text-xl font-semibold break-words min-w-0 sm:line-clamp-2">{metadata.title}</div>
const tagsComponent = metadata.tags.length > 0 && ( const tagsComponent = metadata.tags.length > 0 && (
<div className="flex gap-1 flex-wrap"> <div className="flex gap-1 flex-wrap">

2
src/components/Note/PublicationCard.tsx

@ -28,7 +28,7 @@ export default function PublicationCard({
push(toNote(event.id)) push(toNote(event.id))
} }
const titleComponent = metadata.title ? <div className="text-xl font-semibold line-clamp-2">{metadata.title}</div> : null const titleComponent = metadata.title ? <div className="text-xl font-semibold break-words min-w-0 sm:line-clamp-2">{metadata.title}</div> : null
const formatBookName = (book: string) => { const formatBookName = (book: string) => {
return book return book

2
src/components/Note/WikiCard.tsx

@ -24,7 +24,7 @@ export default function WikiCard({
push(toNote(event.id)) push(toNote(event.id))
} }
const titleComponent = <div className="text-xl font-semibold line-clamp-2">{metadata.title}</div> const titleComponent = <div className="text-xl font-semibold break-words min-w-0 sm:line-clamp-2">{metadata.title}</div>
const tagsComponent = metadata.tags.length > 0 && ( const tagsComponent = metadata.tags.length > 0 && (
<div className="flex gap-1 flex-wrap"> <div className="flex gap-1 flex-wrap">

11
src/components/PostEditor/PostRelaySelector.tsx

@ -15,7 +15,6 @@ import relaySelectionService, { type RelaySourceType } from '@/services/relay-se
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet' import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet'
import { ScrollArea } from '@/components/ui/scroll-area'
import logger from '@/lib/logger' import logger from '@/lib/logger'
export default function PostRelaySelector({ export default function PostRelaySelector({
@ -390,9 +389,9 @@ export default function PostRelaySelector({
<span className="text-sm text-muted-foreground truncate">{description}</span> <span className="text-sm text-muted-foreground truncate">{description}</span>
</div> </div>
</div> </div>
<ScrollArea className="flex-1 p-4"> <div className="flex-1 min-h-0 overflow-y-scroll overflow-x-hidden p-4">
{content} {content}
</ScrollArea> </div>
</div> </div>
</SheetContent> </SheetContent>
</Sheet> </Sheet>
@ -417,14 +416,14 @@ export default function PostRelaySelector({
<ChevronDown className="w-3 h-3 shrink-0" /> <ChevronDown className="w-3 h-3 shrink-0" />
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent className="w-[90vw] max-w-md p-0 max-h-[40vh] flex flex-col" align="start" side="bottom" sideOffset={8}> <PopoverContent className="w-[90vw] max-w-md p-0 max-h-[40vh] flex flex-col overflow-hidden" align="start" side="bottom" sideOffset={8}>
<div className="p-3 border-b flex items-center justify-between shrink-0"> <div className="p-3 border-b flex items-center justify-between shrink-0">
<span className="text-sm font-medium">{t('Select relays')}</span> <span className="text-sm font-medium">{t('Select relays')}</span>
<span className="text-xs text-muted-foreground truncate ml-2">{description}</span> <span className="text-xs text-muted-foreground truncate ml-2">{description}</span>
</div> </div>
<ScrollArea className="p-3 max-h-[30vh]"> <div className="max-h-[35vh] min-h-0 overflow-y-scroll overflow-x-hidden p-3">
{content} {content}
</ScrollArea> </div>
</PopoverContent> </PopoverContent>
</Popover> </Popover>
</div> </div>

2
src/components/PostEditor/PostTextarea/Emoji/EmojiList.tsx

@ -69,7 +69,7 @@ export const EmojiList = forwardRef<EmojiListHandler, EmojiListProps>((props, re
return ( return (
<ScrollArea <ScrollArea
className="border rounded-lg bg-background z-50 pointer-events-auto flex flex-col max-h-80 overflow-y-auto" className="border rounded-lg bg-background z-[110] pointer-events-auto flex flex-col max-h-80 overflow-y-auto"
onWheel={(e) => e.stopPropagation()} onWheel={(e) => e.stopPropagation()}
onTouchMove={(e) => e.stopPropagation()} onTouchMove={(e) => e.stopPropagation()}
> >

7
src/components/PostEditor/PostTextarea/Mention/MentionList.tsx

@ -1,4 +1,3 @@
import { ScrollArea } from '@/components/ui/scroll-area'
import { formatNpub, userIdToPubkey } from '@/lib/pubkey' import { formatNpub, userIdToPubkey } from '@/lib/pubkey'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { SuggestionKeyDownProps } from '@tiptap/suggestion' import { SuggestionKeyDownProps } from '@tiptap/suggestion'
@ -77,8 +76,8 @@ const MentionList = forwardRef<MentionListHandle, MentionListProps>((props, ref)
} }
return ( return (
<ScrollArea <div
className="border rounded-lg bg-background z-50 pointer-events-auto flex flex-col max-h-80 overflow-y-auto" className="border rounded-lg bg-background z-[110] pointer-events-auto flex flex-col max-h-80 min-h-0 overflow-y-scroll overflow-x-hidden"
onWheel={(e: React.WheelEvent) => e.stopPropagation()} onWheel={(e: React.WheelEvent) => e.stopPropagation()}
onTouchMove={(e: React.TouchEvent) => e.stopPropagation()} onTouchMove={(e: React.TouchEvent) => e.stopPropagation()}
> >
@ -101,7 +100,7 @@ const MentionList = forwardRef<MentionListHandle, MentionListProps>((props, ref)
</div> </div>
</button> </button>
))} ))}
</ScrollArea> </div>
) )
}) })
MentionList.displayName = 'MentionList' MentionList.displayName = 'MentionList'

22
src/components/Profile/index.tsx

@ -417,9 +417,9 @@ export default function Profile({ id }: { id?: string }) {
)} )}
{/* Display payment info from kind 10133 */} {/* Display payment info from kind 10133 */}
{paymentInfo && ((paymentInfo.methods && paymentInfo.methods.length > 0) || paymentInfo.payto) && ( {paymentInfo && ((paymentInfo.methods && paymentInfo.methods.length > 0) || paymentInfo.payto) && (
<div className="mt-2 p-2 border rounded-lg bg-muted/50"> <div className="mt-2 p-2 border rounded-lg bg-muted/50 min-w-0 overflow-hidden">
<div className="text-xs font-semibold text-muted-foreground mb-2">Payment Methods</div> <div className="text-xs font-semibold text-muted-foreground mb-2">Payment Methods</div>
<div className="space-y-2"> <div className="space-y-2 min-w-0">
{paymentInfo.methods && paymentInfo.methods.length > 0 ? ( {paymentInfo.methods && paymentInfo.methods.length > 0 ? (
paymentInfo.methods.map((method, idx) => { paymentInfo.methods.map((method, idx) => {
// NIP-A3: type is in method.type, authority is in method.authority // NIP-A3: type is in method.type, authority is in method.authority
@ -428,12 +428,12 @@ export default function Profile({ id }: { id?: string }) {
const paytoUri = method.payto || (method.type && authority ? `payto://${method.type}/${authority}` : undefined) const paytoUri = method.payto || (method.type && authority ? `payto://${method.type}/${authority}` : undefined)
return ( return (
<div key={idx} className="text-sm"> <div key={idx} className="text-sm min-w-0">
<div className="font-medium">{displayType}</div> <div className="font-medium">{displayType}</div>
{authority && ( {authority && (
<div className="text-muted-foreground mt-1 flex items-center gap-2"> <div className="text-muted-foreground mt-1 flex items-center gap-2 min-w-0">
{method.type === 'lightning' && <Zap className="size-3 text-yellow-400" />} {method.type === 'lightning' && <Zap className="size-3 text-yellow-400 shrink-0" />}
<span className="select-text">{authority}</span> <span className="select-text min-w-0 break-all">{authority}</span>
</div> </div>
)} )}
{paytoUri && ( {paytoUri && (
@ -441,7 +441,7 @@ export default function Profile({ id }: { id?: string }) {
href={paytoUri} href={paytoUri}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="text-muted-foreground text-xs mt-1 hover:underline" className="text-muted-foreground text-xs mt-1 hover:underline block break-all min-w-0"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
{paytoUri} {paytoUri}
@ -463,11 +463,11 @@ export default function Profile({ id }: { id?: string }) {
) : ( ) : (
// Display payto from root level if methods array is empty // Display payto from root level if methods array is empty
paymentInfo.payto && ( paymentInfo.payto && (
<div className="text-sm"> <div className="text-sm min-w-0">
<div className="font-medium">Lightning Network</div> <div className="font-medium">Lightning Network</div>
<div className="text-muted-foreground mt-1 flex items-center gap-2"> <div className="text-muted-foreground mt-1 flex items-center gap-2 min-w-0">
<Zap className="size-3 text-yellow-400" /> <Zap className="size-3 text-yellow-400 shrink-0" />
<span>{paymentInfo.payto}</span> <span className="select-text min-w-0 break-all">{paymentInfo.payto}</span>
</div> </div>
{paymentInfo.currency && ( {paymentInfo.currency && (
<div className="text-muted-foreground text-xs mt-1">({paymentInfo.currency})</div> <div className="text-muted-foreground text-xs mt-1">({paymentInfo.currency})</div>

4
src/components/ui/dialog.tsx

@ -58,7 +58,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay <DialogPrimitive.Overlay
ref={ref} ref={ref}
className={cn( className={cn(
'fixed inset-0 z-40 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0', 'fixed inset-0 z-[100] bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
className className
)} )}
{...props} {...props}
@ -77,7 +77,7 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content <DialogPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
'fixed left-[50%] top-[50%] z-40 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 sm:border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg', 'fixed left-[50%] top-[50%] z-[100] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 sm:border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
className className
)} )}
{...props} {...props}

2
src/components/ui/popover.tsx

@ -20,7 +20,7 @@ const PopoverContent = React.forwardRef<
sideOffset={sideOffset} sideOffset={sideOffset}
collisionPadding={10} collisionPadding={10}
className={cn( className={cn(
'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', 'z-[110] w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className className
)} )}
onOpenAutoFocus={(e) => e.preventDefault()} onOpenAutoFocus={(e) => e.preventDefault()}

68
src/index.css

@ -444,3 +444,71 @@
display: block; display: block;
margin: 0.25rem 0; margin: 0.25rem 0;
} }
/* Lightbox (yet-another-react-lightbox) caption title: wrap on narrow screens instead of truncating */
.yarl__slide_title {
white-space: normal !important;
overflow: visible !important;
text-overflow: unset !important;
word-wrap: break-word;
}
/* Lightbox: responsive on narrow screens so images are not cut off */
.yarl__portal {
inset: 0;
width: 100%;
height: 100%;
}
@supports (height: 100dvh) {
.yarl__portal {
height: 100dvh;
}
}
.yarl__container {
height: 100%;
min-height: 0;
width: 100%;
}
.yarl__carousel {
min-height: 0;
}
.yarl__slide {
min-height: 0;
min-width: 0;
display: flex;
align-items: center;
justify-content: center;
}
.yarl__slide_image {
max-height: 100% !important;
max-width: 100% !important;
width: auto !important;
height: auto !important;
object-fit: contain !important;
}
/* Ensure slide wrapper allows image to shrink and fit viewport on narrow screens */
.yarl__slide_wrapper {
min-height: 0;
flex: 1;
display: flex !important;
align-items: center;
justify-content: center;
width: 100%;
max-width: 100%;
}
.yarl__slide_wrapper .yarl__slide_image {
max-height: 100% !important;
max-width: 100% !important;
}
@media (max-width: 768px) {
.yarl__slide_captions_container {
padding: 12px;
}
.yarl__toolbar {
padding: 8px;
}
.yarl__navigation_prev,
.yarl__navigation_next {
padding: 12px 8px;
}
}

4
src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx

@ -587,11 +587,11 @@ export default function CreateThreadDialog({
sideOffset={4} sideOffset={4}
> >
<div className="max-h-60 overflow-y-auto"> <div className="max-h-60 overflow-y-auto">
{allAvailableTopics.map((topic) => { {allAvailableTopics.map((topic, index) => {
const Icon = topic.icon const Icon = topic.icon
return ( return (
<div <div
key={topic.id} key={`topic-${index}-${topic.id}`}
className="flex items-center p-2 hover:bg-accent cursor-pointer rounded" className="flex items-center p-2 hover:bg-accent cursor-pointer rounded"
onClick={() => { onClick={() => {
setSelectedTopic(topic.id) setSelectedTopic(topic.id)

Loading…
Cancel
Save