mirror of
https://github.com/yang991178/fluent-reader.git
synced 2025-02-21 22:17:44 +01:00
mark below or above as read
This commit is contained in:
parent
debf45e4d6
commit
ce026aec9c
2
dist/styles.css
vendored
2
dist/styles.css
vendored
@ -52,7 +52,7 @@ html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ms-ContextualMenu-link, .ms-Button {
|
||||
.ms-ContextualMenu-link, .ms-Button, .ms-ContextualMenu-item button {
|
||||
cursor: default;
|
||||
font-size: 13px;
|
||||
user-select: none;
|
||||
|
@ -27,7 +27,7 @@ export type ContextMenuProps = ContextReduxProps & {
|
||||
switchView: (viewType: ViewType) => void
|
||||
switchFilter: (filter: FilterType) => void
|
||||
toggleFilter: (filter: FilterType) => void
|
||||
markAllRead: (sids: number[]) => void
|
||||
markAllRead: (sids: number[], date?: Date, before?: boolean) => void
|
||||
settings: () => void
|
||||
close: () => void
|
||||
}
|
||||
@ -67,18 +67,33 @@ export class ContextMenu extends React.Component<ContextMenuProps> {
|
||||
window.utils.openExternal(this.props.item.link)
|
||||
}
|
||||
},
|
||||
this.props.item.hasRead
|
||||
? {
|
||||
key: "markAsUnread",
|
||||
text: intl.get("article.markUnread"),
|
||||
iconProps: { iconName: "RadioBtnOn", style: { fontSize: 14, textAlign: "center" } },
|
||||
onClick: () => { this.props.markUnread(this.props.item) }
|
||||
}
|
||||
: {
|
||||
{
|
||||
key: "markAsRead",
|
||||
text: intl.get("article.markRead"),
|
||||
iconProps: { iconName: "StatusCircleRing" },
|
||||
onClick: () => { this.props.markRead(this.props.item) }
|
||||
text: this.props.item.hasRead ? intl.get("article.markUnread") : intl.get("article.markRead"),
|
||||
iconProps: this.props.item.hasRead
|
||||
? { iconName: "RadioBtnOn", style: { fontSize: 14, textAlign: "center" } }
|
||||
: { iconName: "StatusCircleRing" },
|
||||
onClick: () => {
|
||||
if (this.props.item.hasRead) this.props.markUnread(this.props.item)
|
||||
else this.props.markRead(this.props.item)
|
||||
},
|
||||
split: true,
|
||||
subMenuProps: {
|
||||
items: [
|
||||
{
|
||||
key: "markBelow",
|
||||
text: intl.get("article.markBelow"),
|
||||
iconProps: { iconName: "Down", style: { fontSize: 14 } },
|
||||
onClick: () => this.props.markAllRead(null, this.props.item.date)
|
||||
},
|
||||
{
|
||||
key: "markAbove",
|
||||
text: intl.get("article.markAbove"),
|
||||
iconProps: { iconName: "Up", style: { fontSize: 14 } },
|
||||
onClick: () => this.props.markAllRead(null, this.props.item.date, false)
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "toggleStarred",
|
||||
|
@ -62,7 +62,9 @@ const mapDispatchToProps = dispatch => {
|
||||
},
|
||||
switchFilter: (filter: FilterType) => dispatch(switchFilter(filter)),
|
||||
toggleFilter: (filter: FilterType) => dispatch(toggleFilter(filter)),
|
||||
markAllRead: (sids: number[]) => dispatch(markAllRead(sids)),
|
||||
markAllRead: (sids: number[], date?: Date, before?: boolean) => {
|
||||
dispatch(markAllRead(sids, date, before))
|
||||
},
|
||||
settings: () => dispatch(toggleSettings()),
|
||||
close: () => dispatch(closeContextMenu())
|
||||
}
|
||||
|
@ -55,6 +55,8 @@
|
||||
"unhide": "Unhide article",
|
||||
"markRead": "Mark as read",
|
||||
"markUnread": "Mark as unread",
|
||||
"markAbove": "Mark above as read",
|
||||
"markBelow": "Mark below as read",
|
||||
"star": "Star",
|
||||
"unstar": "Remove star",
|
||||
"fontSize": "Font size",
|
||||
|
@ -55,6 +55,8 @@
|
||||
"unhide": "取消隐藏",
|
||||
"markRead": "标为已读",
|
||||
"markUnread": "标为未读",
|
||||
"markAbove": "将以上标为已读",
|
||||
"markBelow": "将以下标为已读",
|
||||
"star": "标为星标",
|
||||
"unstar": "取消星标",
|
||||
"fontSize": "字体大小",
|
||||
|
@ -91,6 +91,9 @@ interface MarkReadAction {
|
||||
interface MarkAllReadAction {
|
||||
type: typeof MARK_ALL_READ,
|
||||
sids: number[]
|
||||
counts?: number[]
|
||||
time?: number
|
||||
before?: boolean
|
||||
}
|
||||
|
||||
interface MarkUnreadAction {
|
||||
@ -203,11 +206,6 @@ const markReadDone = (item: RSSItem): ItemActionTypes => ({
|
||||
item: item
|
||||
})
|
||||
|
||||
const markAllReadDone = (sids: number[]): ItemActionTypes => ({
|
||||
type: MARK_ALL_READ,
|
||||
sids: sids
|
||||
})
|
||||
|
||||
const markUnreadDone = (item: RSSItem): ItemActionTypes => ({
|
||||
type: MARK_UNREAD,
|
||||
item: item
|
||||
@ -222,23 +220,52 @@ export function markRead(item: RSSItem): AppThunk {
|
||||
}
|
||||
}
|
||||
|
||||
export function markAllRead(sids: number[] = null): AppThunk {
|
||||
export function markAllRead(sids: number[] = null, date: Date = null, before = true): AppThunk {
|
||||
return (dispatch, getState) => {
|
||||
let state = getState()
|
||||
if (sids === null) {
|
||||
let feed = state.feeds[state.page.feedId]
|
||||
sids = feed.sids
|
||||
}
|
||||
let query = { source: { $in: sids } }
|
||||
db.idb.update(query, { $set: { hasRead: true } }, { multi: true }, (err) => {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
dispatch(markAllReadDone(sids))
|
||||
if (!(state.page.filter.type & FilterType.ShowRead)) {
|
||||
dispatch(initFeeds(true))
|
||||
let query = {
|
||||
source: { $in: sids },
|
||||
hasRead: false,
|
||||
} as any
|
||||
if (date) {
|
||||
query.date = before ? { $lte: date } : { $gte: date }
|
||||
}
|
||||
const callback = (items: RSSItem[] = null) => {
|
||||
if (items) {
|
||||
const counts = new Map<number, number>()
|
||||
for (let sid of sids) {
|
||||
counts.set(sid, 0)
|
||||
}
|
||||
for (let item of items) {
|
||||
counts.set(item.source, counts.get(item.source) + 1)
|
||||
}
|
||||
dispatch({
|
||||
type: MARK_ALL_READ,
|
||||
sids: sids,
|
||||
counts: sids.map(i => counts.get(i)),
|
||||
time: date.getTime(),
|
||||
before: before
|
||||
})
|
||||
} else {
|
||||
dispatch({
|
||||
type: MARK_ALL_READ,
|
||||
sids: sids
|
||||
})
|
||||
}
|
||||
if (!(state.page.filter.type & FilterType.ShowRead)) {
|
||||
dispatch(initFeeds(true))
|
||||
}
|
||||
}
|
||||
db.idb.update(query, { $set: { hasRead: true } }, { multi: true, returnUpdatedDocs: Boolean(date) },
|
||||
(err, _, affectedDocuments) => {
|
||||
if (err) console.log(err)
|
||||
if (date) callback(affectedDocuments as unknown as RSSItem[])
|
||||
})
|
||||
if (!date) callback()
|
||||
}
|
||||
}
|
||||
|
||||
@ -352,16 +379,19 @@ export function itemReducer(
|
||||
}
|
||||
}
|
||||
case MARK_ALL_READ: {
|
||||
let nextState = {} as ItemState
|
||||
let nextState = { ...state }
|
||||
let sids = new Set(action.sids)
|
||||
for (let [id, item] of Object.entries(state)) {
|
||||
if (sids.has(item.source) && !item.hasRead) {
|
||||
nextState[id] = {
|
||||
...item,
|
||||
hasRead: true
|
||||
if (!action.time || (action.before
|
||||
? item.date.getTime() <= action.time
|
||||
: item.date.getTime() >= action.time)
|
||||
) {
|
||||
nextState[id] = {
|
||||
...item,
|
||||
hasRead: true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nextState[id] = item
|
||||
}
|
||||
}
|
||||
return nextState
|
||||
|
@ -397,19 +397,15 @@ export function sourceReducer(
|
||||
} as RSSSource
|
||||
}
|
||||
case MARK_ALL_READ: {
|
||||
let nextState = {} as SourceState
|
||||
let sids = new Set(action.sids)
|
||||
for (let [s, source] of Object.entries(state)) {
|
||||
let sid = parseInt(s)
|
||||
if (sids.has(sid) && source.unreadCount > 0) {
|
||||
nextState[sid] = {
|
||||
...source,
|
||||
unreadCount: 0
|
||||
} as RSSSource
|
||||
} else {
|
||||
nextState[sid] = source
|
||||
let nextState = { ...state }
|
||||
action.sids.map((sid, i) => {
|
||||
nextState[sid] = {
|
||||
...state[sid],
|
||||
unreadCount: action.counts
|
||||
? state[sid].unreadCount - action.counts[i]
|
||||
: 0
|
||||
}
|
||||
}
|
||||
})
|
||||
return nextState
|
||||
}
|
||||
default: return state
|
||||
|
Loading…
x
Reference in New Issue
Block a user