@@ -22,6 +22,7 @@ defmodule ExRssWeb.FeedLive.Index do
22
22
join: e in Entry ,
23
23
on: f . id == e . feed_id ,
24
24
group_by: f . id ,
25
+ order_by: [ desc_nulls_last: f . position ] ,
25
26
select: % {
26
27
f
27
28
| unread_entries_count: filter ( count ( e . id ) , e . read == false ) ,
@@ -101,6 +102,94 @@ defmodule ExRssWeb.FeedLive.Index do
101
102
end
102
103
end
103
104
105
+ def handle_event ( "pin_feed" , % { "feed-id" => feed_id } , socket ) do
106
+ update_feed_position ( feed_id , 0 , socket )
107
+ end
108
+
109
+ def handle_event ( "unpin_feed" , % { "feed-id" => feed_id } , socket ) do
110
+ update_feed_position ( feed_id , nil , socket )
111
+ end
112
+
113
+ def update_feed_position ( feed_id , position , socket ) do
114
+ changeset =
115
+ Repo . get! ( User , socket . assigns . current_user . id )
116
+ |> Ecto . assoc ( :feeds )
117
+ |> Repo . get! ( feed_id )
118
+ |> Feed . changeset ( % { "position" => position } )
119
+
120
+ case Repo . update ( changeset ) do
121
+ { :ok , feed } ->
122
+ current_user = Repo . get! ( User , socket . assigns . current_user . id )
123
+
124
+ feeds_of_current_user = current_user |> Ecto . assoc ( :feeds )
125
+
126
+ feeds_with_counts =
127
+ from (
128
+ f in feeds_of_current_user ,
129
+ join: e in Entry ,
130
+ on: f . id == e . feed_id ,
131
+ group_by: f . id ,
132
+ order_by: [ desc_nulls_last: f . position ] ,
133
+ select: % {
134
+ f
135
+ | unread_entries_count: filter ( count ( e . id ) , e . read == false ) ,
136
+ read_entries_count: filter ( count ( e . id ) , e . read == true ) ,
137
+ has_error: f . retries > 0
138
+ }
139
+ )
140
+
141
+ feeds =
142
+ feeds_with_counts
143
+ |> Repo . all ( )
144
+ |> Repo . preload (
145
+ entries: from ( e in Entry , where: e . read == false , order_by: [ desc: e . posted_at ] )
146
+ )
147
+
148
+ feed_with_counts_query =
149
+ from (
150
+ f in Feed ,
151
+ join: e in Entry ,
152
+ on: f . id == e . feed_id ,
153
+ group_by: f . id ,
154
+ select: % {
155
+ f
156
+ | unread_entries_count: filter ( count ( e . id ) , e . read == false ) ,
157
+ read_entries_count: filter ( count ( e . id ) , e . read == true ) ,
158
+ has_error: f . retries > 0
159
+ }
160
+ )
161
+
162
+ updated_feed =
163
+ Repo . get! ( feed_with_counts_query , feed . id )
164
+ |> Repo . preload (
165
+ entries: from ( e in Entry , where: e . read == false , order_by: [ desc: e . posted_at ] )
166
+ )
167
+
168
+ update_broadcaster =
169
+ Application . get_env ( :ex_rss , :update_broadcaster , ExRss.Crawler.UpdateBroadcaster )
170
+
171
+ Task.Supervisor . start_child (
172
+ ExRss.TaskSupervisor ,
173
+ update_broadcaster ,
174
+ :broadcast_update ,
175
+ [ updated_feed ]
176
+ )
177
+
178
+ oldest_unread_entry =
179
+ User . oldest_unread_entry ( socket . assigns . current_user . id )
180
+
181
+ socket =
182
+ socket
183
+ |> assign ( :oldest_unread_entry , oldest_unread_entry )
184
+ |> stream ( :feeds , feeds , reset: true )
185
+
186
+ { :noreply , socket }
187
+
188
+ _ ->
189
+ { :noreply , socket }
190
+ end
191
+ end
192
+
104
193
# 2024-12-03
105
194
# This `use` is needed for `content_tag` to be available in `elm_module`.
106
195
use Phoenix.HTML
0 commit comments