1
1
defmodule ExRssWeb.FeedLive.Index do
2
+ import Ecto.Query
3
+
2
4
use ExRssWeb , :live_view
3
5
4
6
alias ExRss . { Entry , Feed , Repo , User }
@@ -10,11 +12,22 @@ defmodule ExRssWeb.FeedLive.Index do
10
12
) do
11
13
oldest_unread_entry = User . oldest_unread_entry ( current_user . id )
12
14
15
+ current_user = Repo . get! ( User , current_user . id )
16
+
17
+ feeds =
18
+ current_user
19
+ |> Ecto . assoc ( :feeds )
20
+ |> Repo . all ( )
21
+ |> Repo . preload (
22
+ entries: from ( e in Entry , where: e . read == false , order_by: [ desc: e . posted_at ] )
23
+ )
24
+
13
25
socket =
14
26
socket
15
27
|> assign ( :current_user , current_user )
16
28
|> assign ( :api_token , api_token )
17
29
|> assign ( :oldest_unread_entry , oldest_unread_entry )
30
+ |> stream ( :feeds , feeds )
18
31
19
32
{ :ok , socket }
20
33
end
@@ -28,7 +41,11 @@ defmodule ExRssWeb.FeedLive.Index do
28
41
29
42
case Repo . update ( changeset ) do
30
43
{ :ok , entry } ->
31
- updated_feed = Repo . get! ( Feed , entry . feed_id )
44
+ updated_feed =
45
+ Repo . get! ( Feed , entry . feed_id )
46
+ |> Repo . preload (
47
+ entries: from ( e in Entry , where: e . read == false , order_by: [ desc: e . posted_at ] )
48
+ )
32
49
33
50
update_broadcaster =
34
51
Application . get_env ( :ex_rss , :update_broadcaster , ExRss.Crawler.UpdateBroadcaster )
@@ -43,7 +60,12 @@ defmodule ExRssWeb.FeedLive.Index do
43
60
oldest_unread_entry =
44
61
User . oldest_unread_entry ( socket . assigns . current_user . id )
45
62
46
- { :noreply , assign ( socket , :oldest_unread_entry , oldest_unread_entry ) }
63
+ socket =
64
+ socket
65
+ |> assign ( :oldest_unread_entry , oldest_unread_entry )
66
+ |> stream_insert ( :feeds , updated_feed )
67
+
68
+ { :noreply , socket }
47
69
48
70
_ ->
49
71
{ :noreply , socket }
@@ -65,4 +87,66 @@ defmodule ExRssWeb.FeedLive.Index do
65
87
66
88
content_tag ( tag , "" , Keyword . merge ( attrs , data_attributes ) )
67
89
end
90
+
91
+ attr :entry , Entry , required: true
92
+
93
+ def entry ( assigns ) do
94
+ ~H"""
95
+ < ul class = "flex flex-col " >
96
+ < li class = "flex flex-col md:flex-row " >
97
+ < div class = "flex flex-col " >
98
+ < a href = { @ entry . url } target = "_blank " > <%= @ entry . title %> </ a >
99
+ < span > <%= @ entry . posted_at %> </ span >
100
+ </ div >
101
+
102
+ < div class = "md:shrink-0 flex self-start mt-1 ml-auto space-x-4 " >
103
+ < a
104
+ href = { @ entry . url }
105
+ target = "_blank "
106
+ aria-label = { "View entry #{ @ entry . title } " }
107
+ phx-click = "mark_as_read "
108
+ phx-value-entry-id = { @ entry . id }
109
+ >
110
+ < . icon name = "hero-arrow-top-right-on-square-solid " />
111
+ </ a >
112
+ < button aria-label = "Mark as read " phx-click = "mark_as_read " phx-value-entry-id = { @ entry . id } >
113
+ < . icon name = "hero-check-circle-solid " />
114
+ </ button >
115
+ </ div >
116
+ </ li >
117
+ </ ul >
118
+ """
119
+ end
120
+
121
+ attr :entries , :list , required: true
122
+
123
+ def entries ( assigns ) do
124
+ if length ( assigns . entries ) > 5 do
125
+ assigns =
126
+ assigns
127
+ |> assign ( :head_entries , Enum . take ( assigns . entries , 2 ) )
128
+ |> assign ( :number_of_entries_not_shown , length ( assigns . entries ) - 4 )
129
+ |> assign ( :tail_entries , Enum . take ( assigns . entries , - 2 ) )
130
+
131
+ ~H"""
132
+ < ul class = "mb-6 flex flex-col space-y-4 " >
133
+ < li :for = { entry <- @ head_entries } >
134
+ < . entry entry = { entry } />
135
+ </ li >
136
+ < div > <%= @ number_of_entries_not_shown %> entries not shown</ div >
137
+ < li :for = { entry <- @ tail_entries } >
138
+ < . entry entry = { entry } />
139
+ </ li >
140
+ </ ul >
141
+ """
142
+ else
143
+ ~H"""
144
+ < ul class = "mb-6 flex flex-col space-y-4 " >
145
+ < li :for = { entry <- @ entries } >
146
+ < . entry entry = { entry } />
147
+ </ li >
148
+ </ ul >
149
+ """
150
+ end
151
+ end
68
152
end
0 commit comments