11/* refresh skip */
22
33import { TagItem } from "@mutinywallet/mutiny-wasm" ;
4- import {
5- cache ,
6- createAsync ,
7- revalidate ,
8- useNavigate ,
9- useParams
10- } from "@solidjs/router" ;
4+ import { createAsync , useNavigate , useParams } from "@solidjs/router" ;
115import {
126 createEffect ,
7+ createMemo ,
138 createResource ,
149 createSignal ,
1510 For ,
1611 Match ,
1712 onCleanup ,
13+ onMount ,
1814 Show ,
1915 Suspense ,
2016 Switch
@@ -40,7 +36,7 @@ import {
4036} from "~/components" ;
4137import { ParsedParams , toParsedParams } from "~/logic/waila" ;
4238import { useMegaStore } from "~/state/megaStore" ;
43- import { timeAgo } from "~/utils" ;
39+ import { createDeepSignal , timeAgo } from "~/utils" ;
4440
4541type CombinedMessagesAndActivity =
4642 | { kind : "message" ; content : FakeDirectMessage }
@@ -182,6 +178,72 @@ function SingleMessage(props: {
182178 ) ;
183179}
184180
181+ function MessageList ( props : {
182+ convo : CombinedMessagesAndActivity [ ] ;
183+ contact : TagItem ;
184+ } ) {
185+ let scrollRef : HTMLDivElement ;
186+
187+ onMount ( ( ) => {
188+ scrollRef . scrollIntoView ( ) ;
189+ } ) ;
190+
191+ // Details modal stuff
192+ const [ detailsOpen , setDetailsOpen ] = createSignal ( false ) ;
193+ const [ detailsKind , setDetailsKind ] = createSignal < HackActivityType > ( ) ;
194+ const [ detailsId , setDetailsId ] = createSignal ( "" ) ;
195+
196+ function openDetailsModal ( id : string , kind : HackActivityType ) {
197+ console . log ( "Opening details modal: " , id , kind ) ;
198+
199+ if ( ! id ) {
200+ console . warn ( "No id provided to openDetailsModal" ) ;
201+ return ;
202+ }
203+
204+ setDetailsId ( id ) ;
205+ setDetailsKind ( kind ) ;
206+ setDetailsOpen ( true ) ;
207+ }
208+
209+ return (
210+ < >
211+ < div class = "flex flex-col-reverse justify-end gap-4" >
212+ < For each = { props . convo } >
213+ { ( combined , index ) => (
214+ < >
215+ < Show when = { combined . kind === "activity" } >
216+ < div class = "rounded-lg bg-m-grey-800 px-4 pt-4" >
217+ < UnifiedActivityItem
218+ item = { combined . content as IActivityItem }
219+ onClick = { openDetailsModal }
220+ />
221+ </ div >
222+ </ Show >
223+ < Show when = { combined . kind === "message" } >
224+ < SingleMessage
225+ dm = { combined . content as FakeDirectMessage }
226+ counterPartyNpub = { props . contact . npub || "" }
227+ counterPartyContactId = { props . contact . id }
228+ />
229+ </ Show >
230+ </ >
231+ ) }
232+ </ For >
233+ </ div >
234+ < div ref = { ( el ) => ( scrollRef = el ) } id = "scroll-to-me" />
235+ < Show when = { detailsId ( ) && detailsKind ( ) } >
236+ < ActivityDetailsModal
237+ open = { detailsOpen ( ) }
238+ kind = { detailsKind ( ) }
239+ id = { detailsId ( ) }
240+ setOpen = { setDetailsOpen }
241+ />
242+ </ Show >
243+ </ >
244+ ) ;
245+ }
246+
185247export function Chat ( ) {
186248 const params = useParams ( ) ;
187249 const [ state , actions ] = useMegaStore ( ) ;
@@ -193,24 +255,41 @@ export function Chat() {
193255 return state . mutiny_wallet ?. get_tag_item ( params . id ) ;
194256 } ) ;
195257
258+ const [ lastFetch , setLastFetch ] = createSignal ( 0n ) ;
259+
196260 const [ convo , { refetch } ] = createResource (
197261 contact ,
198- async ( contact : TagItem ) => {
262+ async ( contact : TagItem , info ) => {
199263 // if (!contact() || !contact()?.npub) return undefined;
200264 if ( ! contact . npub ) return [ ] ;
201265 try {
202266 const activity = await state . mutiny_wallet ?. get_label_activity (
203267 params . id
204268 ) ;
205269 console . log ( "activity" , activity ) ;
270+ const refetchingTimestamp = info . refetching as bigint ;
271+ console . log ( "refetching since" , refetchingTimestamp ) ;
206272 const convo = await state . mutiny_wallet ?. get_dm_conversation (
207273 // Mutinynet npub, for testing
208274 // "npub1qf8e8cvfp60ywrah984zgsn8veggcrsv2cvttdr47tgz05ypf5yszwx308",
209275 contact . npub ,
210276 20n ,
211- undefined
277+ refetchingTimestamp ? refetchingTimestamp : undefined
212278 ) ;
213279
280+ const lastConvo = info . value as CombinedMessagesAndActivity [ ] ;
281+ if (
282+ lastConvo &&
283+ lastConvo . length === convo . length + activity . length
284+ ) {
285+ console . log ( "no new messages or activity" ) ;
286+ return lastConvo ;
287+ }
288+
289+ console . log ( "dms" , convo ) ;
290+
291+ setLastFetch ( BigInt ( Math . floor ( Date . now ( ) / 1000 ) ) ) ;
292+
214293 const dms = convo as FakeDirectMessage [ ] ;
215294 const acts = activity as IActivityItem [ ] ;
216295
@@ -248,14 +327,14 @@ export function Chat() {
248327 return b_time - a_time ;
249328 } ) ;
250329
251- return combined . reverse ( ) as CombinedMessagesAndActivity [ ] ;
252-
253- // return combined as FakeDirectMessage[];
254- return [ ] ;
330+ return combined as CombinedMessagesAndActivity [ ] ;
255331 } catch ( e ) {
256332 console . error ( "error getting convo:" , e ) ;
257333 return [ ] ;
258334 }
335+ } ,
336+ {
337+ storage : createDeepSignal
259338 }
260339 ) ;
261340
@@ -270,33 +349,16 @@ export function Chat() {
270349 ) ;
271350 console . log ( "dmResult:" , dmResult ) ;
272351 setMessageValue ( "" ) ;
273- refetch ( ) ;
274- chatScrollRef ?. scrollTo ( {
275- top : chatScrollRef . scrollHeight
276- } ) ;
352+ refetch ( lastFetch ( ) ) ;
277353 } catch ( e ) {
278354 console . error ( "error sending dm:" , e ) ;
279355 }
280356 setSending ( false ) ;
281357 }
282358
283- let chatScrollRef : HTMLDivElement | null = null ;
284-
285- // For some reason I can't do scrolling here, but it works in send message
286-
287- // createEffect(() => {
288- // if (convo.latest?.length && chatScrollRef) {
289- // console.log("scrolling");
290-
291- // chatScrollRef?.scrollTo({
292- // top: chatScrollRef.scrollHeight
293- // });
294- // }
295- // });
296-
297359 createEffect ( ( ) => {
298360 const interval = setInterval ( ( ) => {
299- refetch ( ) ;
361+ refetch ( lastFetch ( ) ) ;
300362 } , 5000 ) ; // Poll every 5 seconds
301363 onCleanup ( ( ) => {
302364 clearInterval ( interval ) ;
@@ -344,24 +406,6 @@ export function Chat() {
344406 } ) ;
345407 }
346408
347- // Details modal stuff
348- const [ detailsOpen , setDetailsOpen ] = createSignal ( false ) ;
349- const [ detailsKind , setDetailsKind ] = createSignal < HackActivityType > ( ) ;
350- const [ detailsId , setDetailsId ] = createSignal ( "" ) ;
351-
352- function openDetailsModal ( id : string , kind : HackActivityType ) {
353- console . log ( "Opening details modal: " , id , kind ) ;
354-
355- if ( ! id ) {
356- console . warn ( "No id provided to openDetailsModal" ) ;
357- return ;
358- }
359-
360- setDetailsId ( id ) ;
361- setDetailsKind ( kind ) ;
362- setDetailsOpen ( true ) ;
363- }
364-
365409 return (
366410 < Transition
367411 mode = "outin"
@@ -393,10 +437,7 @@ export function Chat() {
393437 >
394438 < MutinyWalletGuard >
395439 < main class = "mx-auto grid h-[100dvh] w-full max-w-[600px] grid-cols-1 grid-rows-[minmax(10px,1fr)_4rem] flex-col overflow-y-hidden safe-top safe-bottom" >
396- < div
397- class = "overflow-y-auto"
398- ref = { ( el ) => ( chatScrollRef = el ) }
399- >
440+ < div class = "overflow-y-auto" >
400441 < div class = "fixed top-0 z-50 flex w-full flex-col gap-2 bg-m-grey-975/70 p-4 backdrop-blur-lg" >
401442 { /* <BackLink href="/" /> */ }
402443 < BackPop default = "/search" />
@@ -411,51 +452,16 @@ export function Chat() {
411452 { /* <pre class="whitespace-pre-wrap break-all">
412453 {JSON.stringify(convo(), null, 2)}
413454 </pre> */ }
414- < div class = "flex flex-col gap-4 p-4" >
455+ < div class = "p-4" >
415456 < Suspense >
416457 < Show when = { contact ( ) } >
417458 < Suspense fallback = { < LoadingShimmer /> } >
418- < For each = { convo . latest } >
419- { ( combined ) => (
420- < >
421- < Show
422- when = {
423- combined . kind ===
424- "activity"
425- }
426- >
427- < div class = "rounded-lg bg-m-grey-800 px-4 pt-4" >
428- < UnifiedActivityItem
429- item = {
430- combined . content as IActivityItem
431- }
432- onClick = {
433- openDetailsModal
434- }
435- />
436- </ div >
437- </ Show >
438- < Show
439- when = {
440- combined . kind ===
441- "message"
442- }
443- >
444- < SingleMessage
445- dm = {
446- combined . content as FakeDirectMessage
447- }
448- counterPartyNpub = {
449- contact ( ) ! . npub !
450- }
451- counterPartyContactId = {
452- params . id
453- }
454- />
455- </ Show >
456- </ >
457- ) }
458- </ For >
459+ < Show when = { convo . latest } >
460+ < MessageList
461+ convo = { convo . latest }
462+ contact = { contact ( ) ! }
463+ />
464+ </ Show >
459465 </ Suspense >
460466 </ Show >
461467 </ Suspense >
@@ -511,14 +517,6 @@ export function Chat() {
511517 </ div >
512518 </ div >
513519 </ main >
514- < Show when = { detailsId ( ) && detailsKind ( ) } >
515- < ActivityDetailsModal
516- open = { detailsOpen ( ) }
517- kind = { detailsKind ( ) }
518- id = { detailsId ( ) }
519- setOpen = { setDetailsOpen }
520- />
521- </ Show >
522520 </ MutinyWalletGuard >
523521 </ Transition >
524522 ) ;
0 commit comments