Compare commits
No commits in common. "bpistle-music" and "master" have entirely different histories.
bpistle-mu
...
master
|
|
@ -1,2 +0,0 @@
|
|||
VITE_COMMUNITY_RELAYS="wss://basspistol.org/favorites,wss://basspistol.org/popular,wss://basspistol.org/uppermost,wss://basspistol.org/personal"
|
||||
VITE_COMMUNITY_RELAY_SETS=[{"id": "basspistol", "name": "Basspistol", "relayUrls": ["wss://basspistol.org","wss://drops.basspistol.org"]},{"id": "member", "name": "Backstage", "relayUrls": ["wss://basspistol.org/internal"]},{"id": "hood", "name": "Hood", "relayUrls": ["wss://nestr.nedao.ch","wss://pyramid.fiatjaf.com","wss://spatia-arcana.com","wss://lightning.red","wss://inner.sebastix.social"]}]
|
||||
10
README.md
|
|
@ -2,19 +2,15 @@
|
|||
<picture>
|
||||
<img src="./resources/logo-light.svg" alt="Jumble Logo" width="400" />
|
||||
</picture>
|
||||
|
||||
<p>logo designed by <a href="http://wolfertdan.com/">Daniel David</a></p>
|
||||
</div>
|
||||
|
||||
# Bpistle
|
||||
# Jumble
|
||||
|
||||
A community fork of [Jumble](https://github.com/CodyTseng/jumble), the user-friendly Nostr client for exploring relay feeds, made by and for music lovers.
|
||||
|
||||
Experience Bpistle at [https://nostr.basspistol.org](https://nostr.basspistol.org)
|
||||
A user-friendly Nostr client for exploring relay feeds
|
||||
|
||||
Experience Jumble at [https://jumble.social](https://jumble.social)
|
||||
|
||||
Upstream code: https://github.com/CodyTseng/jumble
|
||||
|
||||
## Forks
|
||||
|
||||
> Some interesting forks of Jumble.
|
||||
|
|
|
|||
16
index.html
|
|
@ -4,29 +4,29 @@
|
|||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
|
||||
<title>Bpistle</title>
|
||||
<meta name="description" content="A user-friendly Nostr client for exploring the Basspistol Network" />
|
||||
<title>Jumble</title>
|
||||
<meta name="description" content="A user-friendly Nostr client for exploring relay feeds" />
|
||||
<meta
|
||||
name="keywords"
|
||||
content="basspistol, music, syndicate, creative commons, sovereign, jumble, nostr, web, client, relay, feed, social, pwa, simple, clean"
|
||||
content="jumble, nostr, web, client, relay, feed, social, pwa, simple, clean"
|
||||
/>
|
||||
|
||||
<meta name="apple-mobile-web-app-title" content="Bpistle" />
|
||||
<meta name="apple-mobile-web-app-title" content="Jumble" />
|
||||
<link rel="icon" href="/favicon.ico" sizes="48x48" />
|
||||
<link rel="icon" href="/favicon.svg" sizes="any" type="image/svg+xml" />
|
||||
<meta name="theme-color" content="#200B2E" media="(prefers-color-scheme: dark)" />
|
||||
<meta name="theme-color" content="#171717" media="(prefers-color-scheme: dark)" />
|
||||
<meta name="theme-color" content="#FFFFFF" media="(prefers-color-scheme: light)" />
|
||||
|
||||
<meta property="og:url" content="https://nostr.basspistol.org" />
|
||||
<meta property="og:url" content="https://jumble.social" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="Bpistle" />
|
||||
<meta property="og:title" content="Jumble" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="A user-friendly Nostr client for exploring relay feeds"
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://tortellino.basspistol.org/06052f39027abe9e7e5bc755211ce0ecfb838dcc0c39c7bd767db0354ed5a293.png"
|
||||
content="https://github.com/CodyTseng/jumble/blob/master/resources/og-image.png?raw=true"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 7.9 KiB |
|
|
@ -17,7 +17,7 @@ export default function Icon({ className }: { className?: string }) {
|
|||
>
|
||||
<path
|
||||
id="Icon-Curve-Cut"
|
||||
d="m989.52 727.65q0 110.66-102.99 199.41-102.99 88.749-215.85 88.749-49.305 0-95.323-18.626-44.922-18.626-73.409-40.54-28.487-21.913-60.262-40.54-30.679-18.626-53.688-18.626-21.913 0-40.54 13.148-17.531 13.148-18.626 35.061h-18.626q1.0953-62.453 56.975-107.38 56.975-44.922 121.62-46.018 43.827-47.114 43.827-175.31v-168.73q0-27.392-2.1917-46.018-1.0953-19.722-7.6693-47.114-5.4787-27.392-21.913-41.635-16.435-15.339-41.635-15.339-26.296 0-41.635 21.913-14.244 21.913-14.244 49.305 0 30.679 35.061 93.131 35.061 61.357 35.061 102.99 0 97.514-157.78 146.82l-7.6693-12.052q53.688-24.105 53.688-63.549 0-25.2-36.157-86.558-35.061-61.357-35.061-112.85 0-75.601 70.122-123.81 71.218-49.305 151.2-49.305 112.85 0 157.78 89.844l132.58-89.844q60.262 3.287 106.28 35.061 46.018 30.679 46.018 87.653 0 53.688-38.348 89.845-37.252 36.157-95.323 54.783 78.888 4.3822 123.81 60.262 44.922 54.783 44.922 135.86zm-167.64-273.92q0-39.444-21.913-69.027-21.913-30.679-59.166-30.679-30.679 0-64.644 31.774 7.6693 64.644 7.6693 153.39 0 23.009 0 54.783 56.974-17.531 97.514-52.592 40.54-36.157 40.54-87.653zm46.018 374.72q0-62.453-52.592-133.67-51.496-71.218-110.66-71.218-14.244 0-23.009 4.3823-4.3823 37.253-21.913 65.74-16.435 27.392-32.87 39.444-15.339 12.052-51.496 33.966-35.061 21.913-52.592 33.966 38.348 10.957 129.29 71.218 92.036 59.166 127.1 59.166 40.54 0 64.644-30.679 24.105-30.679 24.105-72.314z"
|
||||
d="M360.047,1225.75c-31.046,-3.901 -75.11,-14.46 -106.756,-25.58c-101.676,-35.727 -175.164,-93.066 -215.387,-168.055c-12.079,-22.521 -30.071,-71.422 -27.297,-74.195c0.736,-0.736 11.648,5.578 24.249,14.031c135.436,90.86 301.047,169.043 465.056,219.547l32.77,10.091l-20.27,7.416c-43.455,15.896 -105.159,22.678 -152.365,16.745Zm166.293,-59.234c-168.523,-50.004 -331.475,-126.514 -481.755,-226.196c-37.737,-25.031 -41.489,-28.372 -43.419,-38.663c-3.585,-19.109 1.498,-83.894 9.798,-124.886c7.343,-36.266 27.664,-106.034 32.278,-110.818c2.023,-2.099 217.924,48.207 221.274,51.557c0.975,0.975 -1.132,11.339 -4.682,23.032c-24.542,80.842 -27.217,127.586 -9.935,173.593c22.507,59.917 114.521,99.888 177.281,77.012c29.23,-10.654 56.593,-41.085 82.629,-91.894c29.288,-57.155 32.348,-64.988 196.483,-503.076c81.138,-216.562 148.499,-394.821 149.692,-396.131c2.1,-2.304 217.949,76.926 223.076,81.884c2.056,1.988 -262.476,712.505 -307.806,826.747c-18.422,46.426 -56.939,123.045 -77.918,154.993c-10.157,15.469 -30.753,40.901 -45.769,56.515c-27.821,28.93 -66.46,58.952 -75.447,58.621c-2.738,-0.106 -23.339,-5.631 -45.78,-12.29Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 47 KiB |
|
|
@ -1,24 +0,0 @@
|
|||
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Event } from 'nostr-tools'
|
||||
|
||||
export default function MusicTrackPreview({ event }: { event: Event }) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const title = event.tags.find(tag => tag[0] === 'title')?.[1]
|
||||
const artist = event.tags.find(tag => tag[0] === 'artist')?.[1]
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2 truncate">
|
||||
<span>🎵</span>
|
||||
<span className="font-medium truncate">
|
||||
{title || t('music.untitled')}
|
||||
</span>
|
||||
{artist && (
|
||||
<span className="text-muted-foreground truncate">
|
||||
{t('music.by')} {artist}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@ import PictureNotePreview from './PictureNotePreview'
|
|||
import PollPreview from './PollPreview'
|
||||
import ReactionPreview from './ReactionPreview'
|
||||
import VideoNotePreview from './VideoNotePreview'
|
||||
import MusicTrackPreview from './MusicTrackPreview'
|
||||
|
||||
export default function ContentPreview({
|
||||
event,
|
||||
|
|
@ -121,10 +120,6 @@ export default function ContentPreview({
|
|||
return <ReactionPreview event={event} className={className} />
|
||||
}
|
||||
|
||||
if (event.kind === ExtendedKind.MUSIC_TRACK) {
|
||||
return <MusicTrackPreview event={event} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
[
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ const KIND_FILTER_OPTIONS = [
|
|||
{ kindGroup: [ExtendedKind.POLL], label: 'Polls' },
|
||||
{ kindGroup: [ExtendedKind.VOICE, ExtendedKind.VOICE_COMMENT], label: 'Voice Posts' },
|
||||
{ kindGroup: [ExtendedKind.PICTURE], label: 'Photo Posts' },
|
||||
{ kindGroup: [ExtendedKind.MUSIC_TRACK], label: 'Music Posts' },
|
||||
{
|
||||
kindGroup: [
|
||||
ExtendedKind.VIDEO,
|
||||
|
|
|
|||
|
|
@ -1,173 +0,0 @@
|
|||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import dayjs from 'dayjs'
|
||||
import { Event } from 'nostr-tools'
|
||||
import AudioPlayer from '@/components/AudioPlayer'
|
||||
|
||||
interface MusicTrackNoteProps {
|
||||
event: Event
|
||||
className?: string
|
||||
}
|
||||
|
||||
export default function MusicTrackNote({ event, className }: MusicTrackNoteProps) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const metadata = useMemo(() => {
|
||||
const getTagValue = (tagName: string) => {
|
||||
const tag = event.tags.find(tag => tag[0] === tagName)
|
||||
return tag?.[1] || null
|
||||
}
|
||||
|
||||
const getTagValues = (tagName: string) => {
|
||||
return event.tags
|
||||
.filter(tag => tag[0] === tagName)
|
||||
.map(tag => tag[1])
|
||||
.filter(Boolean)
|
||||
}
|
||||
|
||||
|
||||
let lyrics = null
|
||||
let credits = null
|
||||
|
||||
if (event.content) {
|
||||
const creditsMatch = event.content.match(/Credits:\s*\n([\s\S]*)/i)
|
||||
if (creditsMatch) {
|
||||
credits = creditsMatch[1].trim()
|
||||
|
||||
const lyricsMatch = event.content.match(/^([\s\S]*?)Credits:/i)
|
||||
lyrics = lyricsMatch ? lyricsMatch[1].trim() : null
|
||||
} else {
|
||||
|
||||
lyrics = event.content
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
title: getTagValue('title') || t('music.untitled'),
|
||||
url: getTagValue('url'),
|
||||
image: getTagValue('image'),
|
||||
license: getTagValue('license'),
|
||||
alt: getTagValue('alt'),
|
||||
releaseDate: getTagValue('released'),
|
||||
artist: getTagValue('artist'),
|
||||
album: getTagValue('album'),
|
||||
trackNumber: getTagValue('track_number'),
|
||||
duration: getTagValue('duration'),
|
||||
genres: getTagValues('t').filter(tag =>
|
||||
!['music', 'electronic', 'lofi pop'].includes(tag)
|
||||
),
|
||||
lyrics,
|
||||
credits
|
||||
}
|
||||
}, [event, t])
|
||||
|
||||
if (!metadata.url) {
|
||||
return (
|
||||
<div className={`p-4 text-red-500 ${className || ''}`}>
|
||||
{t('music.noAudioUrl')}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`space-y-4 p-4 ${className || ''}`}>
|
||||
{/* Main track container */}
|
||||
<div className="flex gap-4 flex-col sm:flex-row">
|
||||
{/* Cover Art */}
|
||||
{metadata.image && (
|
||||
<div className="flex-shrink-0">
|
||||
<img
|
||||
src={metadata.image}
|
||||
alt={metadata.alt || metadata.title}
|
||||
className="w-48 h-48 object-cover rounded-lg shadow-md"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Track Info */}
|
||||
<div className="flex-1 space-y-2">
|
||||
<h3 className="text-xl font-bold">{metadata.title}</h3>
|
||||
|
||||
{metadata.artist && (
|
||||
<p className="text-muted-foreground">
|
||||
{t('music.by')} {metadata.artist}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{metadata.album && (
|
||||
<p className="text-sm">
|
||||
{t('music.album')}: {metadata.album}
|
||||
{metadata.trackNumber && ` • ${t('music.track')} ${metadata.trackNumber}`}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{metadata.releaseDate && (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t('music.released')}: {dayjs(metadata.releaseDate).format('MMMM D, YYYY')}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Audio Player */}
|
||||
<div className="mt-4">
|
||||
<AudioPlayer
|
||||
src={metadata.url}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Show lyrics if they exist */}
|
||||
{metadata.lyrics && (
|
||||
<div className="pt-2">
|
||||
<p className="text-sm whitespace-pre-wrap text-muted-foreground">
|
||||
{metadata.lyrics}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Show credits if they exist */}
|
||||
{metadata.credits && (
|
||||
<div className="pt-2">
|
||||
<p className="text-sm italic text-muted-foreground whitespace-pre-wrap">
|
||||
<span className="font-semibold not-italic">{t('music.credits')}:</span><br />
|
||||
{metadata.credits}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{/* License and Metadata Footer */}
|
||||
<div className="pt-4 border-t space-y-1">
|
||||
{metadata.license && (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{t('music.license')}: {metadata.license}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Only show alt if it's different from what we've shown
|
||||
{metadata.alt && !metadata.credits && (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{t('music.altText')}: {metadata.alt}
|
||||
</p>
|
||||
)}
|
||||
*/}
|
||||
{metadata.genres.length > 0 && (
|
||||
<div className="flex flex-wrap gap-2 mt-2">
|
||||
{metadata.genres.map((genre, index) => (
|
||||
<span
|
||||
key={index}
|
||||
className="px-2 py-1 text-xs rounded-full bg-secondary"
|
||||
>
|
||||
{genre}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -38,7 +38,6 @@ import Reaction from './Reaction'
|
|||
import RelayReview from './RelayReview'
|
||||
import UnknownNote from './UnknownNote'
|
||||
import VideoNote from './VideoNote'
|
||||
import MusicTrackNote from './MusicTrackNote'
|
||||
|
||||
export default function Note({
|
||||
event,
|
||||
|
|
@ -125,8 +124,6 @@ export default function Note({
|
|||
event.kind === ExtendedKind.ADDRESSABLE_SHORT_VIDEO
|
||||
) {
|
||||
content = <VideoNote className="mt-2" event={event} />
|
||||
} else if (event.kind === ExtendedKind.MUSIC_TRACK) {
|
||||
content = <MusicTrackNote className="mt-2" event={event} />
|
||||
} else if (event.kind === ExtendedKind.RELAY_REVIEW) {
|
||||
content = <RelayReview className="mt-2" event={event} />
|
||||
} else if (event.kind === kinds.Emojisets) {
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ function RelayControls({ url }: { url: string }) {
|
|||
}
|
||||
|
||||
const handleCopyShareableUrl = () => {
|
||||
navigator.clipboard.writeText(`https://nostr.basspistol.org/?r=${url}`)
|
||||
navigator.clipboard.writeText(`https://jumble.social/?r=${url}`)
|
||||
setCopiedShareableUrl(true)
|
||||
toast.success('Shareable URL copied to clipboard')
|
||||
setTimeout(() => setCopiedShareableUrl(false), 2000)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { cn } from '@/lib/utils'
|
||||
import { TRelaySet } from '@/types'
|
||||
import { ChevronDown, FolderClosed, Music, Radio, Trees, DoorOpen } from 'lucide-react'
|
||||
import { ChevronDown, FolderClosed } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import RelayIcon from '../RelayIcon'
|
||||
|
|
@ -17,21 +17,6 @@ export default function RelaySetCard({
|
|||
const { t } = useTranslation()
|
||||
const [expand, setExpand] = useState(false)
|
||||
|
||||
const getRelaySetIcon = (name: string) => {
|
||||
const nameLower = name.toLowerCase()
|
||||
|
||||
|
||||
if (nameLower.includes('feed')) return Radio
|
||||
if (nameLower.includes('music')) return Music
|
||||
if (nameLower.includes('backstage')) return DoorOpen
|
||||
if (nameLower.includes('hood')) return Trees
|
||||
|
||||
|
||||
return FolderClosed
|
||||
}
|
||||
|
||||
const IconComponent = getRelaySetIcon(relaySet.name)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
|
@ -40,16 +25,15 @@ export default function RelaySetCard({
|
|||
? 'border-primary bg-primary/5 shadow-sm'
|
||||
: 'clickable border-border hover:border-primary/50 hover:bg-accent/50'
|
||||
)}
|
||||
onClick={() => onSelectChange(!select)}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="flex min-w-0 flex-1 items-center gap-3">
|
||||
<div className="flex size-6 shrink-0 items-center justify-center">
|
||||
{/* Use the dynamic icon component instead of hardcoded FolderClosed */}
|
||||
<IconComponent className="size-5" />
|
||||
</div>
|
||||
<div className="select-none truncate font-medium">{relaySet.name}</div>
|
||||
onClick={() => onSelectChange(!select)}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="flex min-w-0 flex-1 items-center gap-3">
|
||||
<div className="flex size-6 shrink-0 items-center justify-center">
|
||||
<FolderClosed className="size-5" />
|
||||
</div>
|
||||
<div className="select-none truncate font-medium">{relaySet.name}</div>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-1">
|
||||
<RelayUrlsExpandToggle expand={expand} onExpandChange={setExpand}>
|
||||
{t('n relays', { n: relaySet.relayUrls.length })}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { TRelaySet } from './types'
|
|||
export const JUMBLE_API_BASE_URL = 'https://api.jumble.social'
|
||||
|
||||
export const RECOMMENDED_BLOSSOM_SERVERS = [
|
||||
'https://basspistol.org',
|
||||
'https://blossom.band/',
|
||||
'https://blossom.primal.net/',
|
||||
'https://nostr.media/'
|
||||
]
|
||||
|
|
@ -78,9 +78,9 @@ export const BIG_RELAY_URLS = [
|
|||
'wss://offchain.pub/'
|
||||
]
|
||||
|
||||
export const SEARCHABLE_RELAY_URLS = ['wss://basspistol.org/','wss://pyramid.fiatjaf.com/','wss://spatia-arcana.com/']
|
||||
export const SEARCHABLE_RELAY_URLS = ['wss://search.nos.today/', 'wss://relay.nostr.band/']
|
||||
|
||||
export const TRENDING_NOTES_RELAY_URLS = ['wss://basspistol.org/uppermost']
|
||||
export const TRENDING_NOTES_RELAY_URLS = ['wss://trending.relays.land/']
|
||||
|
||||
export const GROUP_METADATA_EVENT_KIND = 39000
|
||||
|
||||
|
|
@ -101,8 +101,7 @@ export const ExtendedKind = {
|
|||
RELAY_REVIEW: 31987,
|
||||
GROUP_METADATA: 39000,
|
||||
ADDRESSABLE_NORMAL_VIDEO: 34235,
|
||||
ADDRESSABLE_SHORT_VIDEO: 34236,
|
||||
MUSIC_TRACK: 36787
|
||||
ADDRESSABLE_SHORT_VIDEO: 34236
|
||||
}
|
||||
|
||||
export const ALLOWED_FILTER_KINDS = [
|
||||
|
|
@ -119,8 +118,7 @@ export const ALLOWED_FILTER_KINDS = [
|
|||
kinds.Highlights,
|
||||
kinds.LongFormArticle,
|
||||
ExtendedKind.ADDRESSABLE_NORMAL_VIDEO,
|
||||
ExtendedKind.ADDRESSABLE_SHORT_VIDEO,
|
||||
ExtendedKind.MUSIC_TRACK
|
||||
ExtendedKind.ADDRESSABLE_SHORT_VIDEO
|
||||
]
|
||||
|
||||
export const SUPPORTED_KINDS = [
|
||||
|
|
@ -204,16 +202,16 @@ export const PRIMARY_COLORS = {
|
|||
DEFAULT: {
|
||||
name: 'Default',
|
||||
light: {
|
||||
primary: '30 100% 50%',
|
||||
'primary-hover': '30 100% 60%',
|
||||
primary: '259 43% 56%',
|
||||
'primary-hover': '259 43% 65%',
|
||||
'primary-foreground': '0 0% 98%',
|
||||
ring: '30 100% 50%'
|
||||
ring: '259 43% 56%'
|
||||
},
|
||||
dark: {
|
||||
primary: '30 100% 50%',
|
||||
'primary-hover': '30 100% 60%',
|
||||
primary: '259 43% 56%',
|
||||
'primary-hover': '259 43% 65%',
|
||||
'primary-foreground': '240 5.9% 10%',
|
||||
ring: '30 100% 50%'
|
||||
ring: '259 43% 56%'
|
||||
}
|
||||
},
|
||||
RED: {
|
||||
|
|
@ -232,18 +230,18 @@ export const PRIMARY_COLORS = {
|
|||
}
|
||||
},
|
||||
ORANGE: {
|
||||
name: 'Lavender',
|
||||
name: 'Orange',
|
||||
light: {
|
||||
primary: '259 43% 56%',
|
||||
'primary-hover': '259 43% 65%',
|
||||
primary: '30 100% 50%',
|
||||
'primary-hover': '30 100% 60%',
|
||||
'primary-foreground': '0 0% 98%',
|
||||
ring: '259 43% 56%'
|
||||
ring: '30 100% 50%'
|
||||
},
|
||||
dark: {
|
||||
primary: '259 43% 56%',
|
||||
'primary-hover': '259 43% 65%',
|
||||
primary: '30 100% 50%',
|
||||
'primary-hover': '30 100% 60%',
|
||||
'primary-foreground': '240 5.9% 10%',
|
||||
ring: '259 43% 56%'
|
||||
ring: '30 100% 50%'
|
||||
}
|
||||
},
|
||||
AMBER: {
|
||||
|
|
|
|||
|
|
@ -686,18 +686,6 @@ export default {
|
|||
'Allow insecure connections description':
|
||||
'Allow loading http:// resources and connecting to ws:// relays. May trigger browser mixed content warnings.',
|
||||
'reacted to': 'reacted to',
|
||||
Reaction: 'Reaction',
|
||||
music: {
|
||||
untitled: 'Untitled Track',
|
||||
by: 'by',
|
||||
album: 'Album',
|
||||
track: 'Track',
|
||||
released: 'Released',
|
||||
license: 'License',
|
||||
altText: 'Credit',
|
||||
credits: 'Credits', // Add this
|
||||
showLyrics: 'Show Lyrics', // Add this (optional)
|
||||
noAudioUrl: 'No audio URL provided for this track',
|
||||
}
|
||||
Reaction: 'Reaction'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,12 +133,12 @@
|
|||
--radius: 0.75rem;
|
||||
}
|
||||
.dark {
|
||||
--surface-background: 276, 61.404%, 9%;
|
||||
--background: 276, 61.404%, 11.176%;
|
||||
--surface-background: 240 10% 3.9%;
|
||||
--background: 0 0% 9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 276, 61.404%, 10%;
|
||||
--card: 0 0% 12%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 276, 61.404%, 10%;
|
||||
--popover: 0 0% 12%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 259 43% 56%;
|
||||
--primary-hover: 259 43% 65%;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const toNote = (eventOrId: Event | string) => {
|
|||
return `/notes/${nevent}`
|
||||
}
|
||||
export const toJumbleNote = (eventOrId: Event | string) => {
|
||||
return `https://nostr.basspistol.org${toNote(eventOrId)}`
|
||||
return `https://jumble.social${toNote(eventOrId)}`
|
||||
}
|
||||
export const toNoteList = ({
|
||||
hashtag,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { cn } from '@/lib/utils'
|
|||
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
|
||||
import { useFeed } from '@/providers/FeedProvider'
|
||||
import { useScreenSize } from '@/providers/ScreenSizeProvider'
|
||||
import { ChevronDown, Server, Star, UsersRound, Music, Radio, Trees, DoorOpen } from 'lucide-react'
|
||||
import { ChevronDown, Server, Star, UsersRound } from 'lucide-react'
|
||||
import { forwardRef, HTMLAttributes, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
|
|
@ -90,25 +90,13 @@ const FeedSwitcherTrigger = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivEle
|
|||
|
||||
const icon = useMemo(() => {
|
||||
if (feedInfo?.feedType === 'following') return <UsersRound />
|
||||
if (feedInfo?.feedType === 'pinned') return <Star />
|
||||
if (feedInfo?.feedType === 'relay' && feedInfo.id) {
|
||||
return <RelayIcon url={feedInfo.id} />
|
||||
}
|
||||
if (feedInfo?.feedType === 'relays') {
|
||||
const relaySetName = feedInfo.name ?? activeRelaySet?.name ?? activeRelaySet?.id ?? ''
|
||||
const nameLower = relaySetName.toLowerCase()
|
||||
if (feedInfo?.feedType === 'pinned') return <Star />
|
||||
if (feedInfo?.feedType === 'relay' && feedInfo.id) {
|
||||
return <RelayIcon url={feedInfo.id} />
|
||||
}
|
||||
|
||||
// Custom icons for your relay sets
|
||||
if (nameLower.includes('feed')) return <Radio />
|
||||
if (nameLower.includes('music')) return <Music />
|
||||
if (nameLower.includes('backstage')) return <DoorOpen />
|
||||
if (nameLower.includes('hood')) return <Trees />
|
||||
|
||||
// Default relay set icon
|
||||
return <Server />
|
||||
}
|
||||
return <Server />
|
||||
}, [feedInfo, activeRelaySet])
|
||||
return <Server />
|
||||
}, [feedInfo])
|
||||
|
||||
const clickable =
|
||||
!IS_COMMUNITY_MODE || COMMUNITY_RELAY_SETS.length + COMMUNITY_RELAYS.length > 1
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ export default defineConfig(({ mode }) => {
|
|||
enabled: true
|
||||
},
|
||||
manifest: {
|
||||
name: 'Bpistle',
|
||||
short_name: 'Bpistle',
|
||||
name: 'Jumble',
|
||||
short_name: 'Jumble',
|
||||
icons: [
|
||||
{
|
||||
src: '/pwa-512x512.png',
|
||||
|
|
|
|||