chore: format
This commit is contained in:
parent
4bd4141b54
commit
e490407dd5
225 changed files with 924 additions and 844 deletions
|
|
@ -22,7 +22,7 @@ function BookmarkPageTitlebar() {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 items-center h-full pl-3">
|
||||
<div className="flex h-full items-center gap-2 pl-3">
|
||||
<BookmarkIcon />
|
||||
<div className="text-lg font-semibold">{t('Bookmarks')}</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ function ExplorePageTitlebar() {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 justify-between h-full">
|
||||
<div className="flex gap-2 items-center h-full pl-3">
|
||||
<div className="flex h-full justify-between gap-2">
|
||||
<div className="flex h-full items-center gap-2 pl-3">
|
||||
<Compass />
|
||||
<div className="text-lg font-semibold">{t('Explore')}</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ const MePage = forwardRef<TPageRef>((_, ref) => {
|
|||
titlebar={<MePageTitlebar />}
|
||||
hideTitlebarBottomBorder
|
||||
>
|
||||
<div className="flex flex-col p-4 gap-4 overflow-auto">
|
||||
<div className="flex flex-col gap-4 overflow-auto p-4">
|
||||
<AccountManager />
|
||||
</div>
|
||||
</PrimaryPageLayout>
|
||||
|
|
@ -55,15 +55,15 @@ const MePage = forwardRef<TPageRef>((_, ref) => {
|
|||
titlebar={<MePageTitlebar />}
|
||||
hideTitlebarBottomBorder
|
||||
>
|
||||
<div className="flex gap-4 items-center p-4">
|
||||
<div className="flex items-center gap-4 p-4">
|
||||
<SimpleUserAvatar userId={pubkey} size="big" />
|
||||
<div className="space-y-1 flex-1 w-0">
|
||||
<div className="w-0 flex-1 space-y-1">
|
||||
<SimpleUsername
|
||||
className="text-xl font-semibold text-wrap"
|
||||
className="text-wrap text-xl font-semibold"
|
||||
userId={pubkey}
|
||||
skeletonClassName="h-6 w-32"
|
||||
/>
|
||||
<div className="flex gap-1 mt-1">
|
||||
<div className="mt-1 flex gap-1">
|
||||
<PubkeyCopy pubkey={pubkey} />
|
||||
<NpubQrCode pubkey={pubkey} />
|
||||
</div>
|
||||
|
|
@ -108,7 +108,7 @@ export default MePage
|
|||
function MePageTitlebar() {
|
||||
const { push } = useSecondaryPage()
|
||||
return (
|
||||
<div className="flex justify-end items-center">
|
||||
<div className="flex items-center justify-end">
|
||||
<Button variant="ghost" size="titlebar-icon" onClick={() => push(toSettings())}>
|
||||
<Settings />
|
||||
</Button>
|
||||
|
|
@ -125,7 +125,7 @@ function Item({
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex clickable justify-between items-center px-4 py-2 h-[52px] rounded-lg [&_svg]:size-4 [&_svg]:shrink-0',
|
||||
'clickable flex h-[52px] items-center justify-between rounded-lg px-4 py-2 [&_svg]:size-4 [&_svg]:shrink-0',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export default function FeedButton({ className }: { className?: string }) {
|
|||
<Drawer open={open} onOpenChange={setOpen}>
|
||||
<DrawerContent className="max-h-[85vh]">
|
||||
<div
|
||||
className="flex-1 overflow-y-auto overscroll-contain py-3 px-4"
|
||||
className="flex-1 overflow-y-auto overscroll-contain px-4 py-3"
|
||||
style={{
|
||||
touchAction: 'pan-y',
|
||||
WebkitOverflowScrolling: 'touch'
|
||||
|
|
@ -41,9 +41,9 @@ export default function FeedButton({ className }: { className?: string }) {
|
|||
<PopoverTrigger asChild>
|
||||
<FeedSwitcherTrigger className={className} />
|
||||
</PopoverTrigger>
|
||||
<PopoverContent sideOffset={0} side="bottom" className="w-[400px] p-0 overflow-hidden">
|
||||
<PopoverContent sideOffset={0} side="bottom" className="w-[400px] overflow-hidden p-0">
|
||||
<div
|
||||
className="max-h-[calc(100vh-16rem)] overflow-y-auto overscroll-contain py-3 px-4"
|
||||
className="max-h-[calc(100vh-16rem)] overflow-y-auto overscroll-contain px-4 py-3"
|
||||
onWheel={(e) => e.stopPropagation()}
|
||||
onTouchMove={(e) => e.stopPropagation()}
|
||||
>
|
||||
|
|
@ -94,12 +94,12 @@ const FeedSwitcherTrigger = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivEle
|
|||
|
||||
return (
|
||||
<div
|
||||
className={cn('flex items-center gap-2 clickable px-3 h-full rounded-xl', className)}
|
||||
className={cn('clickable flex h-full items-center gap-2 rounded-xl px-3', className)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
{icon}
|
||||
<div className="text-lg font-semibold truncate">{title}</div>
|
||||
<div className="truncate text-lg font-semibold">{title}</div>
|
||||
<ChevronDown />
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -44,15 +44,15 @@ export default function FollowingFeed() {
|
|||
// Show empty state when user has no followings
|
||||
if (hasFollowings === false && subRequests.length > 0) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-[60vh] px-6 text-center">
|
||||
<UserPlus size={64} className="text-muted-foreground mb-4" strokeWidth={1.5} />
|
||||
<h2 className="text-2xl font-semibold mb-2">{t('Welcome to Jumble!')}</h2>
|
||||
<p className="text-muted-foreground mb-6 max-w-md">
|
||||
<div className="flex min-h-[60vh] flex-col items-center justify-center px-6 text-center">
|
||||
<UserPlus size={64} className="mb-4 text-muted-foreground" strokeWidth={1.5} />
|
||||
<h2 className="mb-2 text-2xl font-semibold">{t('Welcome to Jumble!')}</h2>
|
||||
<p className="mb-6 max-w-md text-muted-foreground">
|
||||
{t(
|
||||
'Your feed is empty because you are not following anyone yet. Start by exploring interesting content and following users you like!'
|
||||
)}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-3 w-full max-w-md">
|
||||
<div className="flex w-full max-w-md flex-col gap-3 sm:flex-row">
|
||||
<Button size="lg" onClick={() => navigate('explore')} className="w-full">
|
||||
<Compass className="size-5" />
|
||||
{t('Explore')}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ const NoteListPage = forwardRef<TPageRef>((_, ref) => {
|
|||
let content: React.ReactNode = null
|
||||
if (!isReady) {
|
||||
content = (
|
||||
<div className="text-center text-sm text-muted-foreground pt-3">{t('loading...')}</div>
|
||||
<div className="pt-3 text-center text-sm text-muted-foreground">{t('loading...')}</div>
|
||||
)
|
||||
} else if (!feedInfo) {
|
||||
content = <WelcomeGuide />
|
||||
|
|
@ -112,9 +112,9 @@ function NoteListPageTitlebar({
|
|||
const { isSmallScreen } = useScreenSize()
|
||||
|
||||
return (
|
||||
<div className="flex gap-1 items-center h-full justify-between">
|
||||
<FeedButton className="flex-1 max-w-fit w-0" />
|
||||
<div className="shrink-0 flex gap-1 items-center">
|
||||
<div className="flex h-full items-center justify-between gap-1">
|
||||
<FeedButton className="w-0 max-w-fit flex-1" />
|
||||
<div className="flex shrink-0 items-center gap-1">
|
||||
{setShowRelayDetails && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
|
|
@ -182,21 +182,21 @@ function WelcomeGuide() {
|
|||
const { checkLogin } = useNostr()
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-[60vh] px-4 text-center space-y-6">
|
||||
<div className="flex min-h-[60vh] flex-col items-center justify-center space-y-6 px-4 text-center">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center w-full justify-center gap-2">
|
||||
<div className="flex w-full items-center justify-center gap-2">
|
||||
<Sparkles className="text-yellow-400" />
|
||||
<h2 className="text-2xl font-bold">{t('Welcome to Jumble')}</h2>
|
||||
<Sparkles className="text-yellow-400" />
|
||||
</div>
|
||||
<p className="text-muted-foreground max-w-md">
|
||||
<p className="max-w-md text-muted-foreground">
|
||||
{t(
|
||||
'Jumble is a client focused on browsing relays. Get started by exploring interesting relays or login to view your following feed.'
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-3 w-full max-w-md">
|
||||
<div className="flex w-full max-w-md flex-col gap-3 sm:flex-row">
|
||||
<Button size="lg" className="w-full" onClick={() => navigate('explore')}>
|
||||
<Compass className="size-5" />
|
||||
{t('Explore')}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ function NotificationListPageTitlebar() {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 items-center justify-between h-full pl-3">
|
||||
<div className="flex h-full items-center justify-between gap-2 pl-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<Bell />
|
||||
<div className="text-lg font-semibold">{t('Notifications')}</div>
|
||||
|
|
@ -77,8 +77,8 @@ function HideUnrelatedNotificationsToggle() {
|
|||
<Button
|
||||
variant="ghost"
|
||||
className={cn(
|
||||
'h-10 px-3 shrink-0 rounded-xl [&_svg]:size-5',
|
||||
hideIndirect ? 'text-foreground bg-muted/40' : 'text-muted-foreground'
|
||||
'h-10 shrink-0 rounded-xl px-3 [&_svg]:size-5',
|
||||
hideIndirect ? 'bg-muted/40 text-foreground' : 'text-muted-foreground'
|
||||
)}
|
||||
onClick={() => updateHideIndirect(!hideIndirect)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ function ProfilePageTitlebar() {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 items-center h-full pl-3">
|
||||
<div className="flex h-full items-center gap-2 pl-3">
|
||||
<UserRound />
|
||||
<div className="text-lg font-semibold">{t('Profile')}</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ export default RelayPage
|
|||
|
||||
function RelayPageTitlebar({ url }: { url?: string }) {
|
||||
return (
|
||||
<div className="flex items-center gap-2 px-3 h-full">
|
||||
<div className="flex h-full items-center gap-2 px-3">
|
||||
<Server />
|
||||
<div className="text-lg font-semibold truncate">{simplifyUrl(url ?? '')}</div>
|
||||
<div className="truncate text-lg font-semibold">{simplifyUrl(url ?? '')}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ function SettingsPageTitlebar() {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 items-center h-full pl-3">
|
||||
<div className="flex h-full items-center gap-2 pl-3">
|
||||
<SettingsIcon />
|
||||
<div className="text-lg font-semibold">{t('Settings')}</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ const AppearanceSettingsPage = forwardRef(({ index }: { index?: number }, ref) =
|
|||
|
||||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={t('Appearance')}>
|
||||
<div className="space-y-4 my-3">
|
||||
<div className="my-3 space-y-4">
|
||||
<div className="flex flex-col gap-2 px-4">
|
||||
<Label className="text-base">{t('Theme')}</Label>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 w-full">
|
||||
<div className="grid w-full grid-cols-2 gap-4 md:grid-cols-4">
|
||||
{THEMES.map(({ key, label, icon }) => (
|
||||
<OptionButton
|
||||
key={key}
|
||||
|
|
@ -57,7 +57,7 @@ const AppearanceSettingsPage = forwardRef(({ index }: { index?: number }, ref) =
|
|||
{!isSmallScreen && (
|
||||
<div className="flex flex-col gap-2 px-4">
|
||||
<Label className="text-base">{t('Layout')}</Label>
|
||||
<div className="grid grid-cols-2 gap-4 w-full">
|
||||
<div className="grid w-full grid-cols-2 gap-4">
|
||||
{LAYOUTS.map(({ key, label, icon }) => (
|
||||
<OptionButton
|
||||
key={key.toString()}
|
||||
|
|
@ -72,7 +72,7 @@ const AppearanceSettingsPage = forwardRef(({ index }: { index?: number }, ref) =
|
|||
)}
|
||||
<div className="flex flex-col gap-2 px-4">
|
||||
<Label className="text-base">{t('Notification list style')}</Label>
|
||||
<div className="grid grid-cols-2 gap-4 w-full">
|
||||
<div className="grid w-full grid-cols-2 gap-4">
|
||||
{NOTIFICATION_STYLES.map(({ key, label, icon }) => (
|
||||
<OptionButton
|
||||
key={key}
|
||||
|
|
@ -86,7 +86,7 @@ const AppearanceSettingsPage = forwardRef(({ index }: { index?: number }, ref) =
|
|||
</div>
|
||||
<div className="flex flex-col gap-2 px-4">
|
||||
<Label className="text-base">{t('Primary color')}</Label>
|
||||
<div className="grid grid-cols-4 gap-4 w-full">
|
||||
<div className="grid w-full grid-cols-4 gap-4">
|
||||
{Object.entries(PRIMARY_COLORS).map(([key, config]) => (
|
||||
<OptionButton
|
||||
key={key}
|
||||
|
|
@ -127,11 +127,11 @@ const OptionButton = ({
|
|||
<button
|
||||
onClick={onClick}
|
||||
className={cn(
|
||||
'flex flex-col items-center gap-2 py-4 rounded-lg border-2 transition-all',
|
||||
'flex flex-col items-center gap-2 rounded-lg border-2 py-4 transition-all',
|
||||
isSelected ? 'border-primary' : 'border-border hover:border-muted-foreground/40'
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center justify-center w-8 h-8">{icon}</div>
|
||||
<div className="flex h-8 w-8 items-center justify-center">{icon}</div>
|
||||
<span className="text-xs font-medium">{label}</span>
|
||||
</button>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const ExternalContentPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
title={t('External Content')}
|
||||
displayScrollToTopButton
|
||||
>
|
||||
<div className="px-4 mt-3">
|
||||
<div className="mt-3 px-4">
|
||||
<ExternalContent content={id} mustLoadMedia />
|
||||
<StuffStats className="mt-3" stuff={id} fetchIfNotExisting displayTopZapsAndLikes />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ const FollowPackPage = forwardRef(({ id, index }: { id?: string; index?: number
|
|||
if (isFetching) {
|
||||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={t('Follow Pack')}>
|
||||
<div className="px-4 py-3 space-y-2">
|
||||
<div className="space-y-2 px-4 py-3">
|
||||
<Skeleton className="h-48 w-full" />
|
||||
<Skeleton className="h-7 py-1 w-full" />
|
||||
<Skeleton className="h-7 w-full py-1" />
|
||||
</div>
|
||||
</SecondaryPageLayout>
|
||||
)
|
||||
|
|
@ -47,11 +47,11 @@ const FollowPackPage = forwardRef(({ id, index }: { id?: string; index?: number
|
|||
<SecondaryPageLayout ref={ref} index={index} title={t('Follow Pack')} displayScrollToTopButton>
|
||||
<div>
|
||||
{/* Header */}
|
||||
<div className="px-4 pt-3 space-y-2">
|
||||
<div className="space-y-2 px-4 pt-3">
|
||||
{image && (
|
||||
<ImageWithLightbox
|
||||
image={{ url: image, pubkey: event.pubkey }}
|
||||
className="w-full h-48 object-cover rounded-lg"
|
||||
className="h-48 w-full rounded-lg object-cover"
|
||||
classNames={{
|
||||
wrapper: 'w-full h-48 border-none'
|
||||
}}
|
||||
|
|
@ -59,21 +59,21 @@ const FollowPackPage = forwardRef(({ id, index }: { id?: string; index?: number
|
|||
)}
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className="text-2xl font-semibold mb-1 truncate">{title}</h3>
|
||||
<span className="text-xs text-muted-foreground shrink-0">
|
||||
<h3 className="mb-1 truncate text-2xl font-semibold">{title}</h3>
|
||||
<span className="shrink-0 text-xs text-muted-foreground">
|
||||
{t('n users', { count: pubkeys.length })}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{description && (
|
||||
<p className="text-sm text-muted-foreground whitespace-pre-wrap">{description}</p>
|
||||
<p className="whitespace-pre-wrap text-sm text-muted-foreground">{description}</p>
|
||||
)}
|
||||
|
||||
<div className="inline-flex items-center rounded-lg border bg-muted/50">
|
||||
<button
|
||||
onClick={() => setTab('users')}
|
||||
className={cn(
|
||||
'px-3 py-1.5 text-sm font-medium rounded-l-lg transition-colors',
|
||||
'rounded-l-lg px-3 py-1.5 text-sm font-medium transition-colors',
|
||||
tab === 'users'
|
||||
? 'bg-background text-foreground shadow-sm'
|
||||
: 'text-muted-foreground hover:text-foreground'
|
||||
|
|
@ -84,7 +84,7 @@ const FollowPackPage = forwardRef(({ id, index }: { id?: string; index?: number
|
|||
<button
|
||||
onClick={() => setTab('feed')}
|
||||
className={cn(
|
||||
'px-3 py-1.5 text-sm font-medium rounded-r-lg transition-colors',
|
||||
'rounded-r-lg px-3 py-1.5 text-sm font-medium transition-colors',
|
||||
tab === 'feed'
|
||||
? 'bg-background text-foreground shadow-sm'
|
||||
: 'text-muted-foreground hover:text-foreground'
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export default function MutedWords() {
|
|||
{mutedWords.map((word) => (
|
||||
<div
|
||||
key={word}
|
||||
className="flex items-center gap-1 bg-muted px-2 py-1 rounded-md text-sm"
|
||||
className="flex items-center gap-1 rounded-md bg-muted px-2 py-1 text-sm"
|
||||
>
|
||||
<span>{word}</span>
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const SettingItem = forwardRef<HTMLDivElement, HTMLProps<HTMLDivElement>>(
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex justify-between select-none items-center px-4 min-h-9 [&_svg]:size-4 [&_svg]:shrink-0',
|
||||
'flex min-h-9 select-none items-center justify-between px-4 [&_svg]:size-4 [&_svg]:shrink-0',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ const GeneralSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
|
||||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={t('General')}>
|
||||
<div className="space-y-4 mt-3">
|
||||
<div className="mt-3 space-y-4">
|
||||
<SettingItem>
|
||||
<Label htmlFor="languages" className="text-base font-normal">
|
||||
{t('Languages')}
|
||||
|
|
|
|||
|
|
@ -82,18 +82,18 @@ function UserItem({ pubkey }: { pubkey: string }) {
|
|||
const [switching, setSwitching] = useState(false)
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 items-start">
|
||||
<div className="flex items-start gap-2">
|
||||
<UserAvatar userId={pubkey} className="shrink-0" />
|
||||
<div className="w-full overflow-hidden">
|
||||
<Username
|
||||
userId={pubkey}
|
||||
className="font-semibold truncate max-w-full w-fit"
|
||||
className="w-fit max-w-full truncate font-semibold"
|
||||
skeletonClassName="h-4"
|
||||
/>
|
||||
<Nip05 pubkey={pubkey} />
|
||||
<div className="truncate text-muted-foreground text-sm">{profile?.about}</div>
|
||||
<div className="truncate text-sm text-muted-foreground">{profile?.about}</div>
|
||||
</div>
|
||||
<div className="flex gap-2 items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
{switching ? (
|
||||
<Button disabled variant="ghost" size="icon">
|
||||
<Loader className="animate-spin" />
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ const NoteListPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
setTitle(
|
||||
<div className="flex items-center gap-1">
|
||||
{domain}
|
||||
<Favicon domain={domain} className="w-5 h-5" />
|
||||
<Favicon domain={domain} className="h-5 w-5" />
|
||||
</div>
|
||||
)
|
||||
const pubkeys = await fetchPubkeysFromDomain(domain)
|
||||
|
|
@ -101,7 +101,7 @@ const NoteListPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
let content: React.ReactNode = null
|
||||
if (data?.type === 'domain' && subRequests.length === 0) {
|
||||
content = (
|
||||
<div className="text-center w-full py-10">
|
||||
<div className="w-full py-10 text-center">
|
||||
<span className="text-muted-foreground">
|
||||
{t('No pubkeys found from {url}', { url: getWellKnownNip05Url(data.domain) })}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export default function NotFound({ bech32Id }: { bech32Id?: string }) {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="text-muted-foreground w-full h-full flex flex-col items-center justify-center gap-2">
|
||||
<div className="flex h-full w-full flex-col items-center justify-center gap-2 text-muted-foreground">
|
||||
<div>{t('Note not found')}</div>
|
||||
<ClientSelect originalNoteId={bech32Id} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref
|
|||
<SecondaryPageLayout ref={ref} index={index} title={t('Note')}>
|
||||
<div className="px-4 pt-3">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Skeleton className="w-10 h-10 rounded-full" />
|
||||
<div className={`flex-1 w-0`}>
|
||||
<Skeleton className="h-10 w-10 rounded-full" />
|
||||
<div className={`w-0 flex-1`}>
|
||||
<div className="py-1">
|
||||
<Skeleton className="h-4 w-16" />
|
||||
</div>
|
||||
|
|
@ -55,10 +55,10 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref
|
|||
</div>
|
||||
<div className="pt-2">
|
||||
<div className="my-1">
|
||||
<Skeleton className="w-full h-4 my-1 mt-2" />
|
||||
<Skeleton className="my-1 mt-2 h-4 w-full" />
|
||||
</div>
|
||||
<div className="my-1">
|
||||
<Skeleton className="w-2/3 h-4 my-1" />
|
||||
<Skeleton className="my-1 h-4 w-2/3" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -118,12 +118,12 @@ function ExternalRoot({ value }: { value: string }) {
|
|||
return (
|
||||
<div>
|
||||
<Card
|
||||
className="flex space-x-1 px-1.5 py-1 items-center clickable text-sm text-muted-foreground hover:text-foreground"
|
||||
className="clickable flex items-center space-x-1 px-1.5 py-1 text-sm text-muted-foreground hover:text-foreground"
|
||||
onClick={() => push(toExternalContent(value))}
|
||||
>
|
||||
<div className="truncate">{value}</div>
|
||||
</Card>
|
||||
<div className="ml-5 w-px h-2 bg-border" />
|
||||
<div className="ml-5 h-2 w-px bg-border" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -144,13 +144,13 @@ function ParentNote({
|
|||
if (isFetching) {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex space-x-1 px-[0.4375rem] py-1 items-center rounded-full border clickable text-sm text-muted-foreground">
|
||||
<Skeleton className="shrink w-4 h-4 rounded-full" />
|
||||
<div className="py-1 flex-1">
|
||||
<div className="clickable flex items-center space-x-1 rounded-full border px-[0.4375rem] py-1 text-sm text-muted-foreground">
|
||||
<Skeleton className="h-4 w-4 shrink rounded-full" />
|
||||
<div className="flex-1 py-1">
|
||||
<Skeleton className="h-3" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-5 w-px h-3 bg-border" />
|
||||
<div className="ml-5 h-3 w-px bg-border" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -159,7 +159,7 @@ function ParentNote({
|
|||
<div>
|
||||
<div
|
||||
className={cn(
|
||||
'flex space-x-1 px-[0.4375rem] py-1 items-center rounded-full border clickable text-sm text-muted-foreground',
|
||||
'clickable flex items-center space-x-1 rounded-full border px-[0.4375rem] py-1 text-sm text-muted-foreground',
|
||||
event && 'hover:text-foreground'
|
||||
)}
|
||||
onClick={() => {
|
||||
|
|
@ -170,9 +170,9 @@ function ParentNote({
|
|||
<ContentPreview className="truncate" event={event} />
|
||||
</div>
|
||||
{isConsecutive ? (
|
||||
<div className="ml-5 w-px h-3 bg-border" />
|
||||
<div className="ml-5 h-3 w-px bg-border" />
|
||||
) : (
|
||||
<Ellipsis className="ml-3.5 text-muted-foreground/60 size-3" />
|
||||
<Ellipsis className="ml-3.5 size-3 text-muted-foreground/60" />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -109,12 +109,12 @@ export default function BlossomServerListSetting() {
|
|||
<div className="space-y-2">
|
||||
<div className="text-sm font-medium">{t('Blossom server URLs')}</div>
|
||||
{serverUrls.length === 0 && (
|
||||
<div className="flex flex-col gap-1 text-sm border rounded-lg p-2 bg-muted text-muted-foreground">
|
||||
<div className="font-medium flex gap-2 items-center">
|
||||
<div className="flex flex-col gap-1 rounded-lg border bg-muted p-2 text-sm text-muted-foreground">
|
||||
<div className="flex items-center gap-2 font-medium">
|
||||
<AlertCircle className="size-4" />
|
||||
{t('You need to add at least one media server in order to upload media files.')}
|
||||
</div>
|
||||
<Separator className="bg-muted-foreground my-2" />
|
||||
<Separator className="my-2 bg-muted-foreground" />
|
||||
<div className="font-medium">{t('Recommended blossom servers')}:</div>
|
||||
<div className="flex flex-col">
|
||||
{RECOMMENDED_BLOSSOM_SERVERS.map((recommendedUrl) => (
|
||||
|
|
@ -123,7 +123,7 @@ export default function BlossomServerListSetting() {
|
|||
key={recommendedUrl}
|
||||
onClick={() => addBlossomUrl(recommendedUrl)}
|
||||
disabled={removingIndex >= 0 || adding || movingIndex >= 0}
|
||||
className="w-fit p-0 text-muted-foreground hover:text-foreground h-fit"
|
||||
className="h-fit w-fit p-0 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
{recommendedUrl}
|
||||
</Button>
|
||||
|
|
@ -135,7 +135,7 @@ export default function BlossomServerListSetting() {
|
|||
<div
|
||||
key={url}
|
||||
className={cn(
|
||||
'flex items-center justify-between gap-2 pl-3 pr-1 py-1 border rounded-lg',
|
||||
'flex items-center justify-between gap-2 rounded-lg border py-1 pl-3 pr-1',
|
||||
idx === 0 && 'border-primary'
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const PostSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
|
||||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={t('Post settings')}>
|
||||
<div className="px-4 pt-3 space-y-4">
|
||||
<div className="space-y-4 px-4 pt-3">
|
||||
<MediaUploadServiceSetting />
|
||||
</div>
|
||||
</SecondaryPageLayout>
|
||||
|
|
|
|||
|
|
@ -132,15 +132,15 @@ const ProfileEditorPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
|
||||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={profile.username} controls={controls}>
|
||||
<div className="relative bg-cover bg-center mb-2">
|
||||
<div className="relative mb-2 bg-cover bg-center">
|
||||
<Uploader
|
||||
onUploadSuccess={onBannerUploadSuccess}
|
||||
onUploadStart={() => setUploadingBanner(true)}
|
||||
onUploadEnd={() => setUploadingBanner(false)}
|
||||
className="w-full relative cursor-pointer"
|
||||
className="relative w-full cursor-pointer"
|
||||
>
|
||||
<ProfileBanner banner={banner} pubkey={account.pubkey} className="w-full aspect-[3/1]" />
|
||||
<div className="absolute top-0 bg-muted/30 w-full h-full flex flex-col justify-center items-center">
|
||||
<ProfileBanner banner={banner} pubkey={account.pubkey} className="aspect-[3/1] w-full" />
|
||||
<div className="absolute top-0 flex h-full w-full flex-col items-center justify-center bg-muted/30">
|
||||
{uploadingBanner ? <Loader size={36} className="animate-spin" /> : <Upload size={36} />}
|
||||
</div>
|
||||
</Uploader>
|
||||
|
|
@ -148,20 +148,20 @@ const ProfileEditorPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
onUploadSuccess={onAvatarUploadSuccess}
|
||||
onUploadStart={() => setUploadingAvatar(true)}
|
||||
onUploadEnd={() => setUploadingAvatar(false)}
|
||||
className="w-24 h-24 absolute bottom-0 left-4 translate-y-1/2 border-4 border-background cursor-pointer rounded-full"
|
||||
className="absolute bottom-0 left-4 h-24 w-24 translate-y-1/2 cursor-pointer rounded-full border-4 border-background"
|
||||
>
|
||||
<Avatar className="w-full h-full">
|
||||
<Avatar className="h-full w-full">
|
||||
<AvatarImage src={avatar} className="object-cover object-center" />
|
||||
<AvatarFallback>
|
||||
<img src={defaultImage} />
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="absolute top-0 bg-muted/30 w-full h-full rounded-full flex flex-col justify-center items-center">
|
||||
<div className="absolute top-0 flex h-full w-full flex-col items-center justify-center rounded-full bg-muted/30">
|
||||
{uploadingAvatar ? <Loader className="animate-spin" /> : <Upload />}
|
||||
</div>
|
||||
</Uploader>
|
||||
</div>
|
||||
<div className="pt-14 px-4 flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-4 px-4 pt-14">
|
||||
<Item>
|
||||
<Label htmlFor="profile-username-input">{t('Display Name')}</Label>
|
||||
<Input
|
||||
|
|
@ -208,7 +208,7 @@ const ProfileEditorPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
}}
|
||||
className={nip05Error ? 'border-destructive' : ''}
|
||||
/>
|
||||
{nip05Error && <div className="text-xs text-destructive pl-3">{nip05Error}</div>}
|
||||
{nip05Error && <div className="pl-3 text-xs text-destructive">{nip05Error}</div>}
|
||||
</Item>
|
||||
<Item>
|
||||
<Label htmlFor="profile-lightning-address-input">
|
||||
|
|
@ -225,7 +225,7 @@ const ProfileEditorPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
className={lightningAddressError ? 'border-destructive' : ''}
|
||||
/>
|
||||
{lightningAddressError && (
|
||||
<div className="text-xs text-destructive pl-3">{lightningAddressError}</div>
|
||||
<div className="pl-3 text-xs text-destructive">{lightningAddressError}</div>
|
||||
)}
|
||||
</Item>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const ProfileListPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
setTitle(
|
||||
<div className="flex items-center gap-1">
|
||||
{domain}
|
||||
<Favicon domain={domain} className="w-5 h-5" />
|
||||
<Favicon domain={domain} className="h-5 w-5" />
|
||||
</div>
|
||||
)
|
||||
setData({ type: 'domain', id: domain })
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const RelaySettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
|
||||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={t('Relay settings')}>
|
||||
<Tabs value={tabValue} onValueChange={setTabValue} className="px-4 py-3 space-y-4">
|
||||
<Tabs value={tabValue} onValueChange={setTabValue} className="space-y-4 px-4 py-3">
|
||||
<TabsList>
|
||||
<TabsTrigger value="favorite-relays">{t('Favorite Relays')}</TabsTrigger>
|
||||
<TabsTrigger value="mailbox">{t('Read & Write Relays')}</TabsTrigger>
|
||||
|
|
|
|||
|
|
@ -115,9 +115,9 @@ const RizfulPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
if (connected) {
|
||||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={t('Rizful Vault')}>
|
||||
<div className="px-4 pt-3 space-y-6 flex flex-col items-center">
|
||||
<div className="flex flex-col items-center space-y-6 px-4 pt-3">
|
||||
<CheckCircle2 className="size-40 fill-green-400 text-background" />
|
||||
<div className="font-semibold text-2xl">{t('Rizful Vault connected!')}</div>
|
||||
<div className="text-2xl font-semibold">{t('Rizful Vault connected!')}</div>
|
||||
<div className="text-center text-sm text-muted-foreground">
|
||||
{t('You can now use your Rizful Vault to zap your favorite notes and creators.')}
|
||||
</div>
|
||||
|
|
@ -125,7 +125,7 @@ const RizfulPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
<div className="flex flex-col items-center gap-2">
|
||||
<div>{t('Your Lightning Address')}:</div>
|
||||
<div
|
||||
className="font-semibold text-lg rounded-lg px-4 py-1 flex justify-center items-center gap-2 cursor-pointer hover:bg-accent/80"
|
||||
className="flex cursor-pointer items-center justify-center gap-2 rounded-lg px-4 py-1 text-lg font-semibold hover:bg-accent/80"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(lightningAddress)
|
||||
setCopiedLightningAddress(true)
|
||||
|
|
@ -148,11 +148,11 @@ const RizfulPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
|
||||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={t('Rizful Vault')}>
|
||||
<div className="px-4 pt-3 space-y-6">
|
||||
<div className="space-y-6 px-4 pt-3">
|
||||
<div className="space-y-2">
|
||||
<div className="font-semibold">1. {t('New to Rizful?')}</div>
|
||||
<Button
|
||||
className="bg-lime-500 hover:bg-lime-500/90 w-64"
|
||||
className="w-64 bg-lime-500 hover:bg-lime-500/90"
|
||||
onClick={() => window.open(RIZFUL_SIGNUP_URL, '_blank')}
|
||||
>
|
||||
{t('Sign up for Rizful')} <ExternalLink />
|
||||
|
|
@ -165,7 +165,7 @@ const RizfulPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
<div className="space-y-2">
|
||||
<div className="font-semibold">2. {t('Get your one-time code')}</div>
|
||||
<Button
|
||||
className="bg-orange-500 hover:bg-orange-500/90 w-64"
|
||||
className="w-64 bg-orange-500 hover:bg-orange-500/90"
|
||||
onClick={() => openPopup(RIZFUL_GET_TOKEN_URL, 'rizful_codes')}
|
||||
>
|
||||
{t('Get code')}
|
||||
|
|
@ -183,7 +183,7 @@ const RizfulPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
}}
|
||||
/>
|
||||
<Button
|
||||
className="bg-sky-500 hover:bg-sky-500/90 w-64"
|
||||
className="w-64 bg-sky-500 hover:bg-sky-500/90"
|
||||
disabled={!token || connecting}
|
||||
onClick={() => connectRizful()}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ const SearchPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
ref={ref}
|
||||
index={index}
|
||||
titlebar={
|
||||
<div className="flex items-center gap-1 h-full">
|
||||
<div className="flex h-full items-center gap-1">
|
||||
<Button variant="ghost" size="titlebar-icon" onClick={() => pop()}>
|
||||
<ChevronLeft />
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ const SystemSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
|
||||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={t('System')}>
|
||||
<div className="space-y-4 mt-3">
|
||||
<div className="px-4 space-y-2">
|
||||
<div className="mt-3 space-y-4">
|
||||
<div className="space-y-2 px-4">
|
||||
<Label htmlFor="favicon-url" className="text-base font-normal">
|
||||
{t('Favicon URL')}
|
||||
</Label>
|
||||
|
|
@ -31,7 +31,7 @@ const SystemSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
placeholder={DEFAULT_FAVICON_URL_TEMPLATE}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-between items-center px-4 min-h-9">
|
||||
<div className="flex min-h-9 items-center justify-between px-4">
|
||||
<Label htmlFor="filter-out-onion-relays" className="text-base font-normal">
|
||||
{t('Filter out onion relays')}
|
||||
</Label>
|
||||
|
|
@ -44,7 +44,7 @@ const SystemSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="px-4 space-y-2">
|
||||
<div className="space-y-2 px-4">
|
||||
<DefaultRelaysSetting />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export function AccountInfo() {
|
|||
|
||||
if (!pubkey) {
|
||||
return (
|
||||
<div className="w-full flex justify-center">
|
||||
<div className="flex w-full justify-center">
|
||||
<Button onClick={() => startLogin()}>{t('Login')}</Button>
|
||||
</div>
|
||||
)
|
||||
|
|
@ -43,7 +43,7 @@ export function AccountInfo() {
|
|||
type={showApiKey ? 'text' : 'password'}
|
||||
value={account?.api_key ?? ''}
|
||||
readOnly
|
||||
className="font-mono flex-1 max-w-fit"
|
||||
className="max-w-fit flex-1 font-mono"
|
||||
/>
|
||||
<Button variant="outline" onClick={() => setShowApiKey(!showApiKey)}>
|
||||
{showApiKey ? <Eye /> : <EyeOff />}
|
||||
|
|
@ -62,7 +62,7 @@ export function AccountInfo() {
|
|||
</Button>
|
||||
<RegenerateApiKeyButton />
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground select-text">
|
||||
<p className="select-text text-sm text-muted-foreground">
|
||||
{t('jumbleTranslateApiKeyDescription', {
|
||||
serviceUrl: new URL('/v1/translation', JUMBLE_API_BASE_URL).toString()
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ export default function TopUp() {
|
|||
variant="outline"
|
||||
onClick={() => handlePresetClick(amount)}
|
||||
className={cn(
|
||||
'flex flex-col h-auto py-3 hover:bg-primary/10',
|
||||
'flex h-auto flex-col py-3 hover:bg-primary/10',
|
||||
selectedAmount === amount && 'border border-primary bg-primary/10'
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ const TranslationPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
|
||||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={t('Translation')}>
|
||||
<div className="px-4 pt-3 space-y-4">
|
||||
<div className="space-y-4 px-4 pt-3">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="languages" className="text-base font-medium">
|
||||
{t('Languages')}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ const UserAggregationDetailPage = forwardRef(
|
|||
if (!pubkey || !feedId) {
|
||||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={t('User Posts')}>
|
||||
<div className="flex justify-center items-center h-40 text-muted-foreground">
|
||||
<div className="flex h-40 items-center justify-center text-muted-foreground">
|
||||
{t('Invalid user')}
|
||||
</div>
|
||||
</SecondaryPageLayout>
|
||||
|
|
@ -74,7 +74,7 @@ const UserAggregationDetailPage = forwardRef(
|
|||
{aggregation.map((event) => (
|
||||
<NoteCard key={event.id} className="w-full" event={event} filterMutedNotes={false} />
|
||||
))}
|
||||
<div className="text-center text-sm text-muted-foreground mt-2">{t('no more notes')}</div>
|
||||
<div className="mt-2 text-center text-sm text-muted-foreground">{t('no more notes')}</div>
|
||||
</div>
|
||||
</SecondaryPageLayout>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ export default function QuickZapSwitch() {
|
|||
const { quickZap, updateQuickZap } = useZap()
|
||||
|
||||
return (
|
||||
<div className="w-full flex justify-between items-center">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<Label htmlFor="quick-zap-switch">
|
||||
<div className="text-base font-medium">{t('Quick zap')}</div>
|
||||
<div className="text-muted-foreground text-sm">
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{t('If enabled, you can zap with a single click. Click and hold for custom amounts')}
|
||||
</div>
|
||||
</Label>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const WalletPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
return (
|
||||
<SecondaryPageLayout ref={ref} index={index} title={t('Wallet')}>
|
||||
{isWalletConnected ? (
|
||||
<div className="px-4 pt-3 space-y-4">
|
||||
<div className="space-y-4 px-4 pt-3">
|
||||
<div>
|
||||
{walletInfo?.node.alias && (
|
||||
<div className="mb-2">
|
||||
|
|
@ -63,13 +63,13 @@ const WalletPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
<LightningAddressInput />
|
||||
</div>
|
||||
) : (
|
||||
<div className="px-4 pt-3 flex items-center gap-2">
|
||||
<div className="flex items-center gap-2 px-4 pt-3">
|
||||
<Button className="bg-foreground hover:bg-foreground/90" onClick={() => push(toRizful())}>
|
||||
{t('Start with a Rizful Vault')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
className="text-muted-foreground hover:text-foreground px-0"
|
||||
className="px-0 text-muted-foreground hover:text-foreground"
|
||||
onClick={() => {
|
||||
launchModal()
|
||||
}}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue