feat: Topic header and link, disabled disclaimer
This commit is contained in:
parent
62b56da827
commit
9eb0f5bf27
4
TODO.md
4
TODO.md
@ -3,10 +3,10 @@
|
||||
|
||||
# delete the events when the filter changes
|
||||
|
||||
- Improve Login dialog
|
||||
- Fix/Test zaps
|
||||
- mobile view for profile does not fit follow button
|
||||
- repair auto login
|
||||
- store NIP46 secret key
|
||||
- Fix/Test zaps
|
||||
- Reimplement Likes/Zaps based in ngine code
|
||||
- Investigate profile caching
|
||||
- build masonary view only for desktop / window->columns
|
||||
|
BIN
public/images/bitcoinatlantis.jpg
Normal file
BIN
public/images/bitcoinatlantis.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 110 KiB |
Before Width: | Height: | Size: 510 KiB After Width: | Height: | Size: 510 KiB |
@ -39,6 +39,10 @@ const App = () => {
|
||||
path: 'tags/:tags',
|
||||
element: <SlideShow />,
|
||||
},
|
||||
{
|
||||
path: 'topic/:topic',
|
||||
element: <SlideShow />,
|
||||
},
|
||||
{
|
||||
path: 'profile/:npub',
|
||||
element: <SlideShow />,
|
||||
|
@ -8,7 +8,6 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.author-info a {
|
||||
@ -50,8 +49,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
.author-identity {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
.author-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.author-name {
|
||||
display: none;
|
||||
max-width: 14em;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.author-info {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
@ -34,36 +34,38 @@ const AuthorProfile = ({
|
||||
|
||||
return (
|
||||
<div className="author-info">
|
||||
<div
|
||||
className="author-image"
|
||||
onClick={() => {
|
||||
setViewMode && setViewMode('grid');
|
||||
npub && nav({ ...currentSettings, tags: [], npubs: [npub], list: undefined });
|
||||
}}
|
||||
style={{
|
||||
backgroundImage: avatarLoaded && src ? `url(${createImgProxyUrl(src, 80, 80)})` : 'none',
|
||||
}}
|
||||
></div>
|
||||
<div className="author-identity">
|
||||
<div
|
||||
className="author-image"
|
||||
onClick={() => {
|
||||
setViewMode && setViewMode('grid');
|
||||
npub && nav({ ...currentSettings, tags: [], npubs: [npub], list: undefined, topic: undefined });
|
||||
}}
|
||||
style={{
|
||||
backgroundImage: avatarLoaded && src ? `url(${createImgProxyUrl(src, 80, 80)})` : 'none',
|
||||
}}
|
||||
></div>
|
||||
<span
|
||||
className="author-name"
|
||||
onClick={() => {
|
||||
setViewMode && setViewMode('grid');
|
||||
npub && nav({ ...currentSettings, tags: [], npubs: [npub], list: undefined, topic: undefined });
|
||||
}}
|
||||
>
|
||||
{author}
|
||||
</span>
|
||||
</div>
|
||||
<div className="author-actions">
|
||||
{followButtonAvailable && npub && (
|
||||
<FollowButton pubkey={nip19.decode(npub).data as string} className="btn btn-primary" />
|
||||
)}
|
||||
|
||||
<span
|
||||
className="author-name"
|
||||
onClick={() => {
|
||||
setViewMode && setViewMode('grid');
|
||||
npub && nav({ ...currentSettings, tags: [], npubs: [npub] });
|
||||
}}
|
||||
>
|
||||
{author}
|
||||
</span>
|
||||
|
||||
{followButtonAvailable && npub && (
|
||||
<FollowButton pubkey={nip19.decode(npub).data as string} className="btn btn-primary" />
|
||||
)}
|
||||
|
||||
{externalLink && npub && (
|
||||
<a target="_blank" href={`https://nostrapp.link/#${npub}`}>
|
||||
<IconLink></IconLink>
|
||||
</a>
|
||||
)}
|
||||
{externalLink && npub && (
|
||||
<a target="_blank" href={`https://nostrapp.link/#${npub}`}>
|
||||
<IconLink></IconLink>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -30,7 +30,6 @@
|
||||
.home .topic-title {
|
||||
font-size: 30px;
|
||||
padding-bottom: 0.5em;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.home .tag {
|
||||
|
@ -21,9 +21,9 @@ const Home = () => {
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(170deg, rgba(0, 0, 0, .8) 0%, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0) 100%), url('/images/${tk}.jpg')`,
|
||||
}}
|
||||
onClick={() => nav({ ...currentSettings, tags: topics[tk].tags })}
|
||||
onClick={() => nav({ ...currentSettings, topic: tk, npubs: [], tags: [], list: undefined })}
|
||||
>
|
||||
<div className="topic-title">{tk}</div>
|
||||
<div className="topic-title">{topics[tk].name || tk}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@ -37,7 +37,7 @@ const Home = () => {
|
||||
style={{
|
||||
background: `linear-gradient(to bottom, rgba(0, 0, 0, .8) 0%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0) 100%), red)`,
|
||||
}}
|
||||
onClick={() => nav({ ...currentSettings, tags: [], npubs: [], list: l.nevent })}
|
||||
onClick={() => nav({ ...currentSettings, tags: [], npubs: [], list: l.nevent, topic: undefined })}
|
||||
>
|
||||
<div className="topic-title">{l.name}</div>
|
||||
</div>
|
||||
|
@ -16,7 +16,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
padding-top: 8px;
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.info-panel .link svg {
|
||||
|
@ -57,7 +57,7 @@ const InfoPanel = ({ image, onClose, setViewMode, settings }: InfoPanelProps) =>
|
||||
onClick={() => {
|
||||
//setCurrentImage(undefined);
|
||||
setViewMode('grid');
|
||||
nav({ ...currentSettings, tags: [t], npubs: [] });
|
||||
nav({ ...currentSettings, tags: [t], npubs: [], list: undefined, topic: undefined });
|
||||
}}
|
||||
>
|
||||
{t}
|
||||
|
@ -41,11 +41,14 @@ const Layout = () => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Outlet />
|
||||
{/*
|
||||
{disclaimerAccepted ? (
|
||||
<Outlet />
|
||||
) : (
|
||||
<Disclaimer disclaimerAccepted={disclaimerAccepted} setDisclaimerAccepted={setDisclaimerAccepted} />
|
||||
)}
|
||||
*/}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -17,10 +17,10 @@ const MasonryImage = ({ image, onClick, index }: MasonryImageProps) => {
|
||||
const { nav, currentSettings } = useNav();
|
||||
|
||||
const tagClick = (tag: string) => {
|
||||
nav({ ...currentSettings, tags: [tag], npubs: [], list: undefined });
|
||||
nav({ ...currentSettings, tags: [tag], npubs: [], list: undefined, topic: undefined });
|
||||
};
|
||||
const profileClick = (npub: string) => {
|
||||
nav({ ...currentSettings, tags: [], npubs: [npub], list: undefined });
|
||||
nav({ ...currentSettings, tags: [], npubs: [npub], list: undefined, topic: undefined });
|
||||
};
|
||||
|
||||
const mediaIsVideo = isVideo(image.url);
|
||||
|
@ -10,6 +10,7 @@ import { ViewMode } from '../SlideShow';
|
||||
import { useGlobalState } from '../../utils/globalState';
|
||||
import MasonryImage from './MasonryImage';
|
||||
import useWindowSize from '../../utils/useWindowSize';
|
||||
import { topics } from '../env';
|
||||
|
||||
type MasonryViewProps = {
|
||||
settings: Settings;
|
||||
@ -112,7 +113,7 @@ const MasonryView = ({ settings, images, currentImage, setCurrentImage, setViewM
|
||||
<Helmet>
|
||||
<title>{title}</title>
|
||||
</Helmet>
|
||||
{(activeProfile || settings.tags.length == 1) && (
|
||||
{(activeProfile || settings.topic || settings.tags.length == 1) && (
|
||||
<div className="profile-header">
|
||||
{activeProfile ? (
|
||||
<AuthorProfile
|
||||
@ -123,6 +124,8 @@ const MasonryView = ({ settings, images, currentImage, setCurrentImage, setViewM
|
||||
followButton
|
||||
externalLink
|
||||
></AuthorProfile>
|
||||
) : settings.topic ? (
|
||||
<h2>Topic: {topics[settings.topic].name || settings.topic}</h2>
|
||||
) : (
|
||||
settings.tags.map(t => <h2>#{t}</h2>)
|
||||
)}
|
||||
|
@ -44,22 +44,58 @@ const SettingsDialog = ({ onClose, setViewMode }: SettingsProps) => {
|
||||
// If the mode is 'user' and there is exactly one validNpubs
|
||||
if (mode == 'user' && validNpubs.length == 1) {
|
||||
// Navigate with the current settings, but only keep the validNpubs, and reset tags
|
||||
nav({ ...currentSettings, tags: [], npubs: validNpubs, showAdult, showReplies, showReposts });
|
||||
nav({
|
||||
...currentSettings,
|
||||
tags: [],
|
||||
list: undefined,
|
||||
topic: undefined,
|
||||
npubs: validNpubs,
|
||||
showAdult,
|
||||
showReplies,
|
||||
showReposts,
|
||||
});
|
||||
}
|
||||
// If the mode is 'tags' and there is at least one valid tag
|
||||
else if (mode == 'tags' && validTags.length > 0) {
|
||||
// Navigate with the current settings, but only keep the validTags, and reset npubs
|
||||
nav({ ...currentSettings, tags: validTags, npubs: [], showAdult, showReplies, showReposts });
|
||||
nav({
|
||||
...currentSettings,
|
||||
tags: validTags,
|
||||
list: undefined,
|
||||
topic: undefined,
|
||||
npubs: [],
|
||||
showAdult,
|
||||
showReplies,
|
||||
showReposts,
|
||||
});
|
||||
}
|
||||
// If the mode is 'tags' but there are no valid tags
|
||||
else if (mode == 'tags') {
|
||||
// Navigate with the current settings, but reset npubs and use defaultHashTags as tags
|
||||
nav({ ...currentSettings, tags: defaultHashTags, npubs: [], showAdult, showReplies, showReposts });
|
||||
nav({
|
||||
...currentSettings,
|
||||
tags: defaultHashTags,
|
||||
list: undefined,
|
||||
topic: undefined,
|
||||
npubs: [],
|
||||
showAdult,
|
||||
showReplies,
|
||||
showReposts,
|
||||
});
|
||||
}
|
||||
// If none of the above conditions are met
|
||||
else {
|
||||
// Navigate with the current settings, but reset both tags and npubs
|
||||
nav({ ...currentSettings, tags: [], npubs: [], showAdult, showReplies, showReposts });
|
||||
nav({
|
||||
...currentSettings,
|
||||
tags: [],
|
||||
npubs: [],
|
||||
list: undefined,
|
||||
topic: undefined,
|
||||
showAdult,
|
||||
showReplies,
|
||||
showReposts,
|
||||
});
|
||||
}
|
||||
|
||||
onClose();
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
isReply,
|
||||
isAdultRelated,
|
||||
} from './nostrImageDownload';
|
||||
import { adultContentTags, adultNPubs, blockedPublicKeys, mixedAdultNPubs } from './env';
|
||||
import { adultContentTags, adultNPubs, blockedPublicKeys, mixedAdultNPubs, topics } from './env';
|
||||
import Settings from './Settings';
|
||||
import SlideView from './SlideView';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
@ -91,7 +91,9 @@ const SlideShow = () => {
|
||||
const authorsToQuery =
|
||||
listAuthors && listAuthors.length > 0 ? listAuthors : settings.npubs.map(p => nip19.decode(p).data as string);
|
||||
|
||||
const { events } = useEvents(buildFilter(settings.tags, authorsToQuery, settings.showReposts), {
|
||||
const filterTags = settings.topic ? topics[settings.topic].tags : settings.tags;
|
||||
|
||||
const { events } = useEvents(buildFilter(filterTags, authorsToQuery, settings.showReposts), {
|
||||
cacheUsage: NDKSubscriptionCacheUsage.PARALLEL,
|
||||
});
|
||||
|
||||
@ -236,7 +238,7 @@ const SlideShow = () => {
|
||||
setViewMode('grid');
|
||||
}
|
||||
if (event.key.toLowerCase() === 'h') {
|
||||
nav({ ...settings, npubs: [], tags: [] });
|
||||
nav({ ...settings, npubs: [], list: undefined, topic: undefined, tags: [] });
|
||||
}
|
||||
if (event.key.toLowerCase() === 'x') {
|
||||
setViewMode('scroll');
|
||||
@ -282,10 +284,6 @@ const SlideShow = () => {
|
||||
return <AdultContentInfo></AdultContentInfo>;
|
||||
}
|
||||
|
||||
const toggleViewMode = () => {
|
||||
setViewMode(view => (view == 'grid' ? 'scroll' : 'grid'));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{showSettings && <Settings onClose={() => setShowSettings(false)} setViewMode={setViewMode}></Settings>}
|
||||
|
@ -2,11 +2,17 @@ import { nip19 } from 'nostr-tools';
|
||||
|
||||
export const appName = 'slidestr.net';
|
||||
type Topic = {
|
||||
name?: string;
|
||||
tags: string[];
|
||||
};
|
||||
|
||||
export const topics: { [key: string]: Topic } = {
|
||||
bitcoinatlantis: {
|
||||
name: 'Bitcoin Atlantis / Madeira',
|
||||
tags: ['bitcoinatlantis', 'madeira', 'btcatlantis', 'soveng', 'funchal', 'freemadeira'],
|
||||
},
|
||||
art: {
|
||||
name: 'Art',
|
||||
tags: [
|
||||
'art',
|
||||
'artstr',
|
||||
@ -22,10 +28,11 @@ export const topics: { [key: string]: Topic } = {
|
||||
'zeichnen',
|
||||
],
|
||||
},
|
||||
bitcoin: { tags: ['bitcoin', 'plebchain'] },
|
||||
nostr: { tags: ['coffeechain', 'nostr', 'zapathon', 'grownostr', 'freedom', 'purple'] },
|
||||
animals: { tags: ['catstr', 'dogstr', 'animal', 'animals', 'bird', 'birds', 'pets'] },
|
||||
bitcoin: { name: '₿itcoin', tags: ['bitcoin', 'plebchain'] },
|
||||
nostr: { name: 'Nostr', tags: ['coffeechain', 'nostr', 'zapathon', 'grownostr', 'freedom', 'purple'] },
|
||||
animals: { name: 'Animals', tags: ['catstr', 'dogstr', 'animal', 'animals', 'bird', 'birds', 'pets'] },
|
||||
photography: {
|
||||
name: 'Photography',
|
||||
tags: [
|
||||
'naturephotography',
|
||||
'photo',
|
||||
@ -39,9 +46,10 @@ export const topics: { [key: string]: Topic } = {
|
||||
],
|
||||
},
|
||||
lifestyle: {
|
||||
name: 'Lifestyle',
|
||||
tags: ['fashion', 'flowerstr', 'foodstr', 'style', 'weedstr', 'travel', 'travelstr', 'happy', 'life', 'love'],
|
||||
},
|
||||
gardening: { tags: ['gardening', 'gardenstr', 'nature'] },
|
||||
gardenandfarm: { name: 'Gardening und Farming', tags: ['gardening', 'gardenstr', 'nature', 'farming', 'farmstr'] },
|
||||
};
|
||||
|
||||
export const defaultHashTags = [
|
||||
|
@ -9,10 +9,11 @@ export type Settings = {
|
||||
npubs: string[];
|
||||
followers: boolean;
|
||||
list?: string;
|
||||
topic?: string;
|
||||
};
|
||||
|
||||
const useNav = () => {
|
||||
const { tags, npub, list } = useParams();
|
||||
const { tags, npub, list, topic } = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
@ -31,8 +32,9 @@ const useNav = () => {
|
||||
showReposts: reposts,
|
||||
followers,
|
||||
list,
|
||||
topic,
|
||||
};
|
||||
}, [tags, npub, searchParams, list]);
|
||||
}, [tags, npub, searchParams, list, topic]);
|
||||
|
||||
const nav = (settings: Settings) => {
|
||||
const validTags = settings.tags.filter(t => t.length > 0);
|
||||
@ -50,7 +52,9 @@ const useNav = () => {
|
||||
}
|
||||
|
||||
const postfix = searchParams.length > 0 ? `?${searchParams.join('&')}` : '';
|
||||
if (settings.followers) {
|
||||
if (settings.topic) {
|
||||
navigate(`/topic/${settings.topic}${postfix}`);
|
||||
} else if (settings.followers) {
|
||||
navigate(`/followers${postfix}`);
|
||||
} else if (settings.list !== undefined) {
|
||||
navigate(`/list/${settings.list}${postfix}`);
|
||||
|
Loading…
Reference in New Issue
Block a user