diff --git a/index.html b/index.html index 3feb0e1..53997c1 100644 --- a/index.html +++ b/index.html @@ -1,11 +1,17 @@ - + - + + slidestr.net - + + + + + +
diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..5f6bf55 --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,10 @@ +{ + "name": "slidestr.net", + "short_name": "slidestr", + "theme_color": "#4a49ff", + "background_color": "#7600ff", + "display": "standalone", + "scope": "/", + "start_url": "/" + } + \ No newline at end of file diff --git a/src/components/GridView/DetailsView.css b/src/components/GridView/DetailsView.css index 57effe4..d503c86 100644 --- a/src/components/GridView/DetailsView.css +++ b/src/components/GridView/DetailsView.css @@ -158,15 +158,25 @@ .details { overflow-y: scroll; align-items: normal; + overflow-x: hidden; + padding: 0; + overscroll-behavior: none; } .details-contents { grid-template-columns: 1fr; grid-template-rows: auto 1fr; } + .details-contents .detail-image { + border-radius: 0px; + } .detail-description { max-width: 100%; width: 100%; overflow: visible; + padding-left: 2em; + } + .closeButton { + top: 1.5em; } } diff --git a/src/components/GridView/index.tsx b/src/components/GridView/index.tsx index 2246ee9..c61a7ad 100644 --- a/src/components/GridView/index.tsx +++ b/src/components/GridView/index.tsx @@ -6,6 +6,7 @@ import GridImage from './GridImage'; import { Settings } from '../../utils/useNav'; import { useNDK } from '@nostr-dev-kit/ndk-react'; import AuthorProfile from '../AuthorProfile'; +import { useSwipeable } from 'react-swipeable'; type GridViewProps = { settings: Settings; @@ -24,20 +25,37 @@ const GridView = ({ settings, images }: GridViewProps) => { [images, settings] // settings is not used here, but we need to include it to trigger a re-render when it changes ); + const showNextImage = () => { + setActiveImageIdx(idx => (idx !== undefined ? idx + 1 : 0)); + }; + + const showPreviousImage = () => { + setActiveImageIdx(idx => (idx !== undefined && idx > 0 ? idx - 1 : idx)); + }; + const onKeyDown = (event: KeyboardEvent) => { console.log(event); if (event.key === 'ArrowRight') { - setActiveImageIdx(idx => idx !== undefined ? idx + 1 : 0); + showNextImage(); } if (event.key === 'ArrowLeft') { - setActiveImageIdx(idx => (idx !== undefined && idx > 0 ? idx - 1 : idx)); + showPreviousImage(); } if (event.key === 'Escape') { setActiveImageIdx(undefined); } }; + const swipeHandlers = useSwipeable({ + onSwipedLeft: () => { + showNextImage(); + }, + onSwipedRight: () => { + showPreviousImage(); + }, + }); + useEffect(() => { document.body.addEventListener('keydown', onKeyDown); return () => { @@ -48,7 +66,7 @@ const GridView = ({ settings, images }: GridViewProps) => { const activeProfile = settings.npubs.length == 1 && getProfile(settings.npubs[0]); return ( -
+
{activeImageIdx !== undefined ? ( ) : null} diff --git a/src/components/SlideShow.css b/src/components/SlideShow.css index efcc69f..fe9dd96 100644 --- a/src/components/SlideShow.css +++ b/src/components/SlideShow.css @@ -214,3 +214,9 @@ animation-iteration-count: infinite; animation-timing-function: linear; } + +@media screen and (max-width: 768px) { + .controls { + top: 2em; + } +} diff --git a/src/components/env.ts b/src/components/env.ts index fd39762..522510a 100644 --- a/src/components/env.ts +++ b/src/components/env.ts @@ -3,18 +3,20 @@ import { nip19 } from 'nostr-tools'; export const appName = 'slidestr.net'; export const defaultHashTags = [ - 'art', 'artstr', 'catstr', 'dogstr', - 'nature', - 'naturephotography', + 'flowerstr', + 'foodstr', + 'gardenstr', + 'grownostr', + 'nostr', 'photography', 'photostr', - 'streetphotography', + 'picstr', + 'plebchain', 'tavelstr', - 'gardening', - 'gardenstr', + 'zapathon', ]; export const visibleHashTags = [ @@ -27,6 +29,8 @@ export const visibleHashTags = [ 'cute', 'dogstr', 'fashion', + 'flowerstr', + 'foodstr', 'freedom', 'gardening', 'gardenstr', @@ -47,8 +51,10 @@ export const visibleHashTags = [ 'psychedelic', 'streetphotography', 'style', - 'travelstr', + 'tavelstr', 'travel', + 'travelstr', + 'zapathon', ]; /* All posts with the following hashtags are flagged as adult / NSFW are not shown @@ -150,6 +156,7 @@ export const adultNPubs = [ 'npub1apr6dy5z4f0qs4cnswxj0gf37g46jxvh7xgwgs4wvzm6stu8f0asd4996r', // Anime Girl 'npub1acwrv7aqgu949mw0zxmw2akgsjqp574nnq4vcl9wln5355q79w5ssv9qxg', // Arianna 'npub1v3rnmlms82wgxejxwn7rr6kjruy3ty0l4084dx2zp3tn8dlxv28sjnp6pf', // High Elf Archer + 'npub1jvp6kfs2d3m98lyw5wcyr4fnctr83s0rc3mj5p0f75ach6vcd8rst6wqnu', // VelectBlue Art ]; export const adultPublicKeys = adultNPubs.map(npub => (nip19.decode(npub).data as string).toLowerCase()); diff --git a/src/index.css b/src/index.css index f47084c..04d8b50 100644 --- a/src/index.css +++ b/src/index.css @@ -4,7 +4,6 @@ -moz-osx-font-smoothing: grayscale; line-height: 1.5; font-weight: 400; - color-scheme: dark; color: rgba(255, 255, 255, 0.87); background-color: #111111; @@ -51,19 +50,6 @@ button { outline: none; } -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} - input[type='checkbox'] { -webkit-appearance: none; -moz-appearance: none; diff --git a/src/mainInner.tsx b/src/mainInner.tsx index 7118773..5525e6d 100644 --- a/src/mainInner.tsx +++ b/src/mainInner.tsx @@ -28,6 +28,10 @@ const MainInner = () => { path: 'p/:npub', element: , }, + { + path: '/followers', + element: , + }, { path: '/:npub', element: , diff --git a/src/utils/useAutoLogin.ts b/src/utils/useAutoLogin.ts index 8163f8f..eab7898 100644 --- a/src/utils/useAutoLogin.ts +++ b/src/utils/useAutoLogin.ts @@ -7,7 +7,9 @@ declare global { } const useAutoLogin = () => { - const [autoLogin, setAutoLogin] = useState(JSON.parse(localStorage.getItem('autoLogin') as string) as boolean | undefined); + const [autoLogin, setAutoLogin] = useState( + JSON.parse(localStorage.getItem('autoLogin') as string) as boolean | undefined + ); useEffect(() => { const autoLogin = JSON.parse(localStorage.getItem('autoLogin') as string) as boolean | undefined; diff --git a/src/utils/useNav.ts b/src/utils/useNav.ts index eac749a..85f2657 100644 --- a/src/utils/useNav.ts +++ b/src/utils/useNav.ts @@ -7,6 +7,7 @@ export type Settings = { showReposts: boolean; tags: string[]; npubs: string[]; + followers: boolean; }; const useNav = () => { @@ -18,8 +19,11 @@ const useNav = () => { const adult = searchParams.get('adult') === 'true' || searchParams.get('nsfw') === 'true'; const replies = searchParams.get('replies') === 'true'; const reposts = searchParams.get('reposts') === 'true'; + const followers = window.location.pathname.startsWith('/followers'); - console.log(`tags = ${tags}, npub = ${npub}, adult = ${adult}, replies = ${replies}, reposts = ${reposts}`); + console.log( + `tags = ${tags}, npub = ${npub}, adult = ${adult}, replies = ${replies}, reposts = ${reposts}, followers = ${followers}` + ); const useTags = tags?.split(',') || []; @@ -29,6 +33,7 @@ const useNav = () => { showAdult: adult, showReplies: replies, showReposts: reposts, + followers, }; }, [tags, npub, searchParams]); @@ -49,7 +54,9 @@ const useNav = () => { const postfix = searchParams.length > 0 ? `?${searchParams.join('&')}` : ''; - if (validTags.length > 0) { + if (settings.followers) { + navigate(`/followers${postfix}`); + } else if (validTags.length > 0) { navigate(`/tags/${validTags.join('%2C')}${postfix}`); } else if (validNpubs.length == 1) { navigate(`/p/${validNpubs[0]}${postfix}`);