Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
johnpangalos committed Sep 21, 2023
1 parent 2a13bec commit de66712
Show file tree
Hide file tree
Showing 13 changed files with 349 additions and 5,233 deletions.
4,823 changes: 0 additions & 4,823 deletions pnpm-lock.yaml

This file was deleted.

15 changes: 11 additions & 4 deletions web/package.json
Expand Up @@ -3,10 +3,9 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@sentry/react": "^7.51.0",
"@sentry/tracing": "^7.51.0",
"@tanstack/react-query": "^4.29.5",
"@tanstack/react-query-devtools": "^4.29.6",
"@sentry/react": "^7.61.0",
"@tanstack/react-query": "^4.32.1",
"@tanstack/react-query-devtools": "^4.32.1",
"@tanstack/react-virtual": "3.0.0-beta.54",
"react": "^18.0.0",
"react-dom": "^18.0.0",
Expand Down Expand Up @@ -34,9 +33,17 @@
"@types/react-router-dom": "^5.1.7",
"@vitejs/plugin-react": "^2.2.0",
"autoprefixer": "^10.4.14",
<<<<<<< Updated upstream
"cross-env": "^5.2.0",
"postcss": "^8.4.23",
"tailwindcss": "^3.3.2",
"vite": "^3.2.6"
=======
"cross-env": "^7.0.3",
"postcss": "^8.4.27",
"react-intersection-observer": "^9.5.2",
"tailwindcss": "^3.3.3",
"vite": "^4.4.8"
>>>>>>> Stashed changes
}
}
130 changes: 88 additions & 42 deletions web/src/App.tsx
@@ -1,19 +1,99 @@
import {
BrowserRouter as Router,
Navigate,
Route,
Routes,
RouterProvider,
createBrowserRouter,
useNavigate,
useRouteError,
} from "react-router-dom";
import { Login, Upload, Feed, Profile } from "@/pages";
import { Login, Upload, Feed, Profile, loader, profileLoader } from "@/pages";
import { MainLayout } from "./layouts/main";
import { BreakpointProvider } from "@/hooks";
import * as Sentry from "@sentry/react";
import { captureMessage, wrapCreateBrowserRouter } from "@sentry/react";
import { useQuery } from "@tanstack/react-query";
import { loginUrl } from "@/utils";
import { useEffect } from "react";
import { checkRegistration, register, unregister } from "./register-sw";
import { Button } from "./components";

const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes);
const sentryCreateBrowserRouter = wrapCreateBrowserRouter(createBrowserRouter);

function ErrorBoundary() {
const error = useRouteError();
console.error(error);
if (error instanceof Error) captureMessage(error.message, "fatal");
return <div>Dang!</div>;
}

function PageNotFound() {
const navigate = useNavigate();
return (
<div className="h-full flex flex-col items-center max-w-xl pt-24 m-auto space-y-4">
<div className="font-bold text-xl text-gray-700">
Where do you think you&apos;re going?
</div>
<div>
There is really nothing here to see, I mean like nothing. You don&apos;t
have to leave but you can&apos;t stay here.
</div>
<div className="self-end">
<Button onClick={() => navigate("/feed")}>Take me home</Button>
</div>
</div>
);
}

const router = sentryCreateBrowserRouter([
{
path: "/",
element: <MainLayout />,
errorElement: <ErrorBoundary />,
children: [
{
path: "feed",
loader: loader,
element: (
<RequireAuth>
<Feed />
</RequireAuth>
),
},

{
path: "upload",
element: (
<RequireAuth>
<Upload />
</RequireAuth>
),
},
{
path: "profile",
loader: profileLoader,
element: (
<RequireAuth>
<Profile />
</RequireAuth>
),
},
{
path: "login",
element: <Login />,
},
{
path: "*",
element: <PageNotFound />,
},
{
index: true,
Component: () => (
<RequireAuth>
<Navigate to="feed" />
</RequireAuth>
),
},
],
},
]);

const App = () => {
useEffect(() => {
Expand All @@ -26,42 +106,7 @@ const App = () => {
}, []);
return (
<BreakpointProvider>
<div id="App" className="h-[100svh] overflow-hidden text-gray-800">
<Router>
<SentryRoutes>
<Route path="/" element={<MainLayout />}>
<Route
path="feed"
element={
<RequireAuth>
<Feed />
</RequireAuth>
}
/>
<Route path="login" element={<Login />} />

<Route
path={"upload"}
element={
<RequireAuth>
<Upload />
</RequireAuth>
}
/>
<Route
path="profile"
element={
<RequireAuth>
<Profile />
</RequireAuth>
}
/>
<Route path="/" element={<Navigate to="feed" />} />
<Route path="*" element={<Navigate to="feed" />} />
</Route>
</SentryRoutes>
</Router>
</div>
<RouterProvider router={router} />
</BreakpointProvider>
);
};
Expand All @@ -78,4 +123,5 @@ function RequireAuth({ children }: { children: JSX.Element }): JSX.Element {

return children;
}

export default App;
21 changes: 8 additions & 13 deletions web/src/components/Image.tsx
Expand Up @@ -3,23 +3,18 @@ import { NewPost } from "@/types";
type ImageProps = {
thumbnail?: boolean;
loading?: "lazy" | "eager";
post?: NewPost;
post: NewPost;
};

export function Image({
post,
thumbnail = false,
loading = "lazy",
}: ImageProps) {
if (!post) return <></>;
} // thumbnail = false,
: ImageProps) {
return (
<div className={thumbnail ? "h-[115px] md:h-[164px]" : "h-[424px]"}>
<img
className="w-full h-full bg-no-repeat object-contain object-center"
loading={loading}
src={post.url}
alt={post.url}
/>
</div>
<img
className="w-full h-full bg-no-repeat object-contain object-center"
src={post.url}
alt={post.url}
/>
);
}
97 changes: 33 additions & 64 deletions web/src/components/Post.tsx
@@ -1,93 +1,62 @@
import { ReactNode } from "react";
import { Download } from "react-feather";
import { ProfileImage } from "../components";
import { Account } from "@/types";

const forceDownload = (blob: string, filename: string) => {
const a = document.createElement("a");
a.download = filename;
a.href = blob;
document.body.appendChild(a);
a.click();
a.remove();
};
import { ProfileImage } from "@/components";
import { NewPost } from "@/types";
import { usePostsLoadedState } from "@/stores";

type PostProps = {
thumbnail?: boolean;
children: ReactNode | ReactNode[];
timestamp?: string;
selected?: boolean;
selectable?: boolean;
handleClick?: () => void;
account?: Account;
id?: string;
url?: undefined;
post: NewPost;
};

export const Post = ({
children,
timestamp = "0",
thumbnail,
post,
selectable,
selected,
selectable = false,
handleClick = () => null,
account,
thumbnail = false,
url,
handleClick,
}: PostProps): JSX.Element => {
const date = new Date(Number(timestamp));

const downloadResource = (url: string, filename?: string) => {
let name = filename;
if (!name) name = url.split("\\").pop()?.split("/").pop();
fetch(url, {
headers: new Headers({
Origin: window.location.origin,
}),
mode: "cors",
})
.then((response) => response.blob())
.then((blob) => {
const blobUrl = window.URL.createObjectURL(blob);
forceDownload(blobUrl, name as string);
})
.catch((e) => console.error(e));
};
const date = new Date(Number(post.timestamp));
const { updatePost } = usePostsLoadedState();

return (
<div
className={`
flex flex-col bg-white shadow-md
rounded px-2 pt-3 pb-4 w-full xs:max-h-sm
max-h-xs m-auto max-w-xl
w-full m-auto max-w-xl
${thumbnail ? "bg-gray-100 border border-gray-200 p-1 rounded" : ""}
${selectable ? " cursor-pointer" : ""}
${selected ? " border-purple-600 border-2" : ""}
${thumbnail ? "h-[145px] md:h-[195px]" : "h-[520px]"}`}
${selected ? " border-purple-600 border-2" : ""}`}
onClick={() => {
if (!selectable) return;
handleClick?.();
}}
>
<div
className="flex flex-grow bg-gray-300 p-1 rounded justify-center items-center h-full"
onClick={() => {
if (!selectable) return;
handleClick();
}}
className={
thumbnail
? "h-[115px] md:h-[164px]"
: "h-full flex flex-grow justify-center items-center"
}
>
{children}
<img
className="w-full h-full bg-no-repeat object-contain object-center"
src={post.url}
alt={post.url}
onLoad={() => {
updatePost(post.id, true);
}}
/>
</div>
{account && (
{!thumbnail && (
<div className="flex pt-3 items-start">
<div className="h-10 w-10">
<ProfileImage url={account.photoURL} />
<ProfileImage url={post.account.photoURL} />
</div>
<div className="flex-grow pl-3">
<div className="text-xl font-bold">{account.displayName}</div>
<div className="text-xl font-bold">{post.account.displayName}</div>
<div className="text-sm">Uploaded: {date.toLocaleString()}</div>
</div>
{url && (
<Download
className="pb-1 self-center text-purple-600"
role="button"
onClick={() => downloadResource(url)}
/>
)}
</div>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion web/src/hooks/useImageUpload.ts
@@ -1,4 +1,4 @@
import create from "zustand";
import { create } from "zustand";

export type Result = string | ArrayBuffer | null;

Expand Down
28 changes: 26 additions & 2 deletions web/src/hooks/useInfinitePosts.ts
Expand Up @@ -15,7 +15,31 @@ type GetPostsOptions = {
pageParam?: string;
} & UseInfinitePostsOptions;

async function getPosts({
export function getPostsUrl({
imageSize,
pageParam,
limit,
email,
}: GetPostsOptions): string {
return `${
import.meta.env.VITE_API_URL
}/posts?size=${imageSize}&limit=${limit}${
pageParam ? `&cursor=${pageParam}` : ""
}${email ? `&email=${email}` : ""}`;
}
export async function getPosts({
imageSize,
pageParam,
limit,
email,
}: GetPostsOptions): Promise<Response> {
return await fetch(
`${import.meta.env.VITE_API_URL}/posts?size=${imageSize}&limit=${limit}${
pageParam ? `&cursor=${pageParam}` : ""
}${email ? `&email=${email}` : ""}`
);
}
async function getPostsQueryRes({
imageSize,
pageParam,
limit,
Expand Down Expand Up @@ -43,7 +67,7 @@ export function useInfinitePosts({
}: UseInfinitePostsOptions) {
return useInfiniteQuery(
infinitePostsQueryKey({ imageSize, limit, email }),
({ pageParam }) => getPosts({ imageSize, pageParam, limit, email }),
({ pageParam }) => getPostsQueryRes({ imageSize, pageParam, limit, email }),
{
getNextPageParam: (lastPage: { posts: NewPost[]; cursor: string }) =>
lastPage.cursor,
Expand Down

0 comments on commit de66712

Please sign in to comment.