This commit is contained in:
刘浩远 2020-06-05 15:25:48 +08:00
parent 8debcfe7e4
commit 9bdcf4ea34
12 changed files with 78 additions and 54 deletions

Binary file not shown.

46
dist/styles.css vendored
View File

@ -1,11 +1,6 @@
@font-face {
font-family: "Source Han Sans";
src: url("SourceHanSansSC-Regular.otf");
}
html, body { html, body {
background-color: #faf9f8; background-color: #faf9f8;
font-family: "Source Han Sans", sans-serif; font-family: "Source Han Sans SC Regular", "Microsoft YaHei", sans-serif;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
margin: 0; margin: 0;
@ -101,12 +96,15 @@ i.ms-Nav-chevron {
position: relative; position: relative;
z-index: 10; z-index: 10;
} }
nav.hide-btns .btn-group .btn { nav.menu-on .btn-group .btn, nav.hide-btns .btn-group .btn {
display: none; display: none;
} }
nav.hide-btns .btn-group .btn.system { nav.menu-on .btn-group .btn.system, nav.hide-btns .btn-group .btn.system {
display: inline-block; display: inline-block;
} }
.btn-group .btn.system.menu-on {
color: #fff;
}
.btn-group .btn:hover { .btn-group .btn:hover {
background-color: #0001; background-color: #0001;
} }
@ -132,8 +130,8 @@ nav.hide-btns .btn-group .btn.system {
background-color: #f1707a; background-color: #f1707a;
color: #fff; color: #fff;
} }
.btn-group .btn.system.on { .btn-group .btn.inline-block-wide {
color: #fff; display: none;
} }
.menu-container { .menu-container {
@ -242,6 +240,34 @@ img.favicon {
z-index: 1; z-index: 1;
} }
@media (min-width: 1721px) {
#root > nav.menu-on {
padding-left: 296px;
}
nav.menu-on .btn-group .btn {
display: inline-block;
}
.btn-group .btn.system.menu-on {
color: #000;
}
.menu-container {
width: 280px;
}
.menu-container .menu {
background-color: #edebe9;
}
.main.menu-on {
padding-left: 280px;
}
nav.menu-on .btn-group .btn.hide-wide, .menu .btn-group .btn.hide-wide {
display: none;
}
.btn-group .btn.inline-block-wide {
display: inline-block;
}
}
.cards-feed-container { .cards-feed-container {
display: inline-flex; display: inline-flex;
flex-wrap: wrap; flex-wrap: wrap;

View File

@ -1,18 +1,17 @@
import * as React from "react" import * as React from "react"
import { Icon } from "@fluentui/react/lib/Icon" import { Icon } from "@fluentui/react/lib/Icon"
import { Nav, INavLink, INavLinkGroup } from "office-ui-fabric-react/lib/Nav" import { Nav, INavLink, INavLinkGroup } from "office-ui-fabric-react/lib/Nav"
import { MenuStatus } from "../scripts/models/app"
import { SourceGroup } from "../scripts/models/page" import { SourceGroup } from "../scripts/models/page"
import { SourceState, RSSSource } from "../scripts/models/source" import { SourceState, RSSSource } from "../scripts/models/source"
import { ALL } from "../scripts/models/feed" import { ALL } from "../scripts/models/feed"
import { AnimationClassNames } from "@fluentui/react" import { AnimationClassNames } from "@fluentui/react"
export type MenuProps = { export type MenuProps = {
status: MenuStatus, status: boolean,
selected: string, selected: string,
sources: SourceState, sources: SourceState,
groups: SourceGroup[], groups: SourceGroup[],
closeMenu: () => void, toggleMenu: () => void,
allArticles: () => void, allArticles: () => void,
selectSourceGroup: (group: SourceGroup, menuKey: string) => void, selectSourceGroup: (group: SourceGroup, menuKey: string) => void,
selectSource: (source: RSSSource) => void selectSource: (source: RSSSource) => void
@ -74,11 +73,12 @@ export class Menu extends React.Component<MenuProps> {
}) })
render() { render() {
return this.props.status == MenuStatus.Hidden ? null : ( return this.props.status ? (
<div className="menu-container" onClick={this.props.closeMenu}> <div className="menu-container" onClick={this.props.toggleMenu}>
<div className="menu" onClick={(e) => e.stopPropagation()}> <div className="menu" onClick={(e) => e.stopPropagation()}>
<div className="btn-group"> <div className="btn-group">
<a className="btn" title="关闭菜单" onClick={this.props.closeMenu}><Icon iconName="Back" /></a> <a className="btn hide-wide" title="关闭菜单" onClick={this.props.toggleMenu}><Icon iconName="Back" /></a>
<a className="btn inline-block-wide" title="关闭菜单" onClick={this.props.toggleMenu}><Icon iconName="GlobalNavButton" /></a>
</div> </div>
<div className="nav-wrapper"> <div className="nav-wrapper">
<Nav <Nav
@ -91,6 +91,6 @@ export class Menu extends React.Component<MenuProps> {
</div> </div>
</div> </div>
</div> </div>
) ) : null
} }
} }

