From 430fdf1fd43f5cc4512a64721ff57ecb56e6badf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=B5=A9=E8=BF=9C?= Date: Sun, 7 Jun 2020 13:03:19 +0800 Subject: [PATCH] add actions to article --- dist/article/article.css | 12 +++- dist/article/article.html | 2 +- dist/article/article.js | 3 +- dist/article/preload.js | 2 +- dist/icons/fabric-icons-5-f95ba260.woff | Bin 0 -> 15492 bytes dist/styles.css | 20 +++++- src/components/article.tsx | 83 ++++++++++++++++++++++-- src/components/cards/card.tsx | 5 +- src/components/feeds/cards-feed.tsx | 3 +- src/components/feeds/feed.tsx | 2 +- src/components/nav.tsx | 4 +- src/components/page.tsx | 7 +- src/containers/article-container.tsx | 34 ++++++++++ src/containers/feed-container.tsx | 2 +- src/containers/nav-container.tsx | 11 +++- src/containers/page-container.tsx | 10 +-- src/index.html | 2 +- src/scripts/models/app.ts | 2 +- src/scripts/models/item.ts | 10 +-- src/scripts/models/page.ts | 13 ++-- 20 files changed, 177 insertions(+), 50 deletions(-) create mode 100644 dist/icons/fabric-icons-5-f95ba260.woff create mode 100644 src/containers/article-container.tsx diff --git a/dist/article/article.css b/dist/article/article.css index 06faa55..c333c78 100644 --- a/dist/article/article.css +++ b/dist/article/article.css @@ -1,7 +1,11 @@ html, body { font-family: "Segoe UI Regular", "Source Han Sans SC Regular", "Microsoft YaHei", sans-serif; - margin: 16px 48px; - overflow-x: hidden; +} +html { + overflow: hidden scroll; +} +body { + margin: 12px 96px 32px; } a { @@ -22,8 +26,10 @@ a:hover, a:active { article { line-height: 1.6; } -article img { +article > * { max-width: 100%; +} +article img { height: auto; } article figure { diff --git a/dist/article/article.html b/dist/article/article.html index 8314b32..086eb46 100644 --- a/dist/article/article.html +++ b/dist/article/article.html @@ -3,7 +3,7 @@ + content="default-src 'self'; img-src *; style-src 'self' 'unsafe-inline'; frame-src *; media-src *"> Hello World! diff --git a/dist/article/article.js b/dist/article/article.js index 86cd60f..1810a39 100644 --- a/dist/article/article.js +++ b/dist/article/article.js @@ -2,9 +2,10 @@ function get(name) { if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(location.search)) return decodeURIComponent(name[1]); } +document.documentElement.style.fontSize = get("s") + "px" let main = document.getElementById("main") main.innerHTML = decodeURIComponent(window.atob(get("h"))) document.addEventListener("click", event => { event.preventDefault() - if (event.target.href) ipcRenderer.sendToHost("request-navigation", event.target.href) + if (event.target.href) post("request-navigation", event.target.href) }) \ No newline at end of file diff --git a/dist/article/preload.js b/dist/article/preload.js index 82734e1..c15cd6d 100644 --- a/dist/article/preload.js +++ b/dist/article/preload.js @@ -1 +1 @@ -global.ipcRenderer = require("electron").ipcRenderer \ No newline at end of file +global.post = require("electron").ipcRenderer.sendToHost \ No newline at end of file diff --git a/dist/icons/fabric-icons-5-f95ba260.woff b/dist/icons/fabric-icons-5-f95ba260.woff new file mode 100644 index 0000000000000000000000000000000000000000..f403adfe69377b3844ccd3b8e38ebc0d1fa8bcef GIT binary patch literal 15492 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 literal 0 HcmV?d00001 diff --git a/dist/styles.css b/dist/styles.css index 6d69d31..d976e70 100644 --- a/dist/styles.css +++ b/dist/styles.css @@ -117,7 +117,7 @@ nav.menu-on .btn-group .btn, nav.hide-btns .btn-group .btn { nav.menu-on .btn-group .btn.system, nav.hide-btns .btn-group .btn.system { display: inline-block; } -nav.menu-on .btn-group .btn.system { +nav.menu-on .btn-group .btn.system, nav.item-on .btn-group .btn.system { color: #fff; } .btn-group .btn:hover { @@ -161,7 +161,6 @@ nav.menu-on .btn-group .btn.system { } .article-container { z-index: 6; - background-color: #fff6; } .menu-container .menu { position: absolute; @@ -273,6 +272,9 @@ img.favicon { nav.menu-on .btn-group .btn.system { color: #000; } + nav.item-on .btn-group .btn.system { + color: #fff; + } .menu-container { width: 280px; } @@ -313,9 +315,21 @@ img.favicon { } .article webview { width: 100%; - height: calc(100vh - 50px); + height: calc(100vh - 86px); border: none; } +.article i.ms-Icon { + color: #161514; +} +.article .actions { + border-bottom: 1px solid #e1dfdd; +} +.article .actions .favicon { + margin-right: 8px; +} +.article .actions .source-name { + line-height: 35px; +} .cards-feed-container { display: inline-flex; diff --git a/src/components/article.tsx b/src/components/article.tsx index f27a8e5..daf2dca 100644 --- a/src/components/article.tsx +++ b/src/components/article.tsx @@ -2,47 +2,122 @@ import * as React from "react" import { renderToString } from "react-dom/server" import { RSSItem } from "../scripts/models/item" import { openExternal } from "../scripts/utils" +import { Stack, CommandBarButton, IContextualMenuProps } from "@fluentui/react" +import { RSSSource } from "../scripts/models/source" + +const FONT_SIZE_STORE_KEY = "fontSize" +const FONT_SIZE_OPTIONS = [12, 13, 14, 15, 16, 17, 18, 19, 20] type ArticleProps = { item: RSSItem + source: RSSSource dismiss: () => void + toggleHasRead: (item: RSSItem) => void } -class Article extends React.Component { - webview: HTMLWebViewElement +type ArticleState = { + fontSize: number +} +class Article extends React.Component { + webview: HTMLWebViewElement + constructor(props) { super(props) + this.state = { + fontSize: this.getFontSize() + } } + getFontSize = () => { + let size = window.localStorage.getItem(FONT_SIZE_STORE_KEY) + return size ? parseInt(size) : 16 + } + setFontSize = (size: number) => { + window.localStorage.setItem(FONT_SIZE_STORE_KEY, String(size)) + this.setState({fontSize: size}) + } + + fontMenuProps = (): IContextualMenuProps => ({ + items: FONT_SIZE_OPTIONS.map(size => ({ + key: String(size), + text: String(size), + canCheck: true, + checked: size === this.state.fontSize, + onClick: () => this.setFontSize(size) + })) + }) + ipcHandler = event => { if (event.channel === "request-navigation") { openExternal(event.args[0]) } } + popUpHandler = event => { + openExternal(event.url) + } componentDidMount = () => { this.webview = document.getElementById("article") this.webview.addEventListener("ipc-message", this.ipcHandler) + this.webview.addEventListener("new-window", this.popUpHandler) this.webview.addEventListener("will-navigate", this.props.dismiss) } componentWillUnmount = () => { this.webview.removeEventListener("ipc-message", this.ipcHandler) + this.webview.removeEventListener("new-window", this.popUpHandler) this.webview.removeEventListener("will-navigate", this.props.dismiss) } + openInBrowser = () => { + openExternal(this.props.item.link) + } + articleView = () => "article/article.html?h=" + window.btoa(encodeURIComponent(renderToString(<>

{this.props.item.title}

- ))) + ))) + "&s=" + this.state.fontSize render = () => (
+ + + + + {this.props.source.iconurl && } + {this.props.source.name} + + this.props.toggleHasRead(this.props.item)} /> + + + + + + + + + preload="article/preload.js" + partition="sandbox" />
) } diff --git a/src/components/cards/card.tsx b/src/components/cards/card.tsx index 23dac05..61ddedb 100644 --- a/src/components/cards/card.tsx +++ b/src/components/cards/card.tsx @@ -6,12 +6,11 @@ import { FeedIdType } from "../../scripts/models/feed" export interface CardProps { feedId: FeedIdType - index: number item: RSSItem source: RSSSource markRead: (item: RSSItem) => void contextMenu: (item: RSSItem, e) => void - showItem: (fid: FeedIdType, index: number) => void + showItem: (fid: FeedIdType, item: RSSItem) => void } export class Card extends React.Component { @@ -24,7 +23,7 @@ export class Card extends React.Component { e.preventDefault() e.stopPropagation() this.props.markRead(this.props.item) - this.props.showItem(this.props.feedId, this.props.index) + this.props.showItem(this.props.feedId, this.props.item) } onMouseUp = (e: React.MouseEvent) => { diff --git a/src/components/feeds/cards-feed.tsx b/src/components/feeds/cards-feed.tsx index f5f4cf1..143f877 100644 --- a/src/components/feeds/cards-feed.tsx +++ b/src/components/feeds/cards-feed.tsx @@ -32,10 +32,9 @@ class CardsFeed extends Feed { return this.props.feed.loaded && (
{ - this.props.items.map((item, index) => ( + this.props.items.map((item) => ( void contextMenu: (item: RSSItem, e) => void loadMore: (feed: RSSFeed) => void - showItem: (fid: FeedIdType, index: number) => void + showItem: (fid: FeedIdType, item: RSSItem) => void } export class Feed extends React.Component { } \ No newline at end of file diff --git a/src/components/nav.tsx b/src/components/nav.tsx index 2d18731..92223e5 100644 --- a/src/components/nav.tsx +++ b/src/components/nav.tsx @@ -6,6 +6,7 @@ import { ProgressIndicator } from "@fluentui/react" type NavProps = { state: AppState, + itemShown: boolean, fetch: () => void, menu: () => void, logs: () => void, @@ -51,6 +52,7 @@ class Nav extends React.Component { canFetch = () => this.props.state.sourceInit && this.props.state.feedInit && !this.props.state.fetchingItems fetching = () => !this.canFetch() ? " fetching" : "" menuOn = () => this.props.state.menu ? " menu-on" : "" + itemOn = () => this.props.itemShown ? " item-on" : "" hideButtons = () => this.props.state.settings.display ? "hide-btns" : "" fetch = () => { @@ -65,7 +67,7 @@ class Nav extends React.Component { render() { return ( -
} - {this.props.item && ( + {this.props.itemId >= 0 && (
e.stopPropagation()}> -
+
)} diff --git a/src/containers/article-container.tsx b/src/containers/article-container.tsx new file mode 100644 index 0000000..6f41f66 --- /dev/null +++ b/src/containers/article-container.tsx @@ -0,0 +1,34 @@ +import { connect } from "react-redux" +import { createSelector } from "reselect" +import { RootState } from "../scripts/reducer" +import { RSSItem, markUnread, markRead } from "../scripts/models/item" +import { AppDispatch } from "../scripts/utils" +import { dismissItem } from "../scripts/models/page" +import Article from "../components/article" + +type ArticleContainerProps = { + itemId: number +} + +const getItem = (state: RootState, props: ArticleContainerProps) => state.items[props.itemId] +const getSource = (state: RootState, props: ArticleContainerProps) => state.sources[state.items[props.itemId].source] + +const makeMapStateToProps = () => { + return createSelector( + [getItem, getSource], + (item, source) => ({ + item: item, + source: source + }) + ) +} + +const mapDispatchToProps = (dispatch: AppDispatch) => { + return { + dismiss: () => dispatch(dismissItem()), + toggleHasRead: (item: RSSItem) => dispatch(item.hasRead ? markUnread(item) : markRead(item)) + } +} + +const ArticleContainer = connect(makeMapStateToProps, mapDispatchToProps)(Article) +export default ArticleContainer \ No newline at end of file diff --git a/src/containers/feed-container.tsx b/src/containers/feed-container.tsx index 5209cad..fc7a858 100644 --- a/src/containers/feed-container.tsx +++ b/src/containers/feed-container.tsx @@ -30,7 +30,7 @@ const mapDispatchToProps = dispatch => { markRead: (item: RSSItem) => dispatch(markRead(item)), contextMenu: (item: RSSItem, e) => dispatch(openItemMenu(item, e)), loadMore: (feed: RSSFeed) => dispatch(loadMore(feed)), - showItem: (fid: FeedIdType, index: number) => dispatch(showItem(fid, index)) + showItem: (fid: FeedIdType, item: RSSItem) => dispatch(showItem(fid, item)) } } diff --git a/src/containers/nav-container.tsx b/src/containers/nav-container.tsx index 7adc9e4..c2b7a2f 100644 --- a/src/containers/nav-container.tsx +++ b/src/containers/nav-container.tsx @@ -6,10 +6,15 @@ import { toggleMenu, toggleLogMenu, toggleSettings } from "../scripts/models/app import Nav from "../components/nav" const getState = (state: RootState) => state.app +const getItemShown = (state: RootState) => state.page.itemId >= 0 -const mapStateToProps = createSelector(getState, (state) => ({ - state: state -})) +const mapStateToProps = createSelector( + [getState, getItemShown], + (state, itemShown) => ({ + state: state, + itemShown: itemShown + } +)) const mapDispatchToProps = (dispatch) => ({ fetch: () => dispatch(fetchItems()), diff --git a/src/containers/page-container.tsx b/src/containers/page-container.tsx index 3368aa3..f770ca1 100644 --- a/src/containers/page-container.tsx +++ b/src/containers/page-container.tsx @@ -8,18 +8,14 @@ import { dismissItem } from "../scripts/models/page" const getPage = (state: RootState) => state.page const getSettings = (state: RootState) => state.app.settings.display const getMenu = (state: RootState) => state.app.menu -const getItems = (state: RootState) => state.items -const getFeeds = (state: RootState) => state.feeds const mapStateToProps = createSelector( - [getPage, getSettings, getMenu, getItems, getFeeds], - (page, settingsOn, menuOn, items, feeds) => ({ + [getPage, getSettings, getMenu], + (page, settingsOn, menuOn) => ({ feeds: [page.feedId], settingsOn: settingsOn, menuOn: menuOn, - item: page.itemIndex >= 0 // && page.itemIndex < feeds[page.feedId].iids.length - ? items[feeds[page.feedId].iids[page.itemIndex]] - : null + itemId: page.itemId }) ) diff --git a/src/index.html b/src/index.html index 0753f9e..0b72c16 100644 --- a/src/index.html +++ b/src/index.html @@ -2,7 +2,7 @@ - + Hello World! diff --git a/src/scripts/models/app.ts b/src/scripts/models/app.ts index bfc7490..e071b9b 100644 --- a/src/scripts/models/app.ts +++ b/src/scripts/models/app.ts @@ -193,7 +193,7 @@ export function appReducer( ...state, logMenu: { ...state.logMenu, - notify: true, + notify: !state.logMenu.display, logs: [...state.logMenu.logs, new AppLog( AppLogType.Failure, `无法加载订阅源“${action.errSource.name}”`, diff --git a/src/scripts/models/item.ts b/src/scripts/models/item.ts index 702760a..c3090da 100644 --- a/src/scripts/models/item.ts +++ b/src/scripts/models/item.ts @@ -199,18 +199,12 @@ export function itemReducer( } default: return state } + case MARK_UNREAD: case MARK_READ: return { ...state, [action.item.id] : { ...action.item, - hasRead: true - } - } - case MARK_UNREAD: return { - ...state, - [action.item.id] : { - ...action.item, - hasRead: false + hasRead: action.type === MARK_READ } } case LOAD_MORE: diff --git a/src/scripts/models/page.ts b/src/scripts/models/page.ts index 5a7fddc..e6d2f27 100644 --- a/src/scripts/models/page.ts +++ b/src/scripts/models/page.ts @@ -1,5 +1,6 @@ import { ALL, SOURCE, FeedIdType } from "./feed" import { getWindowBreakpoint } from "../utils" +import { RSSItem, ItemActionTypes, MARK_READ, MARK_UNREAD } from "./item" export const SELECT_PAGE = "SELECT_PAGE" export const SHOW_ITEM = "SHOW_ITEM" @@ -22,7 +23,7 @@ interface SelectPageAction { interface ShowItemAction { type: typeof SHOW_ITEM feedId: FeedIdType - itemIndex: number + item: RSSItem } interface DismissItemAction { type: typeof DISMISS_ITEM } @@ -50,11 +51,11 @@ export function selectSources(sids: number[], menuKey: string, title: string): P } } -export function showItem(feedId: FeedIdType, itemIndex: number): PageActionTypes { +export function showItem(feedId: FeedIdType, item: RSSItem): PageActionTypes { return { type: SHOW_ITEM, feedId: feedId, - itemIndex: itemIndex + item: item } } @@ -62,7 +63,7 @@ export const dismissItem = (): PageActionTypes => ({ type: DISMISS_ITEM }) export class PageState { feedId = ALL as FeedIdType - itemIndex = -1 + itemId = -1 } export function pageReducer( @@ -84,11 +85,11 @@ export function pageReducer( } case SHOW_ITEM: return { ...state, - itemIndex: action.itemIndex + itemId: action.item.id } case DISMISS_ITEM: return { ...state, - itemIndex: -1 + itemId: -1 } default: return state }