init commit,
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useAppDispatch, useAppSelector } from "../../store";
|
||||
import { resolveObject } from "../resolve/resolveSlice";
|
||||
import Post from "../post/inFeed/Post";
|
||||
import FeedComment from "../comment/inFeed/FeedComment";
|
||||
import { styled } from "@linaria/react";
|
||||
import { InFeedContext } from "../feed/Feed";
|
||||
import { useDebounceValue } from "usehooks-ts";
|
||||
import { CenteredSpinner } from "../shared/CenteredSpinner";
|
||||
|
||||
const StyledCenteredSpinner = styled(CenteredSpinner)`
|
||||
margin-top: 60px;
|
||||
`;
|
||||
|
||||
interface AutoResolvePostCommentProps {
|
||||
url: string;
|
||||
}
|
||||
|
||||
export default function AutoResolvePostComment({
|
||||
url: userInputUrl,
|
||||
}: AutoResolvePostCommentProps) {
|
||||
const dispatch = useAppDispatch();
|
||||
const [url] = useDebounceValue(userInputUrl, 500);
|
||||
const object = useAppSelector((state) => state.resolve.objectByUrl[url]);
|
||||
const [error, setError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const _url = url;
|
||||
setError(false);
|
||||
|
||||
try {
|
||||
await dispatch(resolveObject(url));
|
||||
} catch (error) {
|
||||
if (_url === url) setError(true);
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (_url === url) setError(false);
|
||||
})();
|
||||
}, [url, dispatch]);
|
||||
|
||||
if (object === "couldnt_find_object" || error) return null;
|
||||
if (!object) return <StyledCenteredSpinner />;
|
||||
|
||||
if (object.post)
|
||||
return (
|
||||
<InFeedContext.Provider value={true}>
|
||||
<Post post={object.post} />
|
||||
</InFeedContext.Provider>
|
||||
);
|
||||
|
||||
if (object.comment)
|
||||
return (
|
||||
<InFeedContext.Provider value={true}>
|
||||
<FeedComment comment={object.comment} />
|
||||
</InFeedContext.Provider>
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
import SpecialSearchMenu from "./SpecialSearchMenu";
|
||||
import TrendingCommunities from "./TrendingCommunities";
|
||||
|
||||
export default function EmptySearch() {
|
||||
return (
|
||||
<>
|
||||
<TrendingCommunities />
|
||||
<SpecialSearchMenu />
|
||||
</>
|
||||
);
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
import { IonIcon, IonItem, IonList } from "@ionic/react";
|
||||
import { SettingLabel } from "../user/Profile";
|
||||
import { useBuildGeneralBrowseLink } from "../../helpers/routes";
|
||||
import {
|
||||
albumsOutline,
|
||||
arrowForward,
|
||||
chatbubbleOutline,
|
||||
personOutline,
|
||||
searchOutline,
|
||||
} from "ionicons/icons";
|
||||
import useLemmyUrlHandler from "../shared/useLemmyUrlHandler";
|
||||
import { useMemo } from "react";
|
||||
import AutoResolvePostComment from "./AutoResolvePostComment";
|
||||
|
||||
interface SearchOptionsProps {
|
||||
search: string;
|
||||
}
|
||||
|
||||
export default function SearchOptions({ search }: SearchOptionsProps) {
|
||||
const buildGeneralBrowseLink = useBuildGeneralBrowseLink();
|
||||
const { determineObjectTypeFromUrl, redirectToLemmyObjectIfNeeded } =
|
||||
useLemmyUrlHandler();
|
||||
|
||||
const searchURI = encodeURIComponent(search);
|
||||
|
||||
const sanitizedUser = search.replace(/|\/|#|\?|\\/g, "").replace(/^@/, "");
|
||||
|
||||
const type = useMemo(
|
||||
() => determineObjectTypeFromUrl(search),
|
||||
[determineObjectTypeFromUrl, search],
|
||||
);
|
||||
|
||||
const autoResolveType = type === "post" || type === "comment";
|
||||
|
||||
return (
|
||||
<>
|
||||
<IonList inset color="primary">
|
||||
{type && !autoResolveType && (
|
||||
<IonItem
|
||||
onClick={(e) => redirectToLemmyObjectIfNeeded(search, e)}
|
||||
detail
|
||||
button
|
||||
>
|
||||
<IonIcon icon={arrowForward} color="primary" />
|
||||
<SettingLabel>Visit {type}</SettingLabel>
|
||||
</IonItem>
|
||||
)}
|
||||
<IonItem routerLink={`/search/posts/${searchURI}`}>
|
||||
<IonIcon icon={albumsOutline} color="primary" />
|
||||
<SettingLabel className="ion-text-nowrap">
|
||||
Posts with “{search}”
|
||||
</SettingLabel>
|
||||
</IonItem>
|
||||
<IonItem routerLink={`/search/comments/${searchURI}`}>
|
||||
<IonIcon icon={chatbubbleOutline} color="primary" />
|
||||
<SettingLabel className="ion-text-nowrap">
|
||||
Comments with “{search}”
|
||||
</SettingLabel>
|
||||
</IonItem>
|
||||
<IonItem routerLink={`/search/communities/${searchURI}`}>
|
||||
<IonIcon icon={searchOutline} color="primary" />
|
||||
<SettingLabel className="ion-text-nowrap">
|
||||
Communities with “{search}”
|
||||
</SettingLabel>
|
||||
</IonItem>
|
||||
<IonItem routerLink={buildGeneralBrowseLink(`/u/${sanitizedUser}`)}>
|
||||
<IonIcon icon={personOutline} color="primary" />
|
||||
<SettingLabel className="ion-text-nowrap">
|
||||
Go to User “{search}”
|
||||
</SettingLabel>
|
||||
</IonItem>
|
||||
</IonList>
|
||||
{autoResolveType && <AutoResolvePostComment url={search} />}
|
||||
</>
|
||||
);
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
import { IonIcon, IonItem, IonLabel, IonList } from "@ionic/react";
|
||||
import { planetOutline, shuffle } from "ionicons/icons";
|
||||
import { useAppSelector } from "../../store";
|
||||
|
||||
export default function SpecialSearchMenu() {
|
||||
const trendingCommunities = useAppSelector(
|
||||
(state) => state.community.trendingCommunities,
|
||||
);
|
||||
const communitiesCount = useAppSelector(
|
||||
(state) => state.site.response?.site_view.counts.communities,
|
||||
);
|
||||
|
||||
// Prevent shift of content
|
||||
if (trendingCommunities === undefined) return;
|
||||
|
||||
if (!communitiesCount) return;
|
||||
|
||||
return (
|
||||
<IonList inset color="primary">
|
||||
<IonItem routerLink="/search/random">
|
||||
<IonIcon icon={shuffle} color="primary" slot="start" />
|
||||
<IonLabel className="ion-text-nowrap">Random Community</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem routerLink="/search/explore">
|
||||
<IonIcon icon={planetOutline} color="primary" slot="start" />
|
||||
<IonLabel className="ion-text-nowrap">Explore</IonLabel>
|
||||
</IonItem>
|
||||
</IonList>
|
||||
);
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
IonIcon,
|
||||
IonItem,
|
||||
IonLabel,
|
||||
IonList,
|
||||
IonListHeader,
|
||||
} from "@ionic/react";
|
||||
import { useBuildGeneralBrowseLink } from "../../helpers/routes";
|
||||
import { useAppDispatch, useAppSelector } from "../../store";
|
||||
import { getHandle } from "../../helpers/lemmy";
|
||||
import { trendingUp } from "ionicons/icons";
|
||||
import { useEffect } from "react";
|
||||
import { getTrendingCommunities } from "../community/communitySlice";
|
||||
import { css } from "@linaria/core";
|
||||
|
||||
export default function TrendingCommunities() {
|
||||
const dispatch = useAppDispatch();
|
||||
const buildGeneralBrowseLink = useBuildGeneralBrowseLink();
|
||||
const trendingCommunities = useAppSelector(
|
||||
(state) => state.community.trendingCommunities,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (trendingCommunities === undefined) dispatch(getTrendingCommunities());
|
||||
}, [dispatch, trendingCommunities]);
|
||||
|
||||
return (
|
||||
<IonList inset color="primary">
|
||||
<IonListHeader>
|
||||
<IonLabel
|
||||
className={css`
|
||||
margin-top: 0;
|
||||
`}
|
||||
>
|
||||
Trending communities
|
||||
</IonLabel>
|
||||
</IonListHeader>
|
||||
{trendingCommunities?.map((community) => (
|
||||
<IonItem
|
||||
routerLink={buildGeneralBrowseLink(
|
||||
`/c/${getHandle(community.community)}`,
|
||||
)}
|
||||
key={community.community.id}
|
||||
>
|
||||
<IonIcon icon={trendingUp} color="primary" slot="start" />
|
||||
<IonLabel className="ion-text-nowrap">
|
||||
{getHandle(community.community)}
|
||||
</IonLabel>
|
||||
</IonItem>
|
||||
))}
|
||||
</IonList>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user