diff --git a/src/components/article.tsx b/src/components/article.tsx index d6c57db..cba4845 100644 --- a/src/components/article.tsx +++ b/src/components/article.tsx @@ -109,6 +109,7 @@ class Article extends React.Component { webview.addEventListener("new-window", this.popUpHandler) webview.addEventListener("will-navigate", this.navigationHandler) this.webview = webview + webview.focus() } } componentDidUpdate = (prevProps: ArticleProps) => { diff --git a/src/components/menu.tsx b/src/components/menu.tsx index 56077e6..0972227 100644 --- a/src/components/menu.tsx +++ b/src/components/menu.tsx @@ -5,7 +5,7 @@ import { Nav, INavLink, INavLinkGroup } from "office-ui-fabric-react/lib/Nav" import { SourceGroup } from "../scripts/models/group" import { SourceState, RSSSource } from "../scripts/models/source" import { ALL } from "../scripts/models/feed" -import { AnimationClassNames, Stack } from "@fluentui/react" +import { AnimationClassNames, Stack, FocusZone, FocusZoneDirection } from "@fluentui/react" export type MenuProps = { status: boolean, @@ -26,7 +26,7 @@ export type MenuProps = { export class Menu extends React.Component { countOverflow = (count: number) => count >= 1000 ? "999+" : String(count) - getItems = (): INavLinkGroup[] => [ + getLinkGroups = (): INavLinkGroup[] => [ { links: [ { @@ -46,28 +46,28 @@ export class Menu extends React.Component { url: null } ] + }, + { + name: intl.get("menu.subscriptions"), + links: this.props.groups.filter(g => g.sids.length > 0).map((g, i) => { + if (g.isMultiple) { + let sources = g.sids.map(sid => this.props.sources[sid]) + return { + name: g.name, + ariaLabel: this.countOverflow(sources.map(s => s.unreadCount).reduce((a, b) => a + b, 0)), + key: "g-" + i, + url: null, + isExpanded: g.expanded, + onClick: () => this.props.selectSourceGroup(g, "g-" + i), + links: sources.map(this.getSource) + } + } else { + return this.getSource(this.props.sources[g.sids[0]]) + } + }) } ] - getGroups = (): INavLinkGroup[] => [{ - links: this.props.groups.filter(g => g.sids.length > 0).map((g, i) => { - if (g.isMultiple) { - let sources = g.sids.map(sid => this.props.sources[sid]) - return { - name: g.name, - ariaLabel: this.countOverflow(sources.map(s => s.unreadCount).reduce((a, b) => a + b, 0)), - key: "g-" + i, - url: null, - isExpanded: g.expanded, - onClick: () => this.props.selectSourceGroup(g, "g-" + i), - links: sources.map(this.getSource) - } - } else { - return this.getSource(this.props.sources[g.sids[0]]) - } - } - )}] - getSource = (s: RSSSource): INavLink => ({ name: s.name, ariaLabel: this.countOverflow(s.unreadCount), @@ -106,6 +106,10 @@ export class Menu extends React.Component { ) }; + _onRenderGroupHeader = (group: INavLinkGroup): JSX.Element => { + return

{group.name}

; + } + render() { return this.props.status && (
@@ -116,15 +120,11 @@ export class Menu extends React.Component {
diff --git a/src/scripts/i18n/zh-CN.json b/src/scripts/i18n/zh-CN.json index 953834e..874c9f8 100644 --- a/src/scripts/i18n/zh-CN.json +++ b/src/scripts/i18n/zh-CN.json @@ -56,7 +56,7 @@ "copyTitle": "复制标题", "copyURL": "复制链接", "copy": "复制", - "search": "使用Google搜索“{text}”", + "search": "使用 Google 搜索“{text}”", "view": "视图", "cardView": "卡片视图", "listView": "列表视图", diff --git a/src/scripts/models/item.ts b/src/scripts/models/item.ts index 7ee4c20..bb3c034 100644 --- a/src/scripts/models/item.ts +++ b/src/scripts/models/item.ts @@ -1,6 +1,6 @@ import * as db from "../db" import intl = require("react-intl-universal") -import { rssParser, domParser, htmlDecode, ActionStatus, AppThunk } from "../utils" +import { domParser, htmlDecode, ActionStatus, AppThunk } from "../utils" import { RSSSource } from "./source" import { FeedActionTypes, INIT_FEED, LOAD_MORE } from "./feed" import Parser = require("@yang991178/rss-parser") @@ -152,7 +152,7 @@ export function fetchItems(): AppThunk> { ((s.lastFetched ? s.lastFetched.getTime() : 0) + (s.fetchFrequency || 0) * 60000) <= timenow ) for (let source of sources) { - let promise = RSSSource.fetchItems(source, rssParser) + let promise = RSSSource.fetchItems(source) promise.finally(() => dispatch(fetchItemsIntermediate())) promises.push(promise) } diff --git a/src/scripts/models/source.ts b/src/scripts/models/source.ts index 3a3aed6..48cea54 100644 --- a/src/scripts/models/source.ts +++ b/src/scripts/models/source.ts @@ -1,7 +1,7 @@ import Parser = require("@yang991178/rss-parser") import intl = require("react-intl-universal") import * as db from "../db" -import { rssParser, fetchFavicon, ActionStatus, AppThunk, parseRSS } from "../utils" +import { fetchFavicon, ActionStatus, AppThunk, parseRSS } from "../utils" import { RSSItem, insertItems, ItemActionTypes, FETCH_ITEMS, MARK_READ, MARK_UNREAD, MARK_ALL_READ } from "./item" import { SourceGroup } from "./group" import { saveSettings } from "./app" @@ -28,16 +28,16 @@ export class RSSSource { this.lastFetched = new Date() } - async fetchMetaData(parser: Parser) { - let feed = await parseRSS(this.url) - if (!this.name) { - if (feed.title) this.name = feed.title.trim() - this.name = this.name || intl.get("sources.untitled") + static async fetchMetaData(source: RSSSource) { + let feed = await parseRSS(source.url) + if (!source.name) { + if (feed.title) source.name = feed.title.trim() + source.name = source.name || intl.get("sources.untitled") } - let domain = this.url.split("/").slice(0, 3).join("/") + let domain = source.url.split("/").slice(0, 3).join("/") try { let f = await fetchFavicon(domain) - if (f !== null) this.iconurl = f + if (f !== null) source.iconurl = f } finally { return feed } @@ -75,7 +75,7 @@ export class RSSSource { }) } - static async fetchItems(source: RSSSource, parser: Parser) { + static async fetchItems(source: RSSSource) { let feed = await parseRSS(source.url) db.sdb.update({ sid: source.sid }, { $set: { lastFetched: new Date() } }) return await this.checkItems(source, feed.items) @@ -236,7 +236,7 @@ export function addSource(url: string, name: string = null, batch = false): AppT if (app.sourceInit) { dispatch(addSourceRequest(batch)) let source = new RSSSource(url, name) - return source.fetchMetaData(rssParser) + return RSSSource.fetchMetaData(source) .then(feed => { return dispatch(insertSource(source)) .then(inserted => { diff --git a/src/scripts/settings.ts b/src/scripts/settings.ts index e18b513..23a85e2 100644 --- a/src/scripts/settings.ts +++ b/src/scripts/settings.ts @@ -1,6 +1,6 @@ import { remote, ipcRenderer } from "electron" import { ViewType } from "./models/page" -import { IPartialTheme, loadTheme, values } from "@fluentui/react" +import { IPartialTheme, loadTheme } from "@fluentui/react" import locales from "./i18n/_locales" import Store = require("electron-store") import { schemaTypes } from "./config-schema" @@ -51,7 +51,7 @@ export const setDefaultView = (viewType: ViewType) => { } const lightTheme: IPartialTheme = { - defaultFontStyle: { fontFamily: '"Source Han Sans SC Regular", "Microsoft YaHei", sans-serif' } + defaultFontStyle: { fontFamily: '"Segoe UI", "Source Han Sans SC Regular", "Microsoft YaHei", sans-serif' } } const darkTheme: IPartialTheme = { ...lightTheme, diff --git a/src/scripts/utils.ts b/src/scripts/utils.ts index 210ba64..d697d73 100644 --- a/src/scripts/utils.ts +++ b/src/scripts/utils.ts @@ -17,7 +17,7 @@ export type AppThunk = ThunkAction< export type AppDispatch = ThunkDispatch import Parser = require("@yang991178/rss-parser") -export const rssParser = new Parser({ +const rssParser = new Parser({ customFields: { item: ["thumb", "image", ["content:encoded", "fullContent"]] as Parser.CustomFieldItem[] }