View File

@ -1,7 +1,7 @@
import * as React from "react" import * as React from "react"
import { ipcRenderer, remote } from "electron" import { ipcRenderer, remote } from "electron"
import { Icon } from "@fluentui/react/lib/Icon" import { Icon } from "@fluentui/react/lib/Icon"
import { AppState, MenuStatus } from "../scripts/models/app" import { AppState } from "../scripts/models/app"
type NavProps = { type NavProps = {
state: AppState, state: AppState,
@ -49,8 +49,8 @@ class Nav extends React.Component<NavProps, NavState> {
canFetch = () => this.props.state.sourceInit && this.props.state.feedInit && !this.props.state.fetchingItems canFetch = () => this.props.state.sourceInit && this.props.state.feedInit && !this.props.state.fetchingItems
fetching = () => !this.canFetch() ? " fetching" : "" fetching = () => !this.canFetch() ? " fetching" : ""
menuOn = () => this.props.state.menu == MenuStatus.Open ? " on" : "" menuOn = () => this.props.state.menu ? " menu-on" : ""
hideButtons = () => (this.props.state.menu == MenuStatus.Open || this.props.state.settings.display) ? "hide-btns" : "" hideButtons = () => this.props.state.settings.display ? "hide-btns" : ""
fetch = () => { fetch = () => {
if (this.canFetch()) this.props.fetch() if (this.canFetch()) this.props.fetch()
@ -58,9 +58,9 @@ class Nav extends React.Component<NavProps, NavState> {
render() { render() {
return ( return (
<nav className={this.hideButtons()}> <nav className={this.hideButtons() + this.menuOn()}>
<div className="btn-group"> <div className="btn-group">
<a className="btn" title="菜单" onClick={this.props.menu}><Icon iconName="GlobalNavButton" /></a> <a className="btn hide-wide" title="菜单" onClick={this.props.menu}><Icon iconName="GlobalNavButton" /></a>
</div> </div>
<span className="title">{this.props.state.title}</span> <span className="title">{this.props.state.title}</span>
<div className="btn-group" style={{float:"right"}}> <div className="btn-group" style={{float:"right"}}>

View File

@ -3,6 +3,7 @@ import { FeedIdType } from "../scripts/models/feed"
import { FeedContainer } from "../containers/feed-container" import { FeedContainer } from "../containers/feed-container"
type PageProps = { type PageProps = {
menuOn: boolean
settingsOn: boolean settingsOn: boolean
feeds: FeedIdType[] feeds: FeedIdType[]
} }
@ -11,7 +12,7 @@ class Page extends React.Component<PageProps> {
render = () => ( render = () => (
<> <>
{this.props.settingsOn ? null : {this.props.settingsOn ? null :
<div className="main"> <div className={"main" + (this.props.menuOn ? " menu-on" : "")}>
{this.props.feeds.map(fid => ( {this.props.feeds.map(fid => (
<FeedContainer feedId={fid} key={fid} /> <FeedContainer feedId={fid} key={fid} />
))} ))}

View File

@ -2,12 +2,12 @@ import { connect } from "react-redux"
import { createSelector } from "reselect" import { createSelector } from "reselect"
import { RootState } from "../scripts/reducer" import { RootState } from "../scripts/reducer"
import { Menu } from "../components/menu" import { Menu } from "../components/menu"
import { closeMenu } from "../scripts/models/app" import { toggleMenu } from "../scripts/models/app"
import { selectAllArticles, selectSources, SourceGroup } from "../scripts/models/page" import { selectAllArticles, selectSources, SourceGroup } from "../scripts/models/page"
import { initFeeds } from "../scripts/models/feed" import { initFeeds } from "../scripts/models/feed"
import { RSSSource } from "../scripts/models/source" import { RSSSource } from "../scripts/models/source"
const getStatus = (state: RootState) => state.app.menu const getStatus = (state: RootState) => state.app.menu && state.app.sourceInit
const getKey = (state: RootState) => state.app.menuKey const getKey = (state: RootState) => state.app.menuKey
const getSources = (state: RootState) => state.sources const getSources = (state: RootState) => state.sources
const getGroups = (state: RootState) => state.page.sourceGroups const getGroups = (state: RootState) => state.page.sourceGroups
@ -23,7 +23,7 @@ const mapStateToProps = createSelector(
) )
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
closeMenu: () => dispatch(closeMenu()), toggleMenu: () => dispatch(toggleMenu()),
allArticles: () => { allArticles: () => {
dispatch(selectAllArticles()), dispatch(selectAllArticles()),
dispatch(initFeeds()) dispatch(initFeeds())

View File

@ -2,7 +2,7 @@ import { connect } from "react-redux"
import { createSelector } from "reselect" import { createSelector } from "reselect"
import { RootState } from "../scripts/reducer" import { RootState } from "../scripts/reducer"
import { fetchItems } from "../scripts/models/item" import { fetchItems } from "../scripts/models/item"
import { openMenu, toggleLogMenu, toggleSettings } from "../scripts/models/app" import { toggleMenu, toggleLogMenu, toggleSettings } from "../scripts/models/app"
import Nav from "../components/nav" import Nav from "../components/nav"
const getState = (state: RootState) => state.app const getState = (state: RootState) => state.app
@ -13,7 +13,7 @@ const mapStateToProps = createSelector(getState, (state) => ({
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
fetch: () => dispatch(fetchItems()), fetch: () => dispatch(fetchItems()),
menu: () => dispatch(openMenu()), menu: () => dispatch(toggleMenu()),
logs: () => dispatch(toggleLogMenu()), logs: () => dispatch(toggleLogMenu()),
settings: () => dispatch(toggleSettings()) settings: () => dispatch(toggleSettings())
}) })

View File

@ -5,12 +5,14 @@ import Page from "../components/page"
const getFeeds = (state: RootState) => state.page.feedId const getFeeds = (state: RootState) => state.page.feedId
const getSettings = (state: RootState) => state.app.settings.display const getSettings = (state: RootState) => state.app.settings.display
const getMenu = (state: RootState) => state.app.menu
const mapStateToProps = createSelector( const mapStateToProps = createSelector(
[getFeeds, getSettings], [getFeeds, getSettings, getMenu],
(feeds, settingsOn) => ({ (feeds, settingsOn, menuOn) => ({
feeds: [feeds], feeds: [feeds],
settingsOn: settingsOn settingsOn: settingsOn,
menuOn: menuOn
}) })
) )

View File

@ -14,7 +14,7 @@ import { AppDispatch, setProxy } from "./scripts/utils"
setProxy() setProxy()
loadTheme({ defaultFontStyle: { fontFamily: '"Source Han Sans", sans-serif' } }) loadTheme({ defaultFontStyle: { fontFamily: '"Source Han Sans SC Regular", "Microsoft YaHei", sans-serif' } })
initializeIcons("icons/") initializeIcons("icons/")
const store = createStore( const store = createStore(

View File

@ -1,6 +1,6 @@
import { RSSSource, INIT_SOURCES, SourceActionTypes, ADD_SOURCE, UPDATE_SOURCE, DELETE_SOURCE } from "./source" import { RSSSource, INIT_SOURCES, SourceActionTypes, ADD_SOURCE, UPDATE_SOURCE, DELETE_SOURCE } from "./source"
import { RSSItem, ItemActionTypes, FETCH_ITEMS, fetchItems } from "./item" import { RSSItem, ItemActionTypes, FETCH_ITEMS } from "./item"
import { ActionStatus, AppThunk } from "../utils" import { ActionStatus, AppThunk, getWindowBreakpoint } from "../utils"
import { INIT_FEEDS, FeedActionTypes, ALL, initFeeds } from "./feed" import { INIT_FEEDS, FeedActionTypes, ALL, initFeeds } from "./feed"
import { PageActionTypes, SELECT_PAGE, PageType, selectAllArticles, SourceGroupActionTypes, UPDATE_SOURCE_GROUP, ADD_SOURCE_TO_GROUP, DELETE_SOURCE_GROUP, REMOVE_SOURCE_FROM_GROUP } from "./page" import { PageActionTypes, SELECT_PAGE, PageType, selectAllArticles, SourceGroupActionTypes, UPDATE_SOURCE_GROUP, ADD_SOURCE_TO_GROUP, DELETE_SOURCE_GROUP, REMOVE_SOURCE_FROM_GROUP } from "./page"
@ -8,10 +8,6 @@ export enum ContextMenuType {
Hidden, Item Hidden, Item
} }
export enum MenuStatus {
Hidden, Open, Pinned
}
export enum AppLogType { export enum AppLogType {
Info, Warning, Failure Info, Warning, Failure
} }
@ -34,7 +30,7 @@ export class AppState {
sourceInit = false sourceInit = false
feedInit = false feedInit = false
fetchingItems = false fetchingItems = false
menu = MenuStatus.Hidden menu = getWindowBreakpoint()
menuKey = ALL menuKey = ALL
title = "全部文章" title = "全部文章"
settings = { settings = {
@ -79,11 +75,10 @@ export type ContextMenuActionTypes = CloseContextMenuAction | OpenItemMenuAction
export const TOGGLE_LOGS = "TOGGLE_LOGS" export const TOGGLE_LOGS = "TOGGLE_LOGS"
export interface LogMenuActionType { type: typeof TOGGLE_LOGS } export interface LogMenuActionType { type: typeof TOGGLE_LOGS }
export const OPEN_MENU = "OPEN_MENU" export const TOGGLE_MENU = "TOGGLE_MENU"
export const CLOSE_MENU = "CLOSE_MENU"
export interface MenuActionTypes { export interface MenuActionTypes {
type: typeof OPEN_MENU | typeof CLOSE_MENU type: typeof TOGGLE_MENU
} }
export const TOGGLE_SETTINGS = "TOGGLE_SETTINGS" export const TOGGLE_SETTINGS = "TOGGLE_SETTINGS"
@ -105,8 +100,7 @@ export function openItemMenu(item: RSSItem, event: React.MouseEvent): ContextMen
} }
} }
export const openMenu = () => ({ type: OPEN_MENU }) export const toggleMenu = () => ({ type: TOGGLE_MENU })
export const closeMenu = () => ({ type: CLOSE_MENU })
export const toggleLogMenu = () => ({ type: TOGGLE_LOGS }) export const toggleLogMenu = () => ({ type: TOGGLE_LOGS })
export const toggleSettings = () => ({ type: TOGGLE_SETTINGS }) export const toggleSettings = () => ({ type: TOGGLE_SETTINGS })
export const saveSettings = () => ({ type: SAVE_SETTINGS }) export const saveSettings = () => ({ type: SAVE_SETTINGS })
@ -218,13 +212,13 @@ export function appReducer(
switch (action.pageType) { switch (action.pageType) {
case PageType.AllArticles: return { case PageType.AllArticles: return {
...state, ...state,
menu: MenuStatus.Hidden, menu: state.menu && action.keepMenu,
menuKey: ALL, menuKey: ALL,
title: "全部文章" title: "全部文章"
} }
case PageType.Sources: return { case PageType.Sources: return {
...state, ...state,
menu: MenuStatus.Hidden, menu: state.menu && action.keepMenu,
menuKey: action.menuKey, menuKey: action.menuKey,
title: action.title title: action.title
} }
@ -243,13 +237,9 @@ export function appReducer(
target: action.item target: action.item
} }
} }
case OPEN_MENU: return { case TOGGLE_MENU: return {
...state, ...state,
menu: MenuStatus.Open menu: !state.menu
}
case CLOSE_MENU: return {
...state,
menu: MenuStatus.Hidden
} }
case SAVE_SETTINGS: return { case SAVE_SETTINGS: return {
...state, ...state,

View File

@ -1,7 +1,7 @@
import fs = require("fs") import fs = require("fs")
import { SourceActionTypes, ADD_SOURCE, DELETE_SOURCE, addSource } from "./source" import { SourceActionTypes, ADD_SOURCE, DELETE_SOURCE, addSource } from "./source"
import { ALL, SOURCE } from "./feed" import { ALL, SOURCE } from "./feed"
import { ActionStatus, AppThunk, domParser, AppDispatch } from "../utils" import { ActionStatus, AppThunk, domParser, AppDispatch, getWindowBreakpoint } from "../utils"
import { saveSettings } from "./app" import { saveSettings } from "./app"
const GROUPS_STORE_KEY = "sourceGroups" const GROUPS_STORE_KEY = "sourceGroups"
@ -43,6 +43,7 @@ interface SelectPageAction {
type: typeof SELECT_PAGE type: typeof SELECT_PAGE
pageType: PageType pageType: PageType
init: boolean init: boolean
keepMenu: boolean
sids?: number[] sids?: number[]
menuKey?: string menuKey?: string
title?: string title?: string
@ -53,6 +54,7 @@ export type PageActionTypes = SelectPageAction
export function selectAllArticles(init = false): SelectPageAction { export function selectAllArticles(init = false): SelectPageAction {
return { return {
type: SELECT_PAGE, type: SELECT_PAGE,
keepMenu: getWindowBreakpoint(),
pageType: PageType.AllArticles, pageType: PageType.AllArticles,
init: init init: init
} }
@ -62,6 +64,7 @@ export function selectSources(sids: number[], menuKey: string, title: string) {
return { return {
type: SELECT_PAGE, type: SELECT_PAGE,
pageType: PageType.Sources, pageType: PageType.Sources,
keepMenu: getWindowBreakpoint(),
sids: sids, sids: sids,
menuKey: menuKey, menuKey: menuKey,
title: title, title: title,

View File

@ -81,3 +81,5 @@ export function openExternal(url: string) {
export const urlTest = (s: string) => export const urlTest = (s: string) =>
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/gi.test(s) /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/gi.test(s)
export const getWindowBreakpoint = () => remote.getCurrentWindow().getSize()[0] >= 1721