a tool for shared writing and social publishing

use localized dates for localeTimeString as well

+52 -48
+12 -14
app/lish/[did]/[publication]/[rkey]/Interactions/Comments/index.tsx
··· 17 17 import { usePathname } from "next/navigation"; 18 18 import { QuoteContent } from "../Quotes"; 19 19 import { timeAgo } from "src/utils/timeAgo"; 20 + import { useLocalizedDate } from "src/hooks/useLocalizedDate"; 20 21 21 22 export type Comment = { 22 23 record: Json; ··· 250 251 }; 251 252 252 253 const DatePopover = (props: { date: string }) => { 253 - let [t, full] = useMemo(() => { 254 - return [ 255 - timeAgo(props.date), 256 - new Date(props.date).toLocaleTimeString(undefined, { 257 - year: "numeric", 258 - month: "2-digit", 259 - day: "2-digit", 260 - hour: "2-digit", 261 - minute: "2-digit", 262 - }), 263 - ]; 264 - }, [props.date]); 254 + const timeAgoText = useMemo(() => timeAgo(props.date), [props.date]); 255 + const fullDate = useLocalizedDate(props.date, { 256 + year: "numeric", 257 + month: "2-digit", 258 + day: "2-digit", 259 + hour: "2-digit", 260 + minute: "2-digit", 261 + }); 262 + 265 263 return ( 266 264 <Popover 267 265 trigger={ 268 - <div className="italic text-sm text-tertiary hover:underline">{t}</div> 266 + <div className="italic text-sm text-tertiary hover:underline">{timeAgoText}</div> 269 267 } 270 268 > 271 - <div className="text-sm text-secondary">{full}</div> 269 + <div className="text-sm text-secondary">{fullDate}</div> 272 270 </Popover> 273 271 ); 274 272 };
+11 -13
app/lish/[did]/[publication]/[rkey]/PublishBskyPostBlock.tsx
··· 10 10 import { useInitialPageLoad } from "components/InitialPageLoadProvider"; 11 11 import { BlueskyTiny } from "components/Icons/BlueskyTiny"; 12 12 import { CommentTiny } from "components/Icons/CommentTiny"; 13 + import { useLocalizedDate } from "src/hooks/useLocalizedDate"; 13 14 import { 14 15 BlueskyEmbed, 15 16 PostNotAvailable, ··· 121 122 122 123 const ClientDate = (props: { date?: string }) => { 123 124 let pageLoaded = useInitialPageLoad(); 125 + const formattedDate = useLocalizedDate(props.date || new Date().toISOString(), { 126 + month: "short", 127 + day: "numeric", 128 + year: "numeric", 129 + hour: "numeric", 130 + minute: "numeric", 131 + hour12: true, 132 + }); 133 + 124 134 if (!pageLoaded) return null; 125 135 126 - let datetimeFormatted = new Date(props.date ? props.date : "").toLocaleString( 127 - "en-US", 128 - { 129 - month: "short", 130 - day: "numeric", 131 - year: "numeric", 132 - hour: "numeric", 133 - minute: "numeric", 134 - hour12: true, 135 - }, 136 - ); 137 - 138 - return <div className="text-xs text-tertiary">{datetimeFormatted}</div>; 136 + return <div className="text-xs text-tertiary">{formattedDate}</div>; 139 137 };
+15 -7
app/lish/[did]/[publication]/dashboard/PublicationSubscribers.tsx
··· 8 8 import { MoreOptionsVerticalTiny } from "components/Icons/MoreOptionsVerticalTiny"; 9 9 import { Checkbox } from "components/Checkbox"; 10 10 import { useEffect, useState } from "react"; 11 + import { useLocalizedDate } from "src/hooks/useLocalizedDate"; 11 12 12 13 type subscriber = { email: string | undefined; did: string | undefined }; 13 14 ··· 198 199 @{props.handle} 199 200 </a> 200 201 )} 201 - <div className="px-1 py-0 h-max rounded-md text-sm italic text-tertiary"> 202 - {new Date(props.createdAt).toLocaleString(undefined, { 203 - year: "2-digit", 204 - month: "2-digit", 205 - day: "2-digit", 206 - })} 207 - </div> 202 + <SubscriberDate createdAt={props.createdAt} /> 208 203 </div> 209 204 </> 210 205 // </Checkbox> ··· 235 230 </Menu> 236 231 ); 237 232 }; 233 + 234 + function SubscriberDate(props: { createdAt: string }) { 235 + const formattedDate = useLocalizedDate(props.createdAt, { 236 + year: "2-digit", 237 + month: "2-digit", 238 + day: "2-digit", 239 + }); 240 + return ( 241 + <div className="px-1 py-0 h-max rounded-md text-sm italic text-tertiary"> 242 + {formattedDate} 243 + </div> 244 + ); 245 + }
+14 -14
components/Blocks/BlueskyPostBlock/index.tsx
··· 13 13 import { useInitialPageLoad } from "components/InitialPageLoadProvider"; 14 14 import { BlueskyTiny } from "components/Icons/BlueskyTiny"; 15 15 import { CommentTiny } from "components/Icons/CommentTiny"; 16 + import { useLocalizedDate } from "src/hooks/useLocalizedDate"; 16 17 17 18 export const BlueskyPostBlock = (props: BlockProps & { preview?: boolean }) => { 18 19 let { permissions } = useEntitySetContext(); ··· 28 29 input?.focus(); 29 30 } else input?.blur(); 30 31 }, [isSelected, props.entityID, props.preview]); 31 - 32 - let initialPageLoad = useInitialPageLoad(); 33 32 34 33 switch (true) { 35 34 case !post: ··· 81 80 //getting the url to the post 82 81 let postId = post.post.uri.split("/")[4]; 83 82 let url = `https://bsky.app/profile/${post.post.author.handle}/post/${postId}`; 84 - 85 - let datetimeFormatted = initialPageLoad 86 - ? new Date(timestamp ? timestamp : "").toLocaleString("en-US", { 87 - month: "short", 88 - day: "numeric", 89 - year: "numeric", 90 - hour: "numeric", 91 - minute: "numeric", 92 - hour12: true, 93 - }) 94 - : ""; 95 83 96 84 return ( 97 85 <div ··· 141 129 </> 142 130 )} 143 131 <div className="w-full flex gap-2 items-center justify-between"> 144 - <div className="text-xs text-tertiary">{datetimeFormatted}</div> 132 + {timestamp && <PostDate timestamp={timestamp} />} 145 133 <div className="flex gap-2 items-center"> 146 134 {post.post.replyCount && post.post.replyCount > 0 && ( 147 135 <> ··· 166 154 ); 167 155 } 168 156 }; 157 + 158 + function PostDate(props: { timestamp: string }) { 159 + const formattedDate = useLocalizedDate(props.timestamp, { 160 + month: "short", 161 + day: "numeric", 162 + year: "numeric", 163 + hour: "numeric", 164 + minute: "numeric", 165 + hour12: true, 166 + }); 167 + return <div className="text-xs text-tertiary">{formattedDate}</div>; 168 + }