creating and retrieving links successfully
This commit is contained in:
@@ -12,7 +12,7 @@ export default class Conversation {
|
|||||||
membersInLiveRoom: string[] = [] as string[]; // all members in a live call right now for this convo
|
membersInLiveRoom: string[] = [] as string[]; // all members in a live call right now for this convo
|
||||||
|
|
||||||
cachedAudioClip?: AudioClip; // last message pretty much
|
cachedAudioClip?: AudioClip; // last message pretty much
|
||||||
cachedDrawerItem?: Link; // last link pretty much
|
cachedLink?: Link; // last link pretty much
|
||||||
|
|
||||||
tldr?: string; // description almost that people keep up to day in the convo
|
tldr?: string; // description almost that people keep up to day in the convo
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ export class Link {
|
|||||||
|
|
||||||
url: string;
|
url: string;
|
||||||
name: string;
|
name: string;
|
||||||
type: LinkType;
|
// type: LinkType;
|
||||||
|
|
||||||
createdByUserId: string;
|
createdByUserId: string;
|
||||||
createdDate: Timestamp = Timestamp.now();
|
createdDate: Timestamp = Timestamp.now();
|
||||||
@@ -101,7 +101,7 @@ export class Link {
|
|||||||
this.createdByUserId = _senderUserId;
|
this.createdByUserId = _senderUserId;
|
||||||
this.url = _linkUrl;
|
this.url = _linkUrl;
|
||||||
this.name = _name;
|
this.name = _name;
|
||||||
this.type = Link.getLinkType(_linkUrl);
|
// this.type = Link.getLinkType(_linkUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getLinkType(url: string): LinkType {
|
static getLinkType(url: string): LinkType {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ enum Collections {
|
|||||||
conversations = "conversations",
|
conversations = "conversations",
|
||||||
conversationMembers = "members",
|
conversationMembers = "members",
|
||||||
conversationAudioClips = "audioClips",
|
conversationAudioClips = "audioClips",
|
||||||
|
conversationLinks = "links",
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Collections;
|
export default Collections;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import Conversation, {
|
|||||||
AudioClip,
|
AudioClip,
|
||||||
ConversationMember,
|
ConversationMember,
|
||||||
ConversationMemberState,
|
ConversationMemberState,
|
||||||
|
Link,
|
||||||
} from "../models/conversation";
|
} from "../models/conversation";
|
||||||
import Collections from "./collections";
|
import Collections from "./collections";
|
||||||
import { cloudStorageService } from "./index";
|
import { cloudStorageService } from "./index";
|
||||||
@@ -210,4 +211,51 @@ export default class ConversationService {
|
|||||||
{ merge: true }
|
{ merge: true }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async shareLink(createdByUserId: string, link: Link, convoId: string) {
|
||||||
|
const linkRef = doc(
|
||||||
|
this.db,
|
||||||
|
Collections.conversations,
|
||||||
|
convoId,
|
||||||
|
Collections.conversationLinks,
|
||||||
|
link.id
|
||||||
|
);
|
||||||
|
const conversationDoc = doc(this.db, Collections.conversations, convoId);
|
||||||
|
const userConvoAssocDoc = doc(
|
||||||
|
this.db,
|
||||||
|
Collections.conversations,
|
||||||
|
convoId,
|
||||||
|
Collections.conversationMembers,
|
||||||
|
createdByUserId
|
||||||
|
);
|
||||||
|
|
||||||
|
await runTransaction(this.db, async (transaction) => {
|
||||||
|
// want to add to the long term collection of all links for a conversation
|
||||||
|
transaction.set(
|
||||||
|
linkRef,
|
||||||
|
{ ...link, createdDate: serverTimestamp() },
|
||||||
|
{ merge: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// want to make updates to the conversation document itself: set the last item for just the basic information to be
|
||||||
|
// published to users
|
||||||
|
transaction.set(
|
||||||
|
conversationDoc,
|
||||||
|
{
|
||||||
|
lastActivityDate: serverTimestamp(),
|
||||||
|
cachedLink: { ...link, createdDate: serverTimestamp() },
|
||||||
|
},
|
||||||
|
{ merge: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// update the user's convo assoc so that their last interaction was set properly
|
||||||
|
transaction.set(
|
||||||
|
userConvoAssocDoc,
|
||||||
|
{
|
||||||
|
lastInteractionDate: serverTimestamp(),
|
||||||
|
},
|
||||||
|
{ merge: true }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,27 @@
|
|||||||
import { Link } from "@nirvana/common/models/conversation";
|
import { Link } from "@nirvana/common/models/conversation";
|
||||||
|
import { conversationService } from "@nirvana/common/services";
|
||||||
import Modal from "antd/lib/modal/Modal";
|
import Modal from "antd/lib/modal/Modal";
|
||||||
import { useState, useEffect } from "react";
|
import Image from "next/image";
|
||||||
|
import { useState, useEffect, useRef } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import LinkIcon from "./LinkIcon";
|
import { useRecoilValue } from "recoil";
|
||||||
|
import { useAuth } from "../../contexts/authContext";
|
||||||
|
import { selectedConvoAtom } from "../../recoil/main";
|
||||||
|
import LinkIcon, { getFavicon } from "./LinkIcon";
|
||||||
|
|
||||||
export default function CreateItemModal(props: {
|
export default function CreateItemModal(props: {
|
||||||
pastedLink: string;
|
pastedLink: string;
|
||||||
show: boolean;
|
show: boolean;
|
||||||
handleClose: () => void;
|
handleClose: () => void;
|
||||||
}) {
|
}) {
|
||||||
|
const { currUser } = useAuth();
|
||||||
|
|
||||||
const [linkVal, setLinkVal] = useState<string>("");
|
const [linkVal, setLinkVal] = useState<string>("");
|
||||||
const [linkDesc, setLinkDesc] = useState<string>("");
|
const [linkDesc, setLinkDesc] = useState<string>("");
|
||||||
|
const linkInput = useRef<HTMLInputElement>();
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const selectedConvoId = useRecoilValue(selectedConvoAtom);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (props.pastedLink) {
|
if (props.pastedLink) {
|
||||||
@@ -18,9 +29,55 @@ export default function CreateItemModal(props: {
|
|||||||
}
|
}
|
||||||
}, [props.pastedLink]);
|
}, [props.pastedLink]);
|
||||||
|
|
||||||
const handleCreate = () => {
|
useEffect(() => {
|
||||||
console.log("added drawer item");
|
linkInput.current?.focus();
|
||||||
toast.success("added drawer item to conversation");
|
}, [props.show]);
|
||||||
|
|
||||||
|
const handleCreate = async () => {
|
||||||
|
if (loading) {
|
||||||
|
toast("in the process of sharing...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// validations
|
||||||
|
if (!linkVal) {
|
||||||
|
toast.error("must put a link");
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!linkDesc) {
|
||||||
|
toast.error("must put a name of some sort");
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// service to add link to the collection
|
||||||
|
// change the cacheddraweritem on the convo doc
|
||||||
|
const newLink = new Link(linkDesc, linkVal, currUser!.uid);
|
||||||
|
|
||||||
|
await conversationService.shareLink(
|
||||||
|
currUser!.uid,
|
||||||
|
newLink,
|
||||||
|
selectedConvoId!
|
||||||
|
);
|
||||||
|
|
||||||
|
toast.success("shared");
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("problem in sharing link");
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
resetForm();
|
||||||
|
props.handleClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
setLinkDesc("");
|
||||||
|
setLinkVal("");
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
@@ -28,15 +85,44 @@ export default function CreateItemModal(props: {
|
|||||||
props.handleClose();
|
props.handleClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleChangeLinkInput = (e) => {
|
||||||
|
setLinkVal(e.target.value);
|
||||||
|
|
||||||
|
// todo: find the tab name of the url
|
||||||
|
};
|
||||||
|
|
||||||
|
function addDefaultSrc(ev) {
|
||||||
|
ev.target.src = getFavicon("www.com");
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title="Share"
|
title="Share"
|
||||||
onOk={handleCreate}
|
onOk={handleCreate}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
|
footer={
|
||||||
|
<span className="flex flex-row justify-end space-x-2">
|
||||||
|
<button
|
||||||
|
onClick={handleCancel}
|
||||||
|
className="rounded-lg p-2 border space-x-2
|
||||||
|
text-slate-400 text-xs hover:bg-slate-50"
|
||||||
|
>
|
||||||
|
<span>Cancel</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={handleCreate}
|
||||||
|
type="submit"
|
||||||
|
className="rounded-lg font-semibold bg-teal-600 p-2 text-white shadow-lg"
|
||||||
|
>
|
||||||
|
<span>Share</span>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
visible={props.show}
|
visible={props.show}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<span className="flex flex-col space-y-5">
|
<form onSubmit={handleCreate} className="flex flex-col space-y-5">
|
||||||
<span className="flex flex-col items-start">
|
<span className="flex flex-col items-start">
|
||||||
<span className="text-lg font-semibold">Link</span>
|
<span className="text-lg font-semibold">Link</span>
|
||||||
<span className="text-gray-300 text-sm mb-2">
|
<span className="text-gray-300 text-sm mb-2">
|
||||||
@@ -44,17 +130,22 @@ export default function CreateItemModal(props: {
|
|||||||
</span>
|
</span>
|
||||||
{/* icon and link input */}
|
{/* icon and link input */}
|
||||||
<span className="flex flex-row items-center space-x-2 w-full">
|
<span className="flex flex-row items-center space-x-2 w-full">
|
||||||
<LinkIcon
|
{linkVal && (
|
||||||
className="text-3xl"
|
<img
|
||||||
linkType={Link.getLinkType(linkVal)}
|
height="30"
|
||||||
/>
|
width="30"
|
||||||
|
src={getFavicon(linkVal)}
|
||||||
|
onError={addDefaultSrc}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<input
|
<input
|
||||||
|
ref={linkInput}
|
||||||
autoFocus
|
autoFocus
|
||||||
className="flex-1 rounded-lg bg-gray-50 p-3"
|
className="flex-1 rounded-lg bg-gray-50 p-3"
|
||||||
value={linkVal}
|
value={linkVal}
|
||||||
placeholder="https://jira.atlassian.com/team/xxx"
|
placeholder="https://jira.atlassian.com/team/xxx"
|
||||||
onChange={(e) => setLinkVal(e.target.value)}
|
onChange={handleChangeLinkInput}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -72,7 +163,7 @@ export default function CreateItemModal(props: {
|
|||||||
onChange={(e) => setLinkDesc(e.target.value)}
|
onChange={(e) => setLinkDesc(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ import Link, { LinkType } from "@nirvana/common/models/conversation";
|
|||||||
|
|
||||||
import { SiGooglemeet, SiZoom } from "react-icons/si";
|
import { SiGooglemeet, SiZoom } from "react-icons/si";
|
||||||
|
|
||||||
|
const faviconGrabberAPI = "https://api.statvoo.com/favicon/?url=";
|
||||||
|
export function getFavicon(url: string): string {
|
||||||
|
return faviconGrabberAPI + url;
|
||||||
|
}
|
||||||
|
|
||||||
export default function LinkIcon(props: {
|
export default function LinkIcon(props: {
|
||||||
className?: string;
|
className?: string;
|
||||||
linkType: LinkType;
|
linkType: LinkType;
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { Link } from "@nirvana/common/models/conversation";
|
||||||
|
import { Tooltip } from "antd";
|
||||||
|
import { linkWithCredential } from "firebase/auth";
|
||||||
|
import moment from "moment";
|
||||||
|
import link from "next/link";
|
||||||
|
import { FaImages, FaExternalLinkAlt } from "react-icons/fa";
|
||||||
|
import { getFavicon } from "./LinkIcon";
|
||||||
|
|
||||||
|
export default function SharedItemsRow(props: { link: Link }) {
|
||||||
|
const { link } = props;
|
||||||
|
|
||||||
|
function addDefaultSrc(ev) {
|
||||||
|
ev.target.src = getFavicon("www.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className="group flex flex-row items-center border-t
|
||||||
|
p-2 hover:bg-slate-50 transition-all shrink-0 text-ellipsis last:border-b w-[18rem]"
|
||||||
|
>
|
||||||
|
{/* <span className="rounded-lg bg-slate-200 p-2 hover:cursor-pointer"></span> */}
|
||||||
|
|
||||||
|
<img
|
||||||
|
height="30"
|
||||||
|
width="30"
|
||||||
|
src={getFavicon(link.url)}
|
||||||
|
onError={addDefaultSrc}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Tooltip title={link.name}>
|
||||||
|
<span className="flex flex-col ml-2 max-w-[10rem]">
|
||||||
|
<span className="text-slate-400 text-sm truncate">{link.name}</span>
|
||||||
|
<span className="text-slate-300 text-xs">
|
||||||
|
{moment(link.createdDate.toDate()).fromNow()}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<span className="flex flex-row ml-auto space-x-1 group-hover:visible invisible">
|
||||||
|
<Tooltip title={"Add to personal drawer."}>
|
||||||
|
<span className="p-2 rounded-full hover:cursor-pointer hover:bg-slate-200 ">
|
||||||
|
<FaImages className="text-xl text-slate-400" />
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip title={link.url}>
|
||||||
|
<span
|
||||||
|
onClick={() => window.open(link.url, "_blank")}
|
||||||
|
className="p-2 rounded-full hover:cursor-pointer hover:bg-slate-200 "
|
||||||
|
>
|
||||||
|
<FaExternalLinkAlt className="text-lg text-slate-400" />
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LinkType } from "@nirvana/common/models/conversation";
|
import { Link, LinkType } from "@nirvana/common/models/conversation";
|
||||||
import { UserStatus } from "@nirvana/common/models/user";
|
import { UserStatus } from "@nirvana/common/models/user";
|
||||||
import { Tooltip } from "antd";
|
import { Tooltip } from "antd";
|
||||||
import { duration } from "moment";
|
import { duration } from "moment";
|
||||||
@@ -49,6 +49,7 @@ import {
|
|||||||
onSnapshot,
|
onSnapshot,
|
||||||
orderBy,
|
orderBy,
|
||||||
query,
|
query,
|
||||||
|
Unsubscribe,
|
||||||
where,
|
where,
|
||||||
} from "firebase/firestore";
|
} from "firebase/firestore";
|
||||||
|
|
||||||
@@ -59,6 +60,8 @@ import Modal from "antd/lib/modal/Modal";
|
|||||||
import { configure, GlobalHotKeys, KeyMap } from "react-hotkeys";
|
import { configure, GlobalHotKeys, KeyMap } from "react-hotkeys";
|
||||||
import CreateItemModal from "../Drawer/CreateItemModal";
|
import CreateItemModal from "../Drawer/CreateItemModal";
|
||||||
import isValidHttpUrl from "../../helpers/urlHelper";
|
import isValidHttpUrl from "../../helpers/urlHelper";
|
||||||
|
import { FaPlus } from "react-icons/fa";
|
||||||
|
import SharedItemsRow from "../Drawer/SharedItemsRow";
|
||||||
|
|
||||||
const testDrawerItems: {
|
const testDrawerItems: {
|
||||||
linkType: LinkType;
|
linkType: LinkType;
|
||||||
@@ -88,6 +91,7 @@ const testDrawerItems: {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const AUDIO_CLIP_FETCH_LIMIT = 50;
|
const AUDIO_CLIP_FETCH_LIMIT = 50;
|
||||||
|
const LINK_FETCH_LIMIT = 5;
|
||||||
|
|
||||||
export default function ViewConvo(props: { conversationId: string }) {
|
export default function ViewConvo(props: { conversationId: string }) {
|
||||||
const { currUser } = useAuth();
|
const { currUser } = useAuth();
|
||||||
@@ -114,11 +118,15 @@ export default function ViewConvo(props: { conversationId: string }) {
|
|||||||
|
|
||||||
const setSelectedConvoId = useSetRecoilState(selectedConvoAtom);
|
const setSelectedConvoId = useSetRecoilState(selectedConvoAtom);
|
||||||
|
|
||||||
|
const [sharedItems, setSharedItems] = useState<Link[]>([] as Link[]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
endOfTimeline.current?.scrollIntoView({ behavior: "smooth" });
|
endOfTimeline.current?.scrollIntoView({ behavior: "smooth" });
|
||||||
}, [audioClips]);
|
}, [audioClips]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const unsubs: Unsubscribe[] = [] as Unsubscribe[];
|
||||||
|
|
||||||
// should have this convo, otherwise unauthorized
|
// should have this convo, otherwise unauthorized
|
||||||
if (!convo || !convo.activeMembers.includes(currUser!.uid)) {
|
if (!convo || !convo.activeMembers.includes(currUser!.uid)) {
|
||||||
toast.error("Not authorized for this conversation");
|
toast.error("Not authorized for this conversation");
|
||||||
@@ -147,7 +155,7 @@ export default function ViewConvo(props: { conversationId: string }) {
|
|||||||
orderBy("createdDate", "desc"),
|
orderBy("createdDate", "desc"),
|
||||||
limit(AUDIO_CLIP_FETCH_LIMIT)
|
limit(AUDIO_CLIP_FETCH_LIMIT)
|
||||||
);
|
);
|
||||||
const unsubscribe = onSnapshot(audioClipsQuery, (querySnapshot) => {
|
const unsubscribeAudClips = onSnapshot(audioClipsQuery, (querySnapshot) => {
|
||||||
const audioClips: AudioClip[] = [] as AudioClip[];
|
const audioClips: AudioClip[] = [] as AudioClip[];
|
||||||
|
|
||||||
querySnapshot.forEach((doc) => {
|
querySnapshot.forEach((doc) => {
|
||||||
@@ -162,7 +170,40 @@ export default function ViewConvo(props: { conversationId: string }) {
|
|||||||
console.log(audioClips);
|
console.log(audioClips);
|
||||||
});
|
});
|
||||||
|
|
||||||
return unsubscribe;
|
unsubs.push(unsubscribeAudClips);
|
||||||
|
|
||||||
|
// links retrieval real time
|
||||||
|
const linksQuery = query(
|
||||||
|
collection(
|
||||||
|
db,
|
||||||
|
Collections.conversations,
|
||||||
|
props.conversationId,
|
||||||
|
Collections.conversationLinks
|
||||||
|
),
|
||||||
|
orderBy("createdDate", "desc"),
|
||||||
|
limit(LINK_FETCH_LIMIT)
|
||||||
|
);
|
||||||
|
const unsubscribeLinks = onSnapshot(linksQuery, (querySnapshot) => {
|
||||||
|
const links: Link[] = [] as Link[];
|
||||||
|
|
||||||
|
querySnapshot.forEach((doc) => {
|
||||||
|
const link = doc.data() as Link;
|
||||||
|
link.id = doc.id;
|
||||||
|
|
||||||
|
// appending all messages in sort order
|
||||||
|
links.push(link);
|
||||||
|
});
|
||||||
|
|
||||||
|
setSharedItems(links);
|
||||||
|
});
|
||||||
|
|
||||||
|
unsubs.push(unsubscribeLinks);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
unsubs.forEach((unsub) => {
|
||||||
|
unsub();
|
||||||
|
});
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleOrganizeConversation = async (
|
const handleOrganizeConversation = async (
|
||||||
@@ -454,50 +495,25 @@ export default function ViewConvo(props: { conversationId: string }) {
|
|||||||
|
|
||||||
{/* drawer items */}
|
{/* drawer items */}
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<span className="text-md tracking-widest font-semibold text-slate-300 uppercase mb-2">
|
<span className="flex flex-row justify-between items-center mb-2">
|
||||||
Shared
|
<span className="text-md tracking-widest font-semibold text-slate-300 uppercase">
|
||||||
|
Shared
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<Tooltip title={"CTRL+V to share a link."}>
|
||||||
|
<span
|
||||||
|
onClick={handleOpenDrawerItemModal}
|
||||||
|
className="p-2 rounded-full hover:cursor-pointer hover:bg-slate-200 "
|
||||||
|
>
|
||||||
|
<FaPlus className="ml-auto text-md text-slate-400" />
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{/* row of cards drawer items */}
|
{/* row of cards drawer items */}
|
||||||
<span className="flex flex-col items-stretch">
|
<span className="flex flex-col items-stretch">
|
||||||
{testDrawerItems.map((link) => (
|
{sharedItems.map((link) => (
|
||||||
<span
|
<SharedItemsRow key={link.id} link={link} />
|
||||||
key={link.linkName}
|
|
||||||
className="group flex flex-row items-center border-t
|
|
||||||
p-2 hover:bg-slate-50 transition-all shrink-0 text-ellipsis last:border-b"
|
|
||||||
>
|
|
||||||
{/* <span className="rounded-lg bg-slate-200 p-2 hover:cursor-pointer"></span> */}
|
|
||||||
|
|
||||||
<LinkIcon
|
|
||||||
linkType={link.linkType}
|
|
||||||
className="text-3xl shrink-0"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Tooltip title={link.linkName}>
|
|
||||||
<span className="flex flex-col ml-2 max-w-[10rem]">
|
|
||||||
<span className="text-slate-400 text-sm truncate">
|
|
||||||
{link.linkName}
|
|
||||||
</span>
|
|
||||||
<span className="text-slate-300 text-xs">
|
|
||||||
{link.relativeSentTime}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<span className="flex flex-row ml-auto space-x-1 group-hover:visible invisible">
|
|
||||||
<Tooltip title={"Add to personal drawer."}>
|
|
||||||
<span className="p-2 rounded-full hover:cursor-pointer hover:bg-slate-200 ">
|
|
||||||
<FaImages className="text-xl text-slate-400" />
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip title={"https://usenirvana.com"}>
|
|
||||||
<span className="p-2 rounded-full hover:cursor-pointer hover:bg-slate-200 ">
|
|
||||||
<FaExternalLinkAlt className="text-lg text-slate-400" />
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
))}
|
))}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -531,15 +547,6 @@ export default function ViewConvo(props: { conversationId: string }) {
|
|||||||
<FaPlay className="text-xl" />
|
<FaPlay className="text-xl" />
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip title={"CTRL+V to share a link."}>
|
|
||||||
<span
|
|
||||||
className={`shadow-lg flex flex-row items-center p-5 justify-center
|
|
||||||
rounded-lg font-bold bg-slate-50 text-purple-600`}
|
|
||||||
>
|
|
||||||
<FaLink className="text-xl" />
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user