@@ -21,8 +21,12 @@ interface Story {
21
21
isNew : boolean ;
22
22
date : number ;
23
23
fromFeed : string ;
24
+ lastRead ?: number ;
24
25
}
25
26
27
+ type StoryLastRead = {
28
+ [ key : string ] : number ;
29
+ } ;
26
30
type FeedLastViewed = {
27
31
[ key : string ] : number ;
28
32
} ;
@@ -49,6 +53,9 @@ function StoryListItem(props: { item: Story; refresh: () => void }) {
49
53
</ ActionPanel >
50
54
}
51
55
accessories = { [
56
+ props . item . lastRead
57
+ ? { icon : Icon . Eye , tooltip : `Last Read: ${ new Date ( props . item . lastRead ) . toDateString ( ) } ` }
58
+ : { icon : Icon . EyeDisabled , tooltip : "Last Read: never" } ,
52
59
{
53
60
text : timeAgo . format ( props . item . date ) as string ,
54
61
icon : props . item . isNew ? { source : Icon . Dot , tintColor : Color . Green } : undefined ,
@@ -58,14 +65,27 @@ function StoryListItem(props: { item: Story; refresh: () => void }) {
58
65
) ;
59
66
}
60
67
68
+ async function updateLastRead ( props : { item : Story } ) {
69
+ const lastRead = new Date ( ) . valueOf ( ) ;
70
+ const storyLastViewedString = await LocalStorage . getItem < string > ( "storyLastRead" ) ;
71
+ const storyLastRead : StoryLastRead = await JSON . parse ( storyLastViewedString ?? "{}" ) ;
72
+ storyLastRead [ props . item . guid ] = lastRead ;
73
+ await LocalStorage . setItem ( "storyLastRead" , JSON . stringify ( storyLastRead ) ) ;
74
+ }
75
+
61
76
function ReadStory ( props : { item : Story } ) {
62
77
return props . item . content ? (
63
- < Action . Push icon = { Icon . Book } title = "Read Story" target = { < StoryDetail item = { props . item } /> } />
78
+ < Action . Push
79
+ icon = { Icon . Book }
80
+ title = "Read Story"
81
+ target = { < StoryDetail item = { props . item } /> }
82
+ onPush = { ( ) => updateLastRead ( props ) }
83
+ />
64
84
) : null ;
65
85
}
66
86
67
87
function OpenStory ( props : { item : Story } ) {
68
- return props . item . link ? < Action . OpenInBrowser url = { props . item . link } /> : null ;
88
+ return props . item . link ? < Action . OpenInBrowser url = { props . item . link } onOpen = { ( ) => updateLastRead ( props ) } /> : null ;
69
89
}
70
90
71
91
function CopyStory ( props : { item : Story } ) {
@@ -90,20 +110,22 @@ function ItemToStory(item: Parser.Item, feed: Feed, lastViewed: number) {
90
110
}
91
111
92
112
async function getStories ( feeds : Feed [ ] ) {
93
- const feedLastViewedString = ( await LocalStorage . getItem ( "feedLastViewed" ) ) as string ;
94
- const feedLastViewed = feedLastViewedString
95
- ? ( JSON . parse ( feedLastViewedString ) as FeedLastViewed )
96
- : ( { } as FeedLastViewed ) ;
113
+ const feedLastViewedString = await LocalStorage . getItem < string > ( "feedLastViewed" ) ;
114
+ const feedLastViewed : FeedLastViewed = JSON . parse ( feedLastViewedString ?? "{}" ) ;
97
115
98
116
const storyItems : Story [ ] = [ ] ;
117
+ const storyLastViewedString = await LocalStorage . getItem < string > ( "storyLastRead" ) ;
118
+ const storyLastRead : StoryLastRead = JSON . parse ( storyLastViewedString ?? "{}" ) ;
99
119
100
120
for ( const feedItem of feeds ) {
101
121
const lastViewed = feedLastViewed [ feedItem . url ] || 0 ;
102
122
try {
103
123
const feed = await parser . parseURL ( feedItem . url ) ;
104
124
const stories : Story [ ] = [ ] ;
105
125
feed . items . forEach ( ( item ) => {
106
- stories . push ( ItemToStory ( item , feedItem , lastViewed ) ) ;
126
+ const story = ItemToStory ( item , feedItem , lastViewed ) ;
127
+ const lastRead = storyLastRead [ story . guid ] || 0 ;
128
+ stories . push ( { ...story , lastRead } ) ;
107
129
} ) ;
108
130
feedLastViewed [ feedItem . url ] = stories . at ( 0 ) ?. date || lastViewed ;
109
131
storyItems . push ( ...stories ) ;
@@ -135,18 +157,22 @@ export function StoriesList(props: { feeds?: Feed[] }) {
135
157
< List
136
158
isLoading = { isLoading }
137
159
searchBarAccessory = {
138
- data ?. feeds . length && data . feeds . length > 1 ? (
139
- < List . Dropdown onChange = { setFilter } tooltip = "Subscription" >
140
- < List . Dropdown . Section >
141
- < List . Dropdown . Item icon = { Icon . Globe } title = "All Subscriptions" value = "all" / >
142
- </ List . Dropdown . Section >
160
+ < List . Dropdown onChange = { setFilter } tooltip = "Subscription" >
161
+ < List . Dropdown . Section >
162
+ < List . Dropdown . Item icon = { Icon . Globe } title = "All Subscriptions" value = "all" / >
163
+ </ List . Dropdown . Section >
164
+ { data ?. feeds && data . feeds . length > 1 && (
143
165
< List . Dropdown . Section >
144
- { data ? .feeds . map ( ( feed ) => (
166
+ { data . feeds . map ( ( feed ) => (
145
167
< List . Dropdown . Item key = { feed . url } icon = { feed . icon } title = { feed . title } value = { feed . url } />
146
168
) ) }
147
169
</ List . Dropdown . Section >
148
- </ List . Dropdown >
149
- ) : null
170
+ ) }
171
+ < List . Dropdown . Section >
172
+ < List . Dropdown . Item icon = { Icon . Eye } title = "Read" value = "read" />
173
+ < List . Dropdown . Item icon = { Icon . EyeDisabled } title = "Unread" value = "unread" />
174
+ </ List . Dropdown . Section >
175
+ </ List . Dropdown >
150
176
}
151
177
actions = {
152
178
! props ?. feeds && (
@@ -162,7 +188,11 @@ export function StoriesList(props: { feeds?: Feed[] }) {
162
188
}
163
189
>
164
190
{ data ?. stories
165
- . filter ( ( story ) => filter === "all" || story . fromFeed === filter )
191
+ . filter ( ( story ) => {
192
+ if ( filter === "read" ) return story . lastRead ;
193
+ if ( filter === "unread" ) return ! story . lastRead ;
194
+ return filter === "all" || story . fromFeed === filter ;
195
+ } )
166
196
. map ( ( story ) => < StoryListItem key = { story . guid } item = { story } refresh = { revalidate } /> ) }
167
197
</ List >
168
198
) ;
0 commit comments