commit
06abd8bc21
|
@ -29,7 +29,7 @@ If you are using macOS or an older version of Windows, you can also [get Fluent
|
|||
|
||||
### Contribute
|
||||
|
||||
Make Fluent Reader better by reporting bugs or opening feature requests through [GitHub issues](https://github.com/yang991178/fluent-reader/issues).
|
||||
Help make Fluent Reader better by reporting bugs or opening feature requests through [GitHub issues](https://github.com/yang991178/fluent-reader/issues).
|
||||
|
||||
You can also help internationalize the app by providing [translations into additional languages](https://github.com/yang991178/fluent-reader/tree/master/src/scripts/i18n).
|
||||
Refer to the repo of [react-intl-universal](https://github.com/alibaba/react-intl-universal) to get started on internationalization.
|
||||
|
|
|
@ -45,9 +45,6 @@ html, body {
|
|||
overflow: hidden;
|
||||
margin: 0;
|
||||
}
|
||||
body {
|
||||
background-color: var(--neutralLighterAlt);
|
||||
}
|
||||
#root {
|
||||
height: 100%;
|
||||
}
|
||||
|
@ -157,6 +154,9 @@ nav .progress {
|
|||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
body.darwin .btn-group .seperator {
|
||||
line-height: 32px;
|
||||
}
|
||||
.btn-group .seperator::before {
|
||||
content: "|";
|
||||
}
|
||||
|
@ -184,12 +184,15 @@ nav.menu-on .btn-group .btn.system, nav.hide-btns .btn-group .btn.system {
|
|||
nav.menu-on .btn-group .btn.system, nav.item-on .btn-group .btn.system {
|
||||
color: var(--white);
|
||||
}
|
||||
.btn-group .btn:hover {
|
||||
.btn-group .btn:hover, .ms-Nav-compositeLink:hover {
|
||||
background-color: #0001;
|
||||
}
|
||||
.btn-group .btn:active {
|
||||
.btn-group .btn:active, .ms-Nav-compositeLink:active {
|
||||
background-color: #0002;
|
||||
}
|
||||
.ms-Nav-compositeLink:hover .ms-Nav-link {
|
||||
background: none;
|
||||
}
|
||||
.btn-group .btn.disabled, .btn-group .btn.fetching {
|
||||
background-color: unset !important;
|
||||
color: var(--neutralSecondaryAlt);
|
||||
|
@ -263,7 +266,7 @@ nav.menu-on .btn-group .btn.system, nav.item-on .btn-group .btn.system {
|
|||
|
||||
.settings-container {
|
||||
position: fixed;
|
||||
z-index: 5;
|
||||
z-index: 7;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
|
@ -295,7 +298,7 @@ div[role="tabpanel"] {
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #fffa;
|
||||
z-index: 6;
|
||||
z-index: 8;
|
||||
}
|
||||
.settings .loading .ms-Spinner {
|
||||
margin-top: 180px;
|
||||
|
@ -346,16 +349,18 @@ img.favicon {
|
|||
}
|
||||
|
||||
.main {
|
||||
height: calc(100% - 32px);
|
||||
overflow-y: scroll;
|
||||
margin-top: -32px;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-color: var(--neutralLighterAlt);
|
||||
}
|
||||
.main::before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
top: 32px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
width: calc(100% - 16px);
|
||||
height: 32px;
|
||||
margin-bottom: -32px;
|
||||
background: linear-gradient(var(--neutralLighterAlt), #faf9f800);
|
||||
|
@ -390,10 +395,15 @@ img.favicon {
|
|||
}
|
||||
.menu-container {
|
||||
width: 280px;
|
||||
background: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
.menu-container .menu {
|
||||
background-color: var(--neutralLight);
|
||||
}
|
||||
body.darwin .menu-container .menu {
|
||||
background: none;
|
||||
}
|
||||
.menu-container .menu::after {
|
||||
content: "";
|
||||
display: block;
|
||||
|
@ -564,6 +574,9 @@ img.favicon {
|
|||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
padding: 12px;
|
||||
height: calc(100% - 56px);
|
||||
overflow: hidden scroll;
|
||||
margin-top: 32px;
|
||||
}
|
||||
.cards-feed-container > div.load-more-wrapper, .flex-fix {
|
||||
text-align: center;
|
||||
|
@ -654,11 +667,13 @@ img.favicon {
|
|||
cursor: pointer;
|
||||
animation-fill-mode: none;
|
||||
}
|
||||
.card:hover, .card:focus {
|
||||
box-shadow: #0006 0px 5px 40px;
|
||||
.card:focus, .list-card:focus {
|
||||
outline: none;
|
||||
}
|
||||
.card:focus::after, .list-card:focus::after {
|
||||
.card:hover, .ms-Fabric--isFocusVisible .card:focus {
|
||||
box-shadow: #0006 0px 5px 40px;
|
||||
}
|
||||
.ms-Fabric--isFocusVisible .card:focus::after, .ms-Fabric--isFocusVisible .list-card:focus::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
|
@ -698,7 +713,9 @@ img.favicon {
|
|||
transition: transform ease-out .12s;
|
||||
}
|
||||
.card.transform:hover img.head, .card.transform:hover p, .card.transform:hover h3,
|
||||
.card.transform:focus img.head, .card.transform:focus p, .card.transform:focus h3 {
|
||||
.ms-Fabric--isFocusVisible .card.transform:focus img.head,
|
||||
.ms-Fabric--isFocusVisible .card.transform:focus p,
|
||||
.ms-Fabric--isFocusVisible .card.transform:focus h3 {
|
||||
transform: translateY(-144px);
|
||||
}
|
||||
.card h3.title {
|
||||
|
@ -752,9 +769,8 @@ img.favicon {
|
|||
cursor: pointer;
|
||||
box-shadow: #0000 0px 5px 15px;
|
||||
}
|
||||
.list-card:hover, .list-card:focus {
|
||||
.list-card:hover, .ms-Fabric--isFocusVisible .list-card:focus {
|
||||
box-shadow: #0004 0px 5px 15px;
|
||||
outline: none;
|
||||
}
|
||||
.list-card:active {
|
||||
box-shadow: #0000 0px 5px 15px, inset #0004 0px 0px 15px;
|
||||
|
@ -793,10 +809,10 @@ img.favicon {
|
|||
.ms-Button--commandBar.active .ms-Button-icon {
|
||||
color: #c7e0f4;
|
||||
}
|
||||
.btn-group .btn:hover {
|
||||
.btn-group .btn:hover, .ms-Nav-compositeLink:hover {
|
||||
background-color: #fff1;
|
||||
}
|
||||
.btn-group .btn:active {
|
||||
.btn-group .btn:active, .ms-Nav-compositeLink:active {
|
||||
background-color: #fff2;
|
||||
}
|
||||
.settings .loading {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "fluent-reader",
|
||||
"version": "0.3.2",
|
||||
"version": "0.3.3",
|
||||
"description": "A simplistic, modern desktop RSS reader",
|
||||
"main": "./dist/electron.js",
|
||||
"scripts": {
|
||||
|
|
|
@ -31,7 +31,6 @@ type ArticleState = {
|
|||
|
||||
class Article extends React.Component<ArticleProps, ArticleState> {
|
||||
webview: Electron.WebviewTag
|
||||
shouldRefocus = false
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
@ -107,18 +106,28 @@ class Article extends React.Component<ArticleProps, ArticleState> {
|
|||
if (input.type === "keyDown") {
|
||||
switch (input.key) {
|
||||
case "Escape":
|
||||
this.shouldRefocus = true
|
||||
this.props.dismiss()
|
||||
break
|
||||
case "ArrowLeft":
|
||||
case "ArrowRight":
|
||||
this.props.offsetItem(input.key === "ArrowLeft" ? -1 : 1)
|
||||
break
|
||||
case "l":
|
||||
case "l": case "L":
|
||||
this.toggleWebpage()
|
||||
break
|
||||
default:
|
||||
this.props.shortcuts(this.props.item, input.key)
|
||||
const keyboardEvent = new KeyboardEvent("keydown", {
|
||||
code: input.code,
|
||||
key: input.key,
|
||||
shiftKey: input.shift,
|
||||
altKey: input.alt,
|
||||
ctrlKey: input.control,
|
||||
metaKey: input.meta,
|
||||
repeat: input.isAutoRepeat,
|
||||
bubbles: true
|
||||
})
|
||||
document.dispatchEvent(keyboardEvent)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -149,10 +158,8 @@ class Article extends React.Component<ArticleProps, ArticleState> {
|
|||
}
|
||||
|
||||
componentWillUnmount = () => {
|
||||
if (this.shouldRefocus) {
|
||||
let refocus = document.querySelector(`#refocus>div[data-iid="${this.props.item._id}"]`) as HTMLElement
|
||||
if (refocus) refocus.focus()
|
||||
}
|
||||
let refocus = document.querySelector(`#refocus>div[data-iid="${this.props.item._id}"]`) as HTMLElement
|
||||
if (refocus) refocus.focus()
|
||||
}
|
||||
|
||||
openInBrowser = () => {
|
||||
|
|
|
@ -17,7 +17,6 @@ class DefaultCard extends Card {
|
|||
className={this.className()}
|
||||
onClick={this.onClick}
|
||||
onMouseUp={this.onMouseUp}
|
||||
onMouseDown={event => event.preventDefault()}
|
||||
onKeyDown={this.onKeyDown}
|
||||
data-iid={this.props.item._id}
|
||||
data-is-focusable>
|
||||
|
|
|
@ -16,7 +16,6 @@ class ListCard extends Card {
|
|||
className={this.className()}
|
||||
onClick={this.onClick}
|
||||
onMouseUp={this.onMouseUp}
|
||||
onMouseDown={event => event.preventDefault()}
|
||||
onKeyDown={this.onKeyDown}
|
||||
data-iid={this.props.item._id}
|
||||
data-is-focusable>
|
||||
|
|
|
@ -91,8 +91,10 @@ export class Menu extends React.Component<MenuProps> {
|
|||
let [type, index] = item.key.split("-")
|
||||
if (type === "s") {
|
||||
sids = [parseInt(index)]
|
||||
} else {
|
||||
} else if (type === "g") {
|
||||
sids = this.props.groups[parseInt(index)].sids
|
||||
} else {
|
||||
return
|
||||
}
|
||||
this.props.groupContextMenu(sids, event)
|
||||
}
|
||||
|
|
|
@ -7,14 +7,15 @@ import { ProgressIndicator } from "@fluentui/react"
|
|||
import { getWindowBreakpoint } from "../scripts/utils"
|
||||
|
||||
type NavProps = {
|
||||
state: AppState,
|
||||
itemShown: boolean,
|
||||
fetch: () => void,
|
||||
menu: () => void,
|
||||
logs: () => void,
|
||||
views: () => void,
|
||||
settings: () => void,
|
||||
state: AppState
|
||||
itemShown: boolean
|
||||
menu: () => void
|
||||
search: () => void
|
||||
markAllRead: () => void
|
||||
fetch: () => void
|
||||
logs: () => void
|
||||
views: () => void
|
||||
settings: () => void
|
||||
}
|
||||
|
||||
type NavState = {
|
||||
|
@ -44,6 +45,9 @@ class Nav extends React.Component<NavProps, NavState> {
|
|||
case "F1":
|
||||
this.props.menu()
|
||||
break
|
||||
case "F2":
|
||||
this.props.search()
|
||||
break
|
||||
case "F5":
|
||||
this.fetch()
|
||||
break
|
||||
|
|
|
@ -7,6 +7,7 @@ import ArticleSearch from "./utils/article-search"
|
|||
|
||||
type PageProps = {
|
||||
menuOn: boolean
|
||||
contextOn: boolean
|
||||
settingsOn: boolean
|
||||
feeds: string[]
|
||||
itemId: string
|
||||
|
@ -35,6 +36,7 @@ class Page extends React.Component<PageProps> {
|
|||
</div>}
|
||||
{this.props.itemId && (
|
||||
<FocusTrapZone
|
||||
disabled={this.props.contextOn}
|
||||
ignoreExternalFocusing={true}
|
||||
isClickableOutsideFocusTrap={true}
|
||||
className="article-container"
|
||||
|
|
|
@ -214,12 +214,13 @@ class GroupsTab extends React.Component<GroupsTabProps, GroupsTabState> {
|
|||
|
||||
handleInputChange = (event) => {
|
||||
const name: string = event.target.name
|
||||
this.setState({[name]: event.target.value.trim()})
|
||||
this.setState({[name]: event.target.value})
|
||||
}
|
||||
|
||||
createGroup = (event: React.FormEvent) => {
|
||||
event.preventDefault()
|
||||
if (this.state.newGroupName.length > 0) this.props.createGroup(this.state.newGroupName)
|
||||
let trimmed = this.state.newGroupName.trim()
|
||||
if (trimmed.length > 0) this.props.createGroup(trimmed)
|
||||
}
|
||||
|
||||
addToGroup = () => {
|
||||
|
@ -239,7 +240,7 @@ class GroupsTab extends React.Component<GroupsTabProps, GroupsTabState> {
|
|||
|
||||
updateGroupName = () => {
|
||||
let group = this.state.selectedGroup
|
||||
group = { ...group, name: this.state.editGroupName }
|
||||
group = { ...group, name: this.state.editGroupName.trim() }
|
||||
this.props.updateGroup(group)
|
||||
}
|
||||
|
||||
|
@ -292,7 +293,7 @@ class GroupsTab extends React.Component<GroupsTabProps, GroupsTabState> {
|
|||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<PrimaryButton
|
||||
disabled={this.state.newGroupName.length == 0}
|
||||
disabled={this.state.newGroupName.trim().length == 0}
|
||||
type="sumbit"
|
||||
text={intl.get("create")} />
|
||||
</Stack.Item>
|
||||
|
@ -325,7 +326,7 @@ class GroupsTab extends React.Component<GroupsTabProps, GroupsTabState> {
|
|||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<DefaultButton
|
||||
disabled={this.state.editGroupName.length == 0}
|
||||
disabled={this.state.editGroupName.trim().length == 0}
|
||||
onClick={this.updateGroupName}
|
||||
text={intl.get("groups.editName")} />
|
||||
</Stack.Item>
|
||||
|
|
|
@ -101,12 +101,13 @@ class SourcesTab extends React.Component<SourcesTabProps, SourcesTabState> {
|
|||
|
||||
handleInputChange = (event) => {
|
||||
const name: string = event.target.name
|
||||
this.setState({[name]: event.target.value.trim()})
|
||||
this.setState({[name]: event.target.value})
|
||||
}
|
||||
|
||||
addSource = (event: React.FormEvent) => {
|
||||
event.preventDefault()
|
||||
if (urlTest(this.state.newUrl)) this.props.addSource(this.state.newUrl)
|
||||
let trimmed = this.state.newUrl.trim()
|
||||
if (urlTest(trimmed)) this.props.addSource(trimmed)
|
||||
}
|
||||
|
||||
onOpenTargetChange = (_, option: IChoiceGroupOption) => {
|
||||
|
@ -142,7 +143,7 @@ class SourcesTab extends React.Component<SourcesTabProps, SourcesTabState> {
|
|||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<PrimaryButton
|
||||
disabled={!urlTest(this.state.newUrl)}
|
||||
disabled={!urlTest(this.state.newUrl.trim())}
|
||||
type="submit"
|
||||
text={intl.get("add")} />
|
||||
</Stack.Item>
|
||||
|
@ -171,8 +172,8 @@ class SourcesTab extends React.Component<SourcesTabProps, SourcesTabState> {
|
|||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<DefaultButton
|
||||
disabled={this.state.newSourceName.length == 0}
|
||||
onClick={() => this.props.updateSourceName(this.state.selectedSource, this.state.newSourceName)}
|
||||
disabled={this.state.newSourceName.trim().length == 0}
|
||||
onClick={() => this.props.updateSourceName(this.state.selectedSource, this.state.newSourceName.trim())}
|
||||
text={intl.get("sources.editName")} />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
|
|
|
@ -41,6 +41,7 @@ class ArticleSearch extends React.Component<SearchProps, SearchState> {
|
|||
|
||||
componentDidUpdate(prevProps: SearchProps) {
|
||||
if (this.props.searchOn && !prevProps.searchOn) {
|
||||
this.setState({ query: this.props.initQuery })
|
||||
this.inputRef.current.focus()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import { createSelector } from "reselect"
|
|||
import { RootState } from "../scripts/reducer"
|
||||
import { fetchItems, markAllRead } from "../scripts/models/item"
|
||||
import { toggleMenu, toggleLogMenu, toggleSettings, openViewMenu } from "../scripts/models/app"
|
||||
import { ViewType } from "../scripts/models/page"
|
||||
import { ViewType, toggleSearch } from "../scripts/models/page"
|
||||
import Nav from "../components/nav"
|
||||
|
||||
const getState = (state: RootState) => state.app
|
||||
|
@ -25,6 +25,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||
logs: () => dispatch(toggleLogMenu()),
|
||||
views: () => dispatch(openViewMenu()),
|
||||
settings: () => dispatch(toggleSettings()),
|
||||
search: () => dispatch(toggleSearch()),
|
||||
markAllRead: () => {
|
||||
remote.dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||
title: intl.get("nav.markAllRead"),
|
||||
|
|
|
@ -4,17 +4,20 @@ import { RootState } from "../scripts/reducer"
|
|||
import Page from "../components/page"
|
||||
import { AppDispatch } from "../scripts/utils"
|
||||
import { dismissItem, showOffsetItem } from "../scripts/models/page"
|
||||
import { ContextMenuType } from "../scripts/models/app"
|
||||
|
||||
const getPage = (state: RootState) => state.page
|
||||
const getSettings = (state: RootState) => state.app.settings.display
|
||||
const getMenu = (state: RootState) => state.app.menu
|
||||
const getContext = (state: RootState) => state.app.contextMenu.type != ContextMenuType.Hidden
|
||||
|
||||
const mapStateToProps = createSelector(
|
||||
[getPage, getSettings, getMenu],
|
||||
(page, settingsOn, menuOn) => ({
|
||||
[getPage, getSettings, getMenu, getContext],
|
||||
(page, settingsOn, menuOn, contextOn) => ({
|
||||
feeds: [page.feedId],
|
||||
settingsOn: settingsOn,
|
||||
menuOn: menuOn,
|
||||
contextOn: contextOn,
|
||||
itemId: page.itemId,
|
||||
viewType: page.viewType
|
||||
})
|
||||
|
|
|
@ -29,7 +29,8 @@ function createWindow() {
|
|||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
title: "Fluent Reader",
|
||||
backgroundColor: nativeTheme.shouldUseDarkColors ? "#282828" : "#faf9f8",
|
||||
backgroundColor: process.platform === "darwin" ? "#00000000" : (nativeTheme.shouldUseDarkColors ? "#282828" : "#faf9f8"),
|
||||
vibrancy: "sidebar",
|
||||
x: mainWindowState.x,
|
||||
y: mainWindowState.y,
|
||||
width: mainWindowState.width,
|
||||
|
@ -55,7 +56,7 @@ function createWindow() {
|
|||
mainWindow.loadFile((app.isPackaged ? "dist/" : "") + "index.html")
|
||||
}
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
if (process.platform === "darwin") {
|
||||
const template = [
|
||||
{
|
||||
label: "Application",
|
||||
|
@ -66,8 +67,12 @@ if (process.platform === 'darwin') {
|
|||
{
|
||||
label: "Edit",
|
||||
submenu: [
|
||||
{ label: "Undo", accelerator: "CmdOrCtrl+Z", selector: "undo:" },
|
||||
{ label: "Redo", accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" },
|
||||
{ label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" },
|
||||
{ label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" },
|
||||
{ label: "Paste", accelerator: "CmdOrCtrl+V", selector: "paste:" },
|
||||
{ label: "Select All", accelerator: "CmdOrCtrl+A", selector: "selectAll:" }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -199,6 +199,7 @@ export function initIntl(): AppThunk<Promise<void>> {
|
|||
|
||||
export function initApp(): AppThunk {
|
||||
return (dispatch) => {
|
||||
document.body.classList.add(process.platform)
|
||||
dispatch(initIntl()).then(() =>
|
||||
dispatch(initSources())
|
||||
).then(() =>
|
||||
|
@ -266,10 +267,7 @@ export function appReducer(
|
|||
}
|
||||
case INIT_FEEDS:
|
||||
switch (action.status) {
|
||||
case ActionStatus.Request: return {
|
||||
...state,
|
||||
feedInit: false
|
||||
}
|
||||
case ActionStatus.Request: return state
|
||||
default: return {
|
||||
...state,
|
||||
feedInit: true
|
||||
|
|
|
@ -266,17 +266,18 @@ export function toggleHidden(item: RSSItem): AppThunk {
|
|||
export function itemShortcuts(item: RSSItem, key: string): AppThunk {
|
||||
return (dispatch) => {
|
||||
switch (key) {
|
||||
case "m":
|
||||
case "m": case "M":
|
||||
if (item.hasRead) dispatch(markUnread(item))
|
||||
else dispatch(markRead(item))
|
||||
break
|
||||
case "b":
|
||||
case "b": case "B":
|
||||
if (!item.hasRead) dispatch(markRead(item))
|
||||
openExternal(item.link)
|
||||
break
|
||||
case "s":
|
||||
case "s": case "S":
|
||||
dispatch(toggleStarred(item))
|
||||
break
|
||||
case "h":
|
||||
case "h": case "H":
|
||||
dispatch(toggleHidden(item))
|
||||
break
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { ALL, SOURCE, loadMore, FeedFilter, FilterType, initFeeds } from "./feed"
|
||||
import { getWindowBreakpoint, AppThunk } from "../utils"
|
||||
import { ALL, SOURCE, loadMore, FeedFilter, FilterType, initFeeds, FeedActionTypes, INIT_FEED } from "./feed"
|
||||
import { getWindowBreakpoint, AppThunk, ActionStatus } from "../utils"
|
||||
import { getDefaultView } from "../settings"
|
||||
import { RSSItem, markRead } from "./item"
|
||||
import { SourceActionTypes, DELETE_SOURCE } from "./source"
|
||||
|
@ -104,7 +104,7 @@ export const toggleSearch = (): AppThunk => {
|
|||
return (dispatch, getState) => {
|
||||
let state = getState()
|
||||
dispatch(({ type: TOGGLE_SEARCH }))
|
||||
if (!getWindowBreakpoint()) {
|
||||
if (!getWindowBreakpoint() && state.app.menu) {
|
||||
dispatch(toggleMenu())
|
||||
}
|
||||
if (state.page.searchOn) {
|
||||
|
@ -214,7 +214,7 @@ export class PageState {
|
|||
|
||||
export function pageReducer(
|
||||
state = new PageState(),
|
||||
action: PageActionTypes | SourceActionTypes
|
||||
action: PageActionTypes | SourceActionTypes | FeedActionTypes
|
||||
): PageState {
|
||||
switch (action.type) {
|
||||
case SELECT_PAGE:
|
||||
|
@ -244,6 +244,14 @@ export function pageReducer(
|
|||
...state,
|
||||
itemId: action.item._id
|
||||
}
|
||||
case INIT_FEED: switch (action.status) {
|
||||
case ActionStatus.Success: return {
|
||||
...state,
|
||||
itemId: (action.feed._id === state.feedId && action.items.filter(i => i._id === state.itemId).length === 0)
|
||||
? null : state.itemId
|
||||
}
|
||||
default: return state
|
||||
}
|
||||
case DELETE_SOURCE:
|
||||
case DISMISS_ITEM: return {
|
||||
...state,
|
||||
|
|
Loading…
Reference in New Issue