diff --git a/dist/styles.css b/dist/styles.css
index 27dfcc1..ccb39e4 100644
--- a/dist/styles.css
+++ b/dist/styles.css
@@ -311,10 +311,10 @@ img.favicon {
right: 0;
width: 120%;
height: 120%;
- box-shadow: inset 5px 0 20px #0004;
+ box-shadow: inset 5px 0 25px #0004;
}
.main.menu-on, .list-main.menu-on {
- padding-left: 280px;
+ margin-left: 280px;
}
nav.hide-btns .btn-group .btn, nav.menu-on .btn-group .btn.hide-wide, .menu .btn-group .btn.hide-wide {
@@ -403,7 +403,7 @@ img.favicon {
flex-wrap: wrap;
height: 100%;
position: relative;
- top: -32px;
+ margin-top: -32px;
overflow: hidden;
background: #fff;
}
@@ -422,7 +422,7 @@ img.favicon {
right: 0;
width: 120%;
height: 120%;
- box-shadow: inset 5px 0 20px #0004;
+ box-shadow: inset 5px 0 25px #0004;
}
.list-feed {
margin-top: 32px;
@@ -476,11 +476,12 @@ img.favicon {
font-size: 12px;
}
-.read-indicator {
+.read-indicator, .starred-indicator {
display: block;
width: 16px;
height: 16px;
float: right;
+ text-align: center;
}
.read-indicator::after {
content: "";
@@ -494,6 +495,13 @@ img.favicon {
font-size: 10px;
box-sizing: border-box;
}
+.starred-indicator::after {
+ content: "★";
+ vertical-align: top;
+ color: #ffaa44;
+ font-size: 11px;
+ line-height: 16px;
+}
.card {
display: inline-block;
@@ -574,6 +582,16 @@ img.favicon {
.card p.snippet.show {
transform: none;
}
+.card.hidden::after, .list-card.hidden::after {
+ content: "";
+ display: block;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ background: #0004;
+}
.list-card {
display: flex;
diff --git a/src/components/cards/default-card.tsx b/src/components/cards/default-card.tsx
index f10f15b..8580352 100644
--- a/src/components/cards/default-card.tsx
+++ b/src/components/cards/default-card.tsx
@@ -1,12 +1,19 @@
import * as React from "react"
import { Card } from "./card"
-import Time from "../utils/time"
import { AnimationClassNames } from "@fluentui/react"
+import CardInfo from "./info"
class DefaultCard extends Card {
+ className = () => {
+ let cn = ["card", AnimationClassNames.slideUpIn10]
+ if (this.props.item.snippet && this.props.item.thumb) cn.push("transform")
+ if (this.props.item.hidden) cn.push("hidden")
+ return cn.join(" ")
+ }
+
render() {
return (
-
{this.props.item.thumb ? (

@@ -15,12 +22,7 @@ class DefaultCard extends Card {
{this.props.item.thumb ? (

) : null}
-
- {this.props.source.iconurl ?
: null}
- {this.props.source.name}
-
- {this.props.item.hasRead ? null : }
-
+
{this.props.item.title}
{this.props.item.snippet}
diff --git a/src/components/cards/info.tsx b/src/components/cards/info.tsx
new file mode 100644
index 0000000..52e4dd3
--- /dev/null
+++ b/src/components/cards/info.tsx
@@ -0,0 +1,21 @@
+import * as React from "react"
+import Time from "../utils/time"
+import { RSSSource } from "../../scripts/models/source"
+import { RSSItem } from "../../scripts/models/item"
+
+type CardInfoProps = {
+ source: RSSSource
+ item: RSSItem
+}
+
+const CardInfo = (props: CardInfoProps) => (
+
+ {props.source.iconurl ?
: null}
+ {props.source.name}
+
+ {props.item.hasRead ? null : }
+ {props.item.starred ? : null}
+
+)
+
+export default CardInfo
\ No newline at end of file
diff --git a/src/components/cards/list-card.tsx b/src/components/cards/list-card.tsx
index 80580f1..25fe82e 100644
--- a/src/components/cards/list-card.tsx
+++ b/src/components/cards/list-card.tsx
@@ -1,23 +1,25 @@
import * as React from "react"
import { Card } from "./card"
-import Time from "../utils/time"
import { AnimationClassNames } from "@fluentui/react"
+import CardInfo from "./info"
class ListCard extends Card {
+ className = () => {
+ let cn = ["list-card", AnimationClassNames.slideUpIn10]
+ if (this.props.item.snippet && this.props.item.thumb) cn.push("transform")
+ if (this.props.item.hidden) cn.push("hidden")
+ return cn.join(" ")
+ }
+
render() {
return (
-
{this.props.item.thumb ? (
) : null}
-
- {this.props.source.iconurl ?
: null}
- {this.props.source.name}
-
- {this.props.item.hasRead ? null : }
-
+
{this.props.item.title}
diff --git a/src/components/context-menu.tsx b/src/components/context-menu.tsx
index ceab24a..c99937e 100644
--- a/src/components/context-menu.tsx
+++ b/src/components/context-menu.tsx
@@ -6,6 +6,7 @@ import { ContextMenuType } from "../scripts/models/app"
import { RSSItem } from "../scripts/models/item"
import { ContextReduxProps } from "../containers/context-menu-container"
import { ViewType } from "../scripts/models/page"
+import { FeedFilter } from "../scripts/models/feed"
export type ContextMenuProps = ContextReduxProps & {
type: ContextMenuType
@@ -14,13 +15,16 @@ export type ContextMenuProps = ContextReduxProps & {
item?: RSSItem
feedId?: string
text?: string
- viewType: ViewType
+ viewType?: ViewType
+ filter?: FeedFilter
showItem: (feedId: string, item: RSSItem) => void
markRead: (item: RSSItem) => void
markUnread: (item: RSSItem) => void
toggleStarred: (item: RSSItem) => void
toggleHidden: (item: RSSItem) => void
switchView: (viewType: ViewType) => void
+ switchFilter: (filter: FeedFilter) => void
+ toggleFilter: (filter: FeedFilter) => void
close: () => void
}
@@ -101,20 +105,71 @@ export class ContextMenu extends React.Component {
]
case ContextMenuType.View: return [
{
- key: "cardView",
- text: "卡片视图",
- iconProps: { iconName: "GridViewMedium" },
- canCheck: true,
- checked: this.props.viewType === ViewType.Cards,
- onClick: () => this.props.switchView(ViewType.Cards)
+ key: "section_1",
+ itemType: ContextualMenuItemType.Section,
+ sectionProps: {
+ title: "视图",
+ bottomDivider: true,
+ items: [
+ {
+ key: "cardView",
+ text: "卡片视图",
+ iconProps: { iconName: "GridViewMedium" },
+ canCheck: true,
+ checked: this.props.viewType === ViewType.Cards,
+ onClick: () => this.props.switchView(ViewType.Cards)
+ },
+ {
+ key: "listView",
+ text: "列表视图",
+ iconProps: { iconName: "BacklogList" },
+ canCheck: true,
+ checked: this.props.viewType === ViewType.List,
+ onClick: () => this.props.switchView(ViewType.List)
+ },
+ ]
+ }
},
{
- key: "listView",
- text: "列表视图",
- iconProps: { iconName: "BacklogList" },
+ key: "section_2",
+ itemType: ContextualMenuItemType.Section,
+ sectionProps: {
+ title: "筛选",
+ bottomDivider: true,
+ items: [
+ {
+ key: "allArticles",
+ text: "全部文章",
+ iconProps: { iconName: "ClearFilter" },
+ canCheck: true,
+ checked: (this.props.filter & ~FeedFilter.ShowHidden) == FeedFilter.Default,
+ onClick: () => this.props.switchFilter(FeedFilter.Default)
+ },
+ {
+ key: "unreadOnly",
+ text: "仅未读文章",
+ iconProps: { iconName: "RadioBtnOn", style: { fontSize: 14, textAlign: "center" } },
+ canCheck: true,
+ checked: (this.props.filter & ~FeedFilter.ShowHidden) == FeedFilter.UnreadOnly,
+ onClick: () => this.props.switchFilter(FeedFilter.UnreadOnly)
+ },
+ {
+ key: "starredOnly",
+ text: "仅星标文章",
+ iconProps: { iconName: "FavoriteStarFill" },
+ canCheck: true,
+ checked: (this.props.filter & ~FeedFilter.ShowHidden) == FeedFilter.StarredOnly,
+ onClick: () => this.props.switchFilter(FeedFilter.StarredOnly)
+ }
+ ]
+ }
+ },
+ {
+ key: "showHidden",
+ text: "显示隐藏文章",
canCheck: true,
- checked: this.props.viewType === ViewType.List,
- onClick: () => this.props.switchView(ViewType.List)
+ checked: Boolean(this.props.filter & FeedFilter.ShowHidden),
+ onClick: () => this.props.toggleFilter(FeedFilter.ShowHidden)
}
]
default: return []
diff --git a/src/containers/context-menu-container.tsx b/src/containers/context-menu-container.tsx
index 37c7fae..23fa16f 100644
--- a/src/containers/context-menu-container.tsx
+++ b/src/containers/context-menu-container.tsx
@@ -4,15 +4,17 @@ import { RootState } from "../scripts/reducer"
import { ContextMenuType, closeContextMenu } from "../scripts/models/app"
import { ContextMenu } from "../components/context-menu"
import { RSSItem, markRead, markUnread, toggleStarred, toggleHidden } from "../scripts/models/item"
-import { showItem, switchView, ViewType } from "../scripts/models/page"
+import { showItem, switchView, ViewType, switchFilter, toggleFilter } from "../scripts/models/page"
import { setDefaultView } from "../scripts/utils"
+import { FeedFilter } from "../scripts/models/feed"
const getContext = (state: RootState) => state.app.contextMenu
const getViewType = (state: RootState) => state.page.viewType
+const getFilter = (state: RootState) => state.page.filter
const mapStateToProps = createSelector(
- [getContext, getViewType],
- (context, viewType) => {
+ [getContext, getViewType, getFilter],
+ (context, viewType, filter) => {
switch (context.type) {
case ContextMenuType.Item: return {
type: context.type,
@@ -28,7 +30,8 @@ const mapStateToProps = createSelector(
case ContextMenuType.View: return {
type: context.type,
event: context.event,
- viewType: viewType
+ viewType: viewType,
+ filter: filter
}
default: return { type: ContextMenuType.Hidden }
}
@@ -46,6 +49,8 @@ const mapDispatchToProps = dispatch => {
setDefaultView(viewType)
dispatch(switchView(viewType))
},
+ switchFilter: (filter: FeedFilter) => dispatch(switchFilter(filter)),
+ toggleFilter: (filter: FeedFilter) => dispatch(toggleFilter(filter)),
close: () => dispatch(closeContextMenu())
}
}
diff --git a/src/scripts/db.ts b/src/scripts/db.ts
index 2ee4385..05b17ca 100644
--- a/src/scripts/db.ts
+++ b/src/scripts/db.ts
@@ -20,6 +20,6 @@ export const idb = new Datastore({
if (err) window.console.log(err)
}
})
-idb.removeIndex("id")
-idb.update({}, {$unset: {id: true}}, {multi: true})
+//idb.removeIndex("id")
+//idb.update({}, {$unset: {id: true}}, {multi: true})
//idb.remove({}, { multi: true })
\ No newline at end of file
diff --git a/src/scripts/models/feed.ts b/src/scripts/models/feed.ts
index fa6b06d..0ba8a61 100644
--- a/src/scripts/models/feed.ts
+++ b/src/scripts/models/feed.ts
@@ -1,8 +1,40 @@
import * as db from "../db"
import { SourceActionTypes, INIT_SOURCES, ADD_SOURCE, DELETE_SOURCE } from "./source"
-import { ItemActionTypes, FETCH_ITEMS, RSSItem } from "./item"
+import { ItemActionTypes, FETCH_ITEMS, RSSItem, MARK_READ, MARK_UNREAD, TOGGLE_STARRED, TOGGLE_HIDDEN, applyItemReduction } from "./item"
import { ActionStatus, AppThunk } from "../utils"
-import { PageActionTypes, SELECT_PAGE, PageType } from "./page"
+import { PageActionTypes, SELECT_PAGE, PageType, APPLY_FILTER } from "./page"
+
+export enum FeedFilter {
+ None,
+ ShowRead = 1 << 0,
+ ShowNotStarred = 1 << 1,
+ ShowHidden = 1 << 2,
+
+ Default = ShowRead | ShowNotStarred,
+ UnreadOnly = ShowNotStarred,
+ StarredOnly = ShowRead
+}
+export namespace FeedFilter {
+ export function toQueryObject(filter: FeedFilter) {
+ let query = {
+ hasRead: false,
+ starred: true,
+ hidden: { $exists: false }
+ }
+ if (filter & FeedFilter.ShowRead) delete query.hasRead
+ if (filter & FeedFilter.ShowNotStarred) delete query.starred
+ if (filter & FeedFilter.ShowHidden) delete query.hidden
+ return query
+ }
+
+ export function testItem(filter: FeedFilter, item: RSSItem) {
+ let flag = true
+ if (!(filter & FeedFilter.ShowRead)) flag = flag && !item.hasRead
+ if (!(filter & FeedFilter.ShowNotStarred)) flag = flag && item.starred
+ if (!(filter & FeedFilter.ShowHidden)) flag = flag && !item.hidden
+ return Boolean(flag)
+ }
+}
export const ALL = "ALL"
export const SOURCE = "SOURCE"
@@ -16,18 +48,24 @@ export class RSSFeed {
allLoaded: boolean
sids: number[]
iids: string[]
+ filter: FeedFilter
- constructor (id: string = null, sids=[]) {
+ constructor (id: string = null, sids=[], filter=FeedFilter.Default) {
this._id = id
this.sids = sids
this.iids = []
this.loaded = false
this.allLoaded = false
+ this.filter = filter
}
static loadFeed(feed: RSSFeed, init = false): Promise {
return new Promise((resolve, reject) => {
- db.idb.find({ source: { $in: feed.sids } })
+ let query = {
+ source: { $in: feed.sids },
+ ...FeedFilter.toQueryObject(feed.filter)
+ }
+ db.idb.find(query)
.sort({ date: -1 })
.skip(init ? 0 : feed.iids.length)
.limit(LOAD_QUANTITY)
@@ -182,14 +220,24 @@ export function feedReducer(
switch (action.status) {
case ActionStatus.Success: return {
...state,
- [ALL]: new RSSFeed(ALL, [...state[ALL].sids, action.source.sid])
+ [ALL]: new RSSFeed(ALL, [...state[ALL].sids, action.source.sid], state[ALL].filter)
}
default: return state
}
case DELETE_SOURCE: {
let nextState = {}
for (let [id, feed] of Object.entries(state)) {
- nextState[id] = new RSSFeed(id, feed.sids.filter(sid => sid != action.source.sid))
+ nextState[id] = new RSSFeed(id, feed.sids.filter(sid => sid != action.source.sid), feed.filter)
+ }
+ return nextState
+ }
+ case APPLY_FILTER: {
+ let nextState = {}
+ for (let [id, feed] of Object.entries(state)) {
+ nextState[id] = {
+ ...feed,
+ filter: action.filter
+ }
}
return nextState
}
@@ -197,13 +245,15 @@ export function feedReducer(
switch (action.status) {
case ActionStatus.Success: {
let nextState = { ...state }
- for (let k of Object.keys(state)) {
- if (state[k].loaded) {
- let iids = action.items.filter(i => state[k].sids.includes(i.source)).map(i => i._id)
+ for (let feed of Object.values(state)) {
+ if (feed.loaded) {
+ let iids = action.items
+ .filter(i => feed.sids.includes(i.source) && FeedFilter.testItem(feed.filter, i))
+ .map(i => i._id)
if (iids.length > 0) {
- nextState[k] = {
- ...nextState[k],
- iids: [...iids, ...nextState[k].iids]
+ nextState[feed._id] = {
+ ...feed,
+ iids: [...iids, ...feed.iids]
}
}
}
@@ -252,17 +302,37 @@ export function feedReducer(
}
default: return state
}
+ case MARK_READ:
+ case MARK_UNREAD:
+ case TOGGLE_STARRED:
+ case TOGGLE_HIDDEN: {
+ let nextItem = applyItemReduction(action.item, action.type)
+ let filteredFeeds = Object.values(state).filter(feed => feed.loaded && !FeedFilter.testItem(feed.filter, nextItem))
+ if (filteredFeeds.length > 0) {
+ let nextState = { ...state }
+ for (let feed of filteredFeeds) {
+ nextState[feed._id] = {
+ ...feed,
+ iids: feed.iids.filter(id => id != nextItem._id)
+ }
+ }
+ return nextState
+ } else {
+ return state
+ }
+ }
case SELECT_PAGE:
switch (action.pageType) {
case PageType.Sources: return {
...state,
- [SOURCE]: new RSSFeed(SOURCE, action.sids)
+ [SOURCE]: new RSSFeed(SOURCE, action.sids, action.filter)
}
case PageType.AllArticles: return action.init ? {
...state,
[ALL]: {
...state[ALL],
- loaded: false
+ loaded: false,
+ filter: action.filter
}
} : state
default: return state
diff --git a/src/scripts/models/item.ts b/src/scripts/models/item.ts
index 6c09de0..0568ac9 100644
--- a/src/scripts/models/item.ts
+++ b/src/scripts/models/item.ts
@@ -225,6 +225,28 @@ export function toggleHidden(item: RSSItem): AppThunk {
}
}
+export function applyItemReduction(item: RSSItem, type: string) {
+ let nextItem = { ...item }
+ switch (type) {
+ case MARK_READ:
+ case MARK_UNREAD: {
+ nextItem.hasRead = type === MARK_READ
+ break
+ }
+ case TOGGLE_STARRED: {
+ if (item.starred === true) delete nextItem.starred
+ else nextItem.starred = true
+ break
+ }
+ case TOGGLE_HIDDEN: {
+ if (item.hidden === true) delete nextItem.hidden
+ else nextItem.hidden = true
+ break
+ }
+ }
+ return nextItem
+}
+
export function itemReducer(
state: ItemState = {},
action: ItemActionTypes | FeedActionTypes
@@ -242,29 +264,12 @@ export function itemReducer(
default: return state
}
case MARK_UNREAD:
- case MARK_READ: return {
- ...state,
- [action.item._id] : {
- ...action.item,
- hasRead: action.type === MARK_READ
- }
- }
- case TOGGLE_STARRED: {
- let newItem = { ...action.item }
- if (newItem.starred === true) delete newItem.starred
- else newItem.starred = true
- return {
- ...state,
- [newItem._id]: newItem
- }
- }
+ case MARK_READ:
+ case TOGGLE_STARRED:
case TOGGLE_HIDDEN: {
- let newItem = { ...action.item }
- if (newItem.hidden === true) delete newItem.hidden
- else newItem.hidden = true
return {
...state,
- [newItem._id]: newItem
+ [action.item._id]: applyItemReduction(action.item, action.type)
}
}
case LOAD_MORE:
diff --git a/src/scripts/models/page.ts b/src/scripts/models/page.ts
index 52055b3..b59b7e6 100644
--- a/src/scripts/models/page.ts
+++ b/src/scripts/models/page.ts
@@ -1,4 +1,4 @@
-import { ALL, SOURCE, loadMore } from "./feed"
+import { ALL, SOURCE, loadMore, FeedFilter, initFeeds } from "./feed"
import { getWindowBreakpoint, AppThunk, getDefaultView } from "../utils"
import { RSSItem, markRead } from "./item"
import { SourceActionTypes, DELETE_SOURCE } from "./source"
@@ -8,6 +8,7 @@ export const SWITCH_VIEW = "SWITCH_VIEW"
export const SHOW_ITEM = "SHOW_ITEM"
export const SHOW_OFFSET_ITEM = "SHOW_OFFSET_ITEM"
export const DISMISS_ITEM = "DISMISS_ITEM"
+export const APPLY_FILTER = "APPLY_FILTER"
export enum PageType {
AllArticles, Sources, Page
@@ -22,6 +23,7 @@ interface SelectPageAction {
pageType: PageType
init: boolean
keepMenu: boolean
+ filter: FeedFilter
sids?: number[]
menuKey?: string
title?: string
@@ -38,28 +40,39 @@ interface ShowItemAction {
item: RSSItem
}
+interface ApplyFilterAction {
+ type: typeof APPLY_FILTER
+ filter: FeedFilter
+}
+
interface DismissItemAction { type: typeof DISMISS_ITEM }
-export type PageActionTypes = SelectPageAction | SwitchViewAction | ShowItemAction | DismissItemAction
+export type PageActionTypes = SelectPageAction | SwitchViewAction | ShowItemAction | DismissItemAction | ApplyFilterAction
-export function selectAllArticles(init = false): PageActionTypes {
- return {
- type: SELECT_PAGE,
- keepMenu: getWindowBreakpoint(),
- pageType: PageType.AllArticles,
- init: init
+export function selectAllArticles(init = false): AppThunk {
+ return (dispatch, getState) => {
+ dispatch({
+ type: SELECT_PAGE,
+ keepMenu: getWindowBreakpoint(),
+ filter: getState().page.filter,
+ pageType: PageType.AllArticles,
+ init: init
+ } as PageActionTypes)
}
}
-export function selectSources(sids: number[], menuKey: string, title: string): PageActionTypes {
- return {
- type: SELECT_PAGE,
- pageType: PageType.Sources,
- keepMenu: getWindowBreakpoint(),
- sids: sids,
- menuKey: menuKey,
- title: title,
- init: true
+export function selectSources(sids: number[], menuKey: string, title: string): AppThunk {
+ return (dispatch, getState) => {
+ dispatch({
+ type: SELECT_PAGE,
+ pageType: PageType.Sources,
+ keepMenu: getWindowBreakpoint(),
+ filter: getState().page.filter,
+ sids: sids,
+ menuKey: menuKey,
+ title: title,
+ init: true
+ } as PageActionTypes)
}
}
@@ -88,7 +101,22 @@ export function showOffsetItem(offset: number): AppThunk {
let iids = feed.iids
let itemIndex = iids.indexOf(itemId)
let newIndex = itemIndex + offset
- if (itemIndex >= 0 && newIndex >= 0) {
+ if (itemIndex < 0) {
+ let item = state.items[itemId]
+ let prevs = feed.iids
+ .map((id, index) => [state.items[id], index] as [RSSItem, number])
+ .filter(([i, _]) => i.date > item.date)
+ if (prevs.length > 0) {
+ let prev = prevs[0]
+ for (let j = 1; j < prevs.length; j += 1) {
+ if (prevs[j][0].date < prev[0].date) prev = prevs[j]
+ }
+ newIndex = prev[1] + offset + (offset < 0 ? 1 : 0)
+ } else {
+ newIndex = offset - 1
+ }
+ }
+ if (newIndex >= 0) {
if (newIndex < iids.length) {
let item = state.items[iids[newIndex]]
dispatch(markRead(item))
@@ -107,8 +135,38 @@ export function showOffsetItem(offset: number): AppThunk {
}
}
+const applyFilterDone = (filter: FeedFilter): PageActionTypes => ({
+ type: APPLY_FILTER,
+ filter: filter
+})
+
+function applyFilter(filter: FeedFilter): AppThunk {
+ return (dispatch) => {
+ dispatch(applyFilterDone(filter))
+ dispatch(initFeeds(true))
+ }
+}
+
+export function switchFilter(filter: FeedFilter): AppThunk {
+ return (dispatch, getState) => {
+ let oldFilter = getState().page.filter
+ let newFilter = filter | (oldFilter & FeedFilter.ShowHidden)
+ if (newFilter != oldFilter) {
+ dispatch(applyFilter(newFilter))
+ }
+ }
+}
+
+export function toggleFilter(filter: FeedFilter): AppThunk {
+ return (dispatch, getState) => {
+ let oldFilter = getState().page.filter
+ dispatch(applyFilter(oldFilter ^ filter))
+ }
+}
+
export class PageState {
viewType = getDefaultView()
+ filter = FeedFilter.Default
feedId = ALL
itemId = null as string
}
@@ -135,6 +193,10 @@ export function pageReducer(
viewType: action.viewType,
itemId: action.viewType === ViewType.List ? state.itemId : null
}
+ case APPLY_FILTER: return {
+ ...state,
+ filter: action.filter
+ }
case SHOW_ITEM: return {
...state,
itemId: action.item._id
diff --git a/src/scripts/utils.ts b/src/scripts/utils.ts
index d43d1e1..152d71e 100644
--- a/src/scripts/utils.ts
+++ b/src/scripts/utils.ts
@@ -2,7 +2,6 @@ import { shell, remote } from "electron"
import { ThunkAction, ThunkDispatch } from "redux-thunk"
import { AnyAction } from "redux"
import { RootState } from "./reducer"
-import URL = require("url")
export enum ActionStatus {
Request, Success, Failure, Intermediate
@@ -50,7 +49,6 @@ export function setProxy(address = null) {
import ElectronProxyAgent = require("@yang991178/electron-proxy-agent")
import { ViewType } from "./models/page"
-import { RSSSource } from "./models/source"
let agent = new ElectronProxyAgent(remote.getCurrentWebContents().session)
export const rssParser = new Parser({
customFields: customFields,