@@ -405,17 +405,129 @@ defmodule EpochtalkServer.Models.Thread do
405405 @ doc """
406406 Returns recent threads accounting for user priority and user's ignored boards
407407 """
408- # TODO(akinsey): complete implementation for main view
409- @ spec recent ( user :: User . t ( ) , user_priority :: non_neg_integer , opts :: list ( ) | nil ) :: [ t ( ) ]
410- def recent ( _user , _user_priority , opts \\ [ ] ) do
411- limit = Keyword . get ( opts , :limit , 5 )
408+ @ spec recent ( user :: User . t ( ) | nil , user_priority :: non_neg_integer ) :: [ t ( ) ]
409+ def recent ( user \\ nil , user_priority ) do
410+ user_id = if user , do: user . id
411+ limit = 5
412+ offset = 0
413+
414+ ignore_boards =
415+ if user ,
416+ do: """
417+ AND NOT (b.id::text = ANY(SELECT jsonb_array_elements_text(up.ignored_boards->'boards') FROM users.preferences up WHERE up.user_id = #{ user_id } ))
418+ """ ,
419+ else: ""
412420
413- query =
414- from Thread ,
415- order_by: [ desc: :updated_at ] ,
416- limit: ^ limit
421+ thread_view_time =
422+ if user ,
423+ do:
424+ "( SELECT time FROM users.thread_views WHERE thread_id = tlist.id AND user_id = #{ user_id } ) AS time," ,
425+ else: ""
417426
418- Repo . all ( query )
427+ latest_user_time =
428+ if user ,
429+ do: "AND created_at >= t.time" ,
430+ else: "AND FALSE"
431+
432+ query = """
433+ SELECT
434+ tlist.id,
435+ tlist.slug,
436+ t.locked,
437+ t.sticky,
438+ t.moderated,
439+ t.poll,
440+ t.updated_at,
441+ t.views AS view_count,
442+ t.board_name,
443+ t.board_slug,
444+ t.board_id,
445+ pf.title,
446+ tv.id AS new_post_id,
447+ tv.position AS new_post_position,
448+ pl.last_post_id,
449+ pl.position AS last_post_position,
450+ pl.created_at AS last_post_created_at,
451+ pl.deleted AS last_post_deleted,
452+ pl.id AS last_post_user_id,
453+ pl.username AS last_post_username,
454+ pl.user_deleted AS last_post_user_deleted
455+ FROM (
456+ SELECT t.id, t.slug
457+ FROM threads t
458+ WHERE EXISTS (
459+ SELECT 1
460+ FROM boards b
461+ WHERE b.id = t.board_id
462+ #{ ignore_boards }
463+ AND ( b.viewable_by IS NULL OR b.viewable_by >= #{ user_priority } )
464+ AND ( SELECT EXISTS ( SELECT 1 FROM board_mapping WHERE board_id = t.board_id ))
465+ )
466+ AND t.updated_at IS NOT NULL
467+ ORDER BY t.updated_at DESC
468+ LIMIT #{ limit } OFFSET #{ offset }
469+ ) tlist
470+ LEFT JOIN LATERAL (
471+ SELECT
472+ t1.locked,
473+ t1.sticky,
474+ t1.moderated,
475+ t1.updated_at,
476+ mt.views,
477+ ( SELECT EXISTS ( SELECT 1 FROM polls WHERE thread_id = tlist.id )) AS poll,
478+ #{ thread_view_time }
479+ ( SELECT b.name FROM boards b WHERE b.id = t1.board_id ) AS board_name,
480+ ( SELECT b.slug FROM boards b WHERE b.id = t1.board_id ) AS board_slug,
481+ ( SELECT b.id FROM boards b WHERE b.id = t1.board_id ) AS board_id
482+ FROM threads t1
483+ LEFT JOIN metadata.threads mt ON tlist.id = mt.thread_id
484+ WHERE t1.id = tlist.id
485+ ) t ON true
486+ LEFT JOIN LATERAL (
487+ SELECT content ->> 'title' as title
488+ FROM posts
489+ WHERE thread_id = tlist.id
490+ ORDER BY created_at
491+ LIMIT 1
492+ ) pf ON true
493+ LEFT JOIN LATERAL (
494+ SELECT id, position
495+ FROM posts
496+ WHERE thread_id = tlist.id
497+ #{ latest_user_time }
498+ ORDER BY created_at
499+ LIMIT 1
500+ ) tv ON true
501+ LEFT JOIN LATERAL (
502+ SELECT
503+ p.id AS last_post_id,
504+ p.position,
505+ p.created_at,
506+ p.deleted,
507+ u.id,
508+ u.username,
509+ u.deleted as user_deleted
510+ FROM posts p
511+ LEFT JOIN users u ON p.user_id = u.id
512+ WHERE p.thread_id = tlist.id
513+ ORDER BY p.created_at DESC
514+ LIMIT 1
515+ ) pl ON true
516+ """
517+
518+ raw_data = Ecto.Adapters.SQL . query! ( Repo , query )
519+
520+ # convert raw sql query results into list of recent thread maps
521+ Enum . reduce ( raw_data . rows , [ ] , fn row , recent_threads ->
522+ recent_thread =
523+ raw_data . columns
524+ |> Enum . with_index ( )
525+ |> Enum . reduce ( % { } , fn { key , row_index } , recent_thread_map ->
526+ Map . put ( recent_thread_map , String . to_atom ( key ) , Enum . at ( row , row_index ) )
527+ end )
528+
529+ recent_threads ++ [ recent_thread ]
530+ end )
419531 end
420532
421533 @ doc """
0 commit comments