Skip to content

Commit

Permalink
release: v2.0.6
Browse files Browse the repository at this point in the history
  • Loading branch information
joshxfi authored Jul 9, 2024
2 parents 624616e + 934ed40 commit 97bbfba
Show file tree
Hide file tree
Showing 27 changed files with 282 additions and 200 deletions.
6 changes: 3 additions & 3 deletions apps/www/src/app/components/chat-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type Props = {

export const ChatList = ({ imageUrl, question, reply, response }: Props) => {
return (
<div className="flex flex-col">
<div className="flex flex-col min-w-0">
<div className="flex gap-2 items-end">
<Avatar>
<AvatarImage className="rounded-full" src={imageUrl ?? ""} />
Expand All @@ -28,13 +28,13 @@ export const ChatList = ({ imageUrl, question, reply, response }: Props) => {
</div>

{reply && (
<div className="max-w-[75%] sm:max-w-[55%] rounded-lg px-3 py-2 whitespace-pre-wrap bg-primary text-primary-foreground mt-6 self-end min-w-0 break-words">
<div className="max-w-[75%] sm:max-w-[55%] rounded-lg px-3 py-2 whitespace-pre-wrap bg-primary text-primary-foreground mt-6 self-end break-words">
{reply}
</div>
)}

{response && (
<div className="flex gap-2 items-center">
<div className="flex gap-2 items-center mt-6">
<Avatar>
<AvatarImage className="rounded-full" src={imageUrl ?? ""} />
<AvatarFallback>
Expand Down
11 changes: 10 additions & 1 deletion apps/www/src/app/components/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ const ShareLinkDialog = dynamic(() => import("./share-link-dialog"), {

export async function Navbar() {
const { user } = await getSession();
const version = process.env.NEXT_PUBLIC_VERSION
? process.env.NEXT_PUBLIC_VERSION
: "v2.0.0";

return (
<nav className="">
Expand All @@ -30,7 +33,13 @@ export async function Navbar() {
<span className="text-muted-foreground font-medium">.link</span>
</Link>

<Badge variant="outline">v2.0</Badge>
<Link
href={`https://github.com/omsimos/umamin/releases/tag/${version}`}
target="_blank"
title="Release Notes"
>
<Badge variant="outline">{version}</Badge>
</Link>
</div>

<div className="flex items-center">
Expand Down
81 changes: 46 additions & 35 deletions apps/www/src/app/inbox/components/received/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import { toast } from "sonner";
import dynamic from "next/dynamic";
import { graphql } from "gql.tada";
import { useEffect, useState } from "react";
import { useInView } from "react-intersection-observer";
import { useCallback, useEffect, useState } from "react";

import { client } from "@/lib/gql/client";
import client from "@/lib/gql/client";
import { ReceivedMessagesResult } from "../../queries";
import { Skeleton } from "@umamin/ui/components/skeleton";
import { useMessageStore } from "@/store/useMessageStore";
import { ReceivedMessageCard, receivedMessageFragment } from "./card";

const AdContainer = dynamic(() => import("@umamin/ui/ad"), { ssr: false });
Expand Down Expand Up @@ -48,47 +49,46 @@ export function ReceivedMessagesList({
createdAt: messages[messages.length - 1]?.createdAt ?? null,
});

const [msgList, setMsgList] = useState(messages);
const msgList = useMessageStore((state) => state.receivedList);
const updateMsgList = useMessageStore((state) => state.updateReceivedList);

const [hasMore, setHasMore] = useState(messages?.length === 10);
const [isFetching, setIsFetching] = useState(false);

function loadMessages() {
const loadMessages = useCallback(async () => {
if (hasMore) {
setIsFetching(true);

client
.query(MESSAGES_FROM_CURSOR_QUERY, {
input: {
type: "received",
cursor,
},
})
.toPromise()
.then((res) => {
if (res.error) {
toast.error(res.error.message);
return;
}

const _res = res.data?.messagesFromCursor;

if (_res?.cursor) {
setCursor({
id: _res.cursor.id,
createdAt: _res.cursor.createdAt,
});

setHasMore(_res.hasMore);
}

if (_res?.data) {
setMsgList([...msgList, ..._res.data]);
}

setIsFetching(false);
const res = await client.query(MESSAGES_FROM_CURSOR_QUERY, {
input: {
type: "received",
cursor,
},
});

if (res.error) {
toast.error(res.error.message);
return;
}

const _res = res.data?.messagesFromCursor;

if (_res?.cursor) {
setCursor({
id: _res.cursor.id,
createdAt: _res.cursor.createdAt,
});

setHasMore(_res.hasMore);
}

if (_res?.data) {
updateMsgList(_res.data);
}

setIsFetching(false);
}
}
}, [cursor, hasMore, msgList]);

useEffect(() => {
if (inView && !isFetching) {
Expand All @@ -98,6 +98,17 @@ export function ReceivedMessagesList({

return (
<>
{messages?.map((msg, i) => (
<div key={msg.id} className="w-full">
<ReceivedMessageCard data={msg} />

{/* v2-received-list */}
{(i + 1) % 5 === 0 && (
<AdContainer className="mt-5" slotId="1546692714" />
)}
</div>
))}

{msgList?.map((msg, i) => (
<div key={msg.id} className="w-full">
<ReceivedMessageCard data={msg} />
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/app/inbox/components/received/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { toast } from "sonner";
import { useState } from "react";
import { graphql } from "gql.tada";
import { client } from "@/lib/gql/client";
import client from "@/lib/gql/client";
import { logEvent } from "firebase/analytics";

import { ReplyDialog } from "./reply";
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/app/inbox/components/received/messages.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { cache } from "react";
import { getClient } from "@/lib/gql/rsc";
import getClient from "@/lib/gql/rsc";
import { ReceivedMessagesList } from "./list";
import { RECEIVED_MESSAGES_QUERY } from "../../queries";

Expand Down
99 changes: 56 additions & 43 deletions apps/www/src/app/inbox/components/received/reply.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { toast } from "sonner";
import { graphql } from "gql.tada";
import { useRouter } from "next/navigation";
import { Loader2, Send } from "lucide-react";
import { logEvent } from "firebase/analytics";
import { FormEventHandler, useState } from "react";
import { formatDistanceToNow, fromUnixTime } from "date-fns";

import { client } from "@/lib/gql/client";
import client from "@/lib/gql/client";
import { cn } from "@umamin/ui/lib/utils";
import { formatError } from "@/lib/utils";
import { analytics } from "@/lib/firebase";

import type { ReceivedMenuProps } from "./menu";
import { Input } from "@umamin/ui/components/input";
import { Button } from "@umamin/ui/components/button";
import { ChatList } from "@/app/components/chat-list";
import { Textarea } from "@umamin/ui/components/textarea";
import { useDynamicTextarea } from "@/hooks/use-dynamic-textarea";
import { Dialog, DialogContent } from "@umamin/ui/components/dialog";
import { useRouter } from "next/navigation";

type Props = {
open: boolean;
Expand All @@ -35,6 +37,7 @@ export function ReplyDialog(props: Props) {
const [loading, setLoading] = useState(false);
const [reply, setReply] = useState(props.data.reply ?? "");
const [updatedAt, setUpdatedAt] = useState(props.data.updatedAt);
const inputRef = useDynamicTextarea(content);

const onReply: FormEventHandler = async (e) => {
e.preventDefault();
Expand Down Expand Up @@ -63,50 +66,60 @@ export function ReplyDialog(props: Props) {

return (
<Dialog open={props.open} onOpenChange={props.onOpenChange}>
<DialogContent className="sm:max-w-xl">
<h3 className="font-bold text-center leading-normal text-lg min-w-0 break-words mb-6">
{props.data.question}
</h3>
<DialogContent className="sm:max-w-xl p-0">
<div
className={cn(
"h-full max-h-[500px] overflow-scroll px-5 sm:px-7 py-10",
!reply ? "pb-28" : ""
)}
>
<h3 className="font-bold text-center leading-normal text-lg min-w-0 break-words mb-10">
{props.data.question}
</h3>

<ChatList
question={props.data.content}
reply={props.data.reply ?? reply}
/>
<ChatList
question={props.data.content}
reply={props.data.reply ?? reply}
/>

{reply && updatedAt && (
<span className="text-muted-foreground text-sm italic w-full text-center mt-6">
replied{" "}
{formatDistanceToNow(fromUnixTime(updatedAt), {
addSuffix: true,
})}
</span>
)}
{reply && updatedAt && (
<div className="text-muted-foreground text-sm italic w-full text-center mt-10">
replied{" "}
{formatDistanceToNow(fromUnixTime(updatedAt), {
addSuffix: true,
})}
</div>
)}
</div>

{!reply && (
<form
onSubmit={onReply}
className="flex max-w-lg items-center space-x-2 w-full self-center mt-12"
>
<Input
id="message"
required
disabled={loading}
value={content}
onChange={(e) => setContent(e.target.value)}
maxLength={1000}
placeholder="Type your reply..."
className="focus-visible:ring-transparent flex-1 text-base"
autoComplete="off"
/>
<Button type="submit" size="icon">
{loading ? (
<Loader2 className="w-4 h-4 animate-spin" />
) : (
<Send className="h-4 w-4" />
)}
<span className="sr-only">Send</span>
</Button>
</form>
<div className="fixed px-5 sm:px-7 bottom-0 left-1/2 -translate-x-1/2 w-full pb-4 rounded-b-lg bg-background pt-3 max-w-xl">
<form
onSubmit={onReply}
className="flex items-center space-x-2 w-full self-center"
>
<Textarea
id="message"
required
ref={inputRef}
disabled={loading}
value={content}
onChange={(e) => setContent(e.target.value)}
maxLength={500}
placeholder="Type your reply..."
className="focus-visible:ring-transparent flex-1 text-base resize-none min-h-10 max-h-20"
autoComplete="off"
/>
<Button type="submit" size="icon">
{loading ? (
<Loader2 className="w-4 h-4 animate-spin" />
) : (
<Send className="h-4 w-4" />
)}
<span className="sr-only">Send</span>
</Button>
</form>
</div>
)}
</DialogContent>
</Dialog>
Expand Down
Loading

0 comments on commit 97bbfba

Please sign in to comment